DemoKit: Add support for handling connect/disconnect

Close the file descriptor when the accessory is disconnected.
Also disable and reset the control widgets when the accessory is reset.

Change-Id: Ifcdedac091428891aeb11cf43ea49b4d8fe77775
Signed-off-by: Mike Lockwood <lockwood@android.com>
diff --git a/demokit/app/AndroidManifest.xml b/demokit/app/AndroidManifest.xml
index 22dadd6..d873887 100644
--- a/demokit/app/AndroidManifest.xml
+++ b/demokit/app/AndroidManifest.xml
@@ -19,7 +19,7 @@
       android:versionCode="1"
       android:versionName="1.0">
 
-  <uses-sdk android:targetSdkVersion="11"></uses-sdk>
+  <uses-sdk android:targetSdkVersion="11" />
 
     <application android:label="DemoKit"
             android:icon="@drawable/icon"
@@ -32,15 +32,19 @@
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.LAUNCHER" />
             </intent-filter>
+        </activity>
 
-	    <intent-filter>
+        <!-- This activity receives USB_ACCESSORY_ATTACHED Intents and springboards to main Gallery activity. -->
+        <activity android:name="UsbAccessoryActivity" android:label="DemoKit"
+                android:taskAffinity=""
+                android:launchMode="singleInstance">
+            <intent-filter>
                 <action android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED" />
             </intent-filter>
 
             <meta-data android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED"
                 android:resource="@xml/accessory_filter" />
-
-
         </activity>
+
     </application>
 </manifest>
diff --git a/demokit/app/src/com/google/DemoKit/DemoKitActivity.java b/demokit/app/src/com/google/DemoKit/DemoKitActivity.java
index b9f3636..338276f 100644
--- a/demokit/app/src/com/google/DemoKit/DemoKitActivity.java
+++ b/demokit/app/src/com/google/DemoKit/DemoKitActivity.java
@@ -54,6 +54,7 @@
     private PendingIntent mPermissionIntent;
     private boolean mPermissionRequestPending;
 
+    UsbAccessory mAccessory;
     ParcelFileDescriptor mFileDescriptor;
     FileInputStream mInputStream;
     FileOutputStream mOutputStream;
@@ -158,7 +159,8 @@
    private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
-            if (ACTION_USB_PERMISSION.equals(intent.getAction())) {
+            String action = intent.getAction();
+            if (ACTION_USB_PERMISSION.equals(action)) {
                 synchronized (this) {
                     UsbAccessory accessory = UsbManager.getAccessory(intent);
                     if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
@@ -168,6 +170,11 @@
                     }
                     mPermissionRequestPending = false;
                 }
+            } else if (UsbManager.ACTION_USB_ACCESSORY_DETACHED.equals(action)) {
+                UsbAccessory accessory = UsbManager.getAccessory(intent);
+                if (accessory != null && accessory.equals(mAccessory)) {
+                    closeAccessory();
+                }
             }
         }
     };
@@ -180,6 +187,7 @@
         mUsbManager = UsbManager.getInstance(this);
         mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
         IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
+        filter.addAction(UsbManager.ACTION_USB_ACCESSORY_DETACHED);
         registerReceiver(mUsbReceiver, filter);
 
         setContentView(R.layout.main);
@@ -229,9 +237,10 @@
 
         mCap = (ImageView)findViewById(R.id.cap);
 
-        mSwitchOff =   getResources().getDrawable(R.drawable.droid_off);
+        mSwitchOff = getResources().getDrawable(R.drawable.droid_off);
         mSwitchOn = getResources().getDrawable(R.drawable.droid_on);
 
+        enableControls(false);
     }
 
     @Override
@@ -261,14 +270,7 @@
     @Override
     public void onPause() {
         super.onPause();
-        if (mFileDescriptor != null) {
-            try {
-                mFileDescriptor.close();
-            } catch (IOException e) {
-            } finally {
-                mFileDescriptor = null;
-            }
-        }
+        closeAccessory();
     }
 
     @Override
