1/*
2 * Copyright (C) 2011 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
17package com.android.accessorychat;
18
19import android.app.Activity;
20import android.app.PendingIntent;
21import android.content.BroadcastReceiver;
22import android.content.Context;
23import android.content.Intent;
24import android.content.IntentFilter;
25import android.os.Bundle;
26import android.os.Handler;
27import android.os.Message;
28import android.os.ParcelFileDescriptor;
29import android.view.KeyEvent;
30import android.view.View;
31import android.view.inputmethod.EditorInfo;
32import android.util.Log;
33import android.widget.EditText;
34import android.widget.TextView;
35
36import android.hardware.usb.UsbManager;
37import android.hardware.usb.UsbAccessory;
38
39import java.io.FileDescriptor;
40import java.io.FileInputStream;
41import java.io.FileOutputStream;
42import java.io.IOException;
43
44public class AccessoryChat extends Activity implements Runnable, TextView.OnEditorActionListener {
45
46    private static final String TAG = "AccessoryChat";
47
48    private static final String ACTION_USB_PERMISSION =
49            "com.android.accessorychat.action.USB_PERMISSION";
50
51    private TextView mLog;
52    private EditText mEditText;
53    private ParcelFileDescriptor mFileDescriptor;
54    private FileInputStream mInputStream;
55    private FileOutputStream mOutputStream;
56    private UsbManager mUsbManager;
57    private PendingIntent mPermissionIntent;
58    private boolean mPermissionRequestPending;
59
60    private static final int MESSAGE_LOG = 1;
61
62   private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
63        @Override
64        public void onReceive(Context context, Intent intent) {
65            if (ACTION_USB_PERMISSION.equals(intent.getAction())) {
66                synchronized (this) {
67                    UsbAccessory accessory = (UsbAccessory) intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
68                    if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
69                        if (accessory != null) {
70                            openAccessory(accessory);
71                        }
72                    } else {
73                        Log.d(TAG, "permission denied for accessory " + accessory);
74                    }
75                    mPermissionRequestPending = false;
76                }
77            }
78        }
79    };
80
81    @Override
82    public void onCreate(Bundle savedInstanceState) {
83        super.onCreate(savedInstanceState);
84
85        mUsbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
86        mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
87        IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
88        registerReceiver(mUsbReceiver, filter);
89
90        setContentView(R.layout.accessory_chat);
91        mLog = (TextView)findViewById(R.id.log);
92        mEditText = (EditText)findViewById(R.id.message);
93        mEditText.setOnEditorActionListener(this);
94    }
95
96    @Override
97    public void onResume() {
98        super.onResume();
99
100        Intent intent = getIntent();
101        Log.d(TAG, "intent: " + intent);
102        UsbAccessory[] accessories = mUsbManager.getAccessoryList();
103        UsbAccessory accessory = (accessories == null ? null : accessories[0]);
104        if (accessory != null) {
105            if (mUsbManager.hasPermission(accessory)) {
106                openAccessory(accessory);
107            } else {
108                synchronized (mUsbReceiver) {
109                    if (!mPermissionRequestPending) {
110                        mUsbManager.requestPermission(accessory, mPermissionIntent);
111                        mPermissionRequestPending = true;
112                    }
113                }
114            }
115         } else {
116            Log.d(TAG, "mAccessory is null");
117        }
118    }
119
120    @Override
121    public void onPause() {
122        super.onPause();
123        if (mFileDescriptor != null) {
124            try {
125                mFileDescriptor.close();
126            } catch (IOException e) {
127            } finally {
128                mFileDescriptor = null;
129            }
130        }
131    }
132
133    @Override
134    public void onDestroy() {
135        unregisterReceiver(mUsbReceiver);
136       super.onDestroy();
137    }
138
139    private void openAccessory(UsbAccessory accessory) {
140        Log.d(TAG, "openAccessory: " + accessory);
141        mFileDescriptor = mUsbManager.openAccessory(accessory);
142        if (mFileDescriptor != null) {
143            FileDescriptor fd = mFileDescriptor.getFileDescriptor();
144            mInputStream = new FileInputStream(fd);
145            mOutputStream = new FileOutputStream(fd);
146            Thread thread = new Thread(null, this, "AccessoryChat");
147            thread.start();
148            Log.d(TAG, "openAccessory succeeded");
149        } else {
150            Log.d(TAG, "openAccessory fail");
151        }
152    }
153
154    public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
155        if (actionId == EditorInfo.IME_ACTION_DONE && mOutputStream != null) {
156            try {
157                mOutputStream.write(v.getText().toString().getBytes());
158            } catch (IOException e) {
159                Log.e(TAG, "write failed", e);
160            }
161            v.setText("");
162            return true;
163        }
164        Log.d(TAG, "onEditorAction " + actionId + " event: " + event);
165        return false;
166    }
167
168    public void run() {
169        int ret = 0;
170        byte[] buffer = new byte[16384];
171        while (ret >= 0) {
172            try {
173                ret = mInputStream.read(buffer);
174            } catch (IOException e) {
175                break;
176            }
177
178            if (ret > 0) {
179                Message m = Message.obtain(mHandler, MESSAGE_LOG);
180                String text = new String(buffer, 0, ret);
181                Log.d(TAG, "chat: " + text);
182                m.obj = text;
183                mHandler.sendMessage(m);
184            }
185        }
186        Log.d(TAG, "thread out");
187    }
188
189   Handler mHandler = new Handler() {
190        @Override
191        public void handleMessage(Message msg) {
192            switch (msg.what) {
193                case MESSAGE_LOG:
194                    mLog.setText(mLog.getText() + "\n" + (String)msg.obj);
195                    break;
196             }
197        }
198    };
199}
200
201
202