@@ -281,17 +283,73 @@
         Log.d(TAG, "openAccessory: " + accessory);
         mFileDescriptor = mUsbManager.openAccessory(accessory);
         if (mFileDescriptor != null) {
+            mAccessory = accessory;
             FileDescriptor fd = mFileDescriptor.getFileDescriptor();
             mInputStream = new FileInputStream(fd);
             mOutputStream = new FileOutputStream(fd);
             Thread thread = new Thread(null, this, "AccessoryChat");
             thread.start();
             Log.d(TAG, "openAccessory succeeded");
+            enableControls(true);
         } else {
             Log.d(TAG, "openAccessory fail");
         }
     }
 
+    private void closeAccessory() {
+        enableControls(false);
+
+        mButton1Image.setImageDrawable(mSwitchOff);
+        mButton2Image.setImageDrawable(mSwitchOff);
+        mButton3Image.setImageDrawable(mSwitchOff);
+        mCap.setImageDrawable(mSwitchOff);
+        mLed1Red.setProgress(0);
+        mLed1Green.setProgress(0);
+        mLed1Blue.setProgress(0);
+        mLed2Red.setProgress(0);
+        mLed2Green.setProgress(0);
+        mLed2Blue.setProgress(0);
+        mLed3Red.setProgress(0);
+        mLed3Green.setProgress(0);
+        mLed3Blue.setProgress(0);
+        mServo1.setProgress(0);
+        mServo2.setProgress(0);
+        mServo3.setProgress(0);
+        mTemperature.setText("");
+        mLight.setText("");
+        mJoyX.setText("");
+        mJoyY.setText("");
+        mRelay1Button.setChecked(false);
+        mRelay2Button.setChecked(false);
+
+        try {
+            if (mFileDescriptor != null) {
+                mFileDescriptor.close();
+            }
+        } catch (IOException e) {
+        } finally {
+            mFileDescriptor = null;
+            mAccessory = null;
+        }
+    }
+
+    private void enableControls(boolean enable) {
+        mLed1Red.setEnabled(enable);
+        mLed1Green.setEnabled(enable);
+        mLed1Blue.setEnabled(enable);
+        mLed2Red.setEnabled(enable);
+        mLed2Green.setEnabled(enable);
+        mLed2Blue.setEnabled(enable);
+        mLed3Red.setEnabled(enable);
+        mLed3Green.setEnabled(enable);
+        mLed3Blue.setEnabled(enable);
+        mServo1.setEnabled(enable);
+        mServo2.setEnabled(enable);
+        mServo3.setEnabled(enable);
+        mRelay1Button.setEnabled(enable);
+        mRelay2Button.setEnabled(enable);
+    }
+
     private int composeInt(byte hi, byte lo) {
         int val = (int)hi & 0xff;
         val *= 256;
@@ -401,9 +459,6 @@
         };
 
     public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
-        if (mOutputStream == null)
-            return;
-
         byte[] buffer = new byte[3];
         if (progress > 255)
             progress = 255;
@@ -454,9 +509,6 @@
     }
 
     public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
-        if (mOutputStream == null)
-            return;
-
         byte[] buffer = new byte[3];
         buffer[0] = 0x3;
         buffer[1] = -1;
diff --git a/demokit/app/src/com/google/DemoKit/UsbAccessoryActivity.java b/demokit/app/src/com/google/DemoKit/UsbAccessoryActivity.java
new file mode 100644
index 0000000..d451e38
--- /dev/null
+++ b/demokit/app/src/com/google/DemoKit/UsbAccessoryActivity.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2011 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.google.DemoKit;
+
+
+import android.app.Activity;
+import android.content.ActivityNotFoundException;
+import android.content.Intent;
+import android.os.Bundle;
+import android.util.Log;
+
+/* This Activity does nothing but receive USB_DEVICE_ATTACHED events from the
+ * USB service and springboards to the main Gallery activity
+ */
+public final class UsbAccessoryActivity extends Activity {
+
+    static final String TAG = "UsbAccessoryActivity";
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        Intent intent = new Intent(this, DemoKitActivity.class);
+        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
+        try {
+            startActivity(intent);
+        } catch (ActivityNotFoundException e) {
+            Log.e(TAG, "unable to start DemoKit activity", e);
+        }
+        finish();
+    }
+}