127555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood/*
227555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood * Copyright (C) 2011 The Android Open Source Project
327555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood *
427555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood * Licensed under the Apache License, Version 2.0 (the "License");
527555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood * you may not use this file except in compliance with the License.
627555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood * You may obtain a copy of the License at
727555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood *
827555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood *      http://www.apache.org/licenses/LICENSE-2.0
927555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood *
1027555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood * Unless required by applicable law or agreed to in writing, software
1127555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood * distributed under the License is distributed on an "AS IS" BASIS,
1227555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1327555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood * See the License for the specific language governing permissions and
1427555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood * limitations under the License.
1527555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood */
1627555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood
17b547fc297f24ce2d74fc86ef2a79a4424b6b4c59Mike Lockwoodpackage com.android.accessorychat;
1827555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood
1927555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwoodimport android.app.Activity;
20580b64111788fd312697d4fe60017127877dadf4Mike Lockwoodimport android.app.PendingIntent;
2127555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwoodimport android.content.BroadcastReceiver;
2227555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwoodimport android.content.Context;
2327555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwoodimport android.content.Intent;
24580b64111788fd312697d4fe60017127877dadf4Mike Lockwoodimport android.content.IntentFilter;
2527555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwoodimport android.os.Bundle;
2627555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwoodimport android.os.Handler;
2727555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwoodimport android.os.Message;
2827555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwoodimport android.os.ParcelFileDescriptor;
2927555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwoodimport android.view.KeyEvent;
3027555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwoodimport android.view.View;
3127555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwoodimport android.view.inputmethod.EditorInfo;
3227555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwoodimport android.util.Log;
3327555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwoodimport android.widget.EditText;
3427555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwoodimport android.widget.TextView;
3527555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood
36c92e6f14f9ac6c86b7784f8a21d7077ea7cae0bbSimon Wilsonimport android.hardware.usb.UsbManager;
37c92e6f14f9ac6c86b7784f8a21d7077ea7cae0bbSimon Wilsonimport android.hardware.usb.UsbAccessory;
3827555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood
3927555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwoodimport java.io.FileDescriptor;
4027555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwoodimport java.io.FileInputStream;
4127555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwoodimport java.io.FileOutputStream;
4227555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwoodimport java.io.IOException;
4327555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood
4427555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwoodpublic class AccessoryChat extends Activity implements Runnable, TextView.OnEditorActionListener {
4527555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood
4627555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood    private static final String TAG = "AccessoryChat";
47580b64111788fd312697d4fe60017127877dadf4Mike Lockwood
48580b64111788fd312697d4fe60017127877dadf4Mike Lockwood    private static final String ACTION_USB_PERMISSION =
49580b64111788fd312697d4fe60017127877dadf4Mike Lockwood            "com.android.accessorychat.action.USB_PERMISSION";
50580b64111788fd312697d4fe60017127877dadf4Mike Lockwood
51580b64111788fd312697d4fe60017127877dadf4Mike Lockwood    private TextView mLog;
52580b64111788fd312697d4fe60017127877dadf4Mike Lockwood    private EditText mEditText;
53580b64111788fd312697d4fe60017127877dadf4Mike Lockwood    private ParcelFileDescriptor mFileDescriptor;
54580b64111788fd312697d4fe60017127877dadf4Mike Lockwood    private FileInputStream mInputStream;
55580b64111788fd312697d4fe60017127877dadf4Mike Lockwood    private FileOutputStream mOutputStream;
56580b64111788fd312697d4fe60017127877dadf4Mike Lockwood    private UsbManager mUsbManager;
57580b64111788fd312697d4fe60017127877dadf4Mike Lockwood    private PendingIntent mPermissionIntent;
58580b64111788fd312697d4fe60017127877dadf4Mike Lockwood    private boolean mPermissionRequestPending;
5927555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood
6027555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood    private static final int MESSAGE_LOG = 1;
6127555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood
62580b64111788fd312697d4fe60017127877dadf4Mike Lockwood   private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
63580b64111788fd312697d4fe60017127877dadf4Mike Lockwood        @Override
64580b64111788fd312697d4fe60017127877dadf4Mike Lockwood        public void onReceive(Context context, Intent intent) {
65580b64111788fd312697d4fe60017127877dadf4Mike Lockwood            if (ACTION_USB_PERMISSION.equals(intent.getAction())) {
66580b64111788fd312697d4fe60017127877dadf4Mike Lockwood                synchronized (this) {
67c92e6f14f9ac6c86b7784f8a21d7077ea7cae0bbSimon Wilson                    UsbAccessory accessory = (UsbAccessory) intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
68580b64111788fd312697d4fe60017127877dadf4Mike Lockwood                    if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
69c92e6f14f9ac6c86b7784f8a21d7077ea7cae0bbSimon Wilson                        if (accessory != null) {
70c92e6f14f9ac6c86b7784f8a21d7077ea7cae0bbSimon Wilson                            openAccessory(accessory);
71c92e6f14f9ac6c86b7784f8a21d7077ea7cae0bbSimon Wilson                        }
72580b64111788fd312697d4fe60017127877dadf4Mike Lockwood                    } else {
73580b64111788fd312697d4fe60017127877dadf4Mike Lockwood                        Log.d(TAG, "permission denied for accessory " + accessory);
74580b64111788fd312697d4fe60017127877dadf4Mike Lockwood                    }
75580b64111788fd312697d4fe60017127877dadf4Mike Lockwood                    mPermissionRequestPending = false;
76580b64111788fd312697d4fe60017127877dadf4Mike Lockwood                }
77580b64111788fd312697d4fe60017127877dadf4Mike Lockwood            }
78580b64111788fd312697d4fe60017127877dadf4Mike Lockwood        }
79580b64111788fd312697d4fe60017127877dadf4Mike Lockwood    };
80580b64111788fd312697d4fe60017127877dadf4Mike Lockwood
8127555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood    @Override
8227555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood    public void onCreate(Bundle savedInstanceState) {
8327555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood        super.onCreate(savedInstanceState);
8427555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood
85c92e6f14f9ac6c86b7784f8a21d7077ea7cae0bbSimon Wilson        mUsbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
86580b64111788fd312697d4fe60017127877dadf4Mike Lockwood        mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
87580b64111788fd312697d4fe60017127877dadf4Mike Lockwood        IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
88580b64111788fd312697d4fe60017127877dadf4Mike Lockwood        registerReceiver(mUsbReceiver, filter);
89580b64111788fd312697d4fe60017127877dadf4Mike Lockwood
9027555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood        setContentView(R.layout.accessory_chat);
9127555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood        mLog = (TextView)findViewById(R.id.log);
9227555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood        mEditText = (EditText)findViewById(R.id.message);
9327555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood        mEditText.setOnEditorActionListener(this);
9427555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood    }
9527555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood
9627555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood    @Override
9727555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood    public void onResume() {
9827555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood        super.onResume();
9927555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood
10027555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood        Intent intent = getIntent();
10127555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood        Log.d(TAG, "intent: " + intent);
102580b64111788fd312697d4fe60017127877dadf4Mike Lockwood        UsbAccessory[] accessories = mUsbManager.getAccessoryList();
10327555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood        UsbAccessory accessory = (accessories == null ? null : accessories[0]);
10427555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood        if (accessory != null) {
105580b64111788fd312697d4fe60017127877dadf4Mike Lockwood            if (mUsbManager.hasPermission(accessory)) {
106580b64111788fd312697d4fe60017127877dadf4Mike Lockwood                openAccessory(accessory);
10727555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood            } else {
108580b64111788fd312697d4fe60017127877dadf4Mike Lockwood                synchronized (mUsbReceiver) {
109580b64111788fd312697d4fe60017127877dadf4Mike Lockwood                    if (!mPermissionRequestPending) {
110580b64111788fd312697d4fe60017127877dadf4Mike Lockwood                        mUsbManager.requestPermission(accessory, mPermissionIntent);
111580b64111788fd312697d4fe60017127877dadf4Mike Lockwood                        mPermissionRequestPending = true;
112580b64111788fd312697d4fe60017127877dadf4Mike Lockwood                    }
113580b64111788fd312697d4fe60017127877dadf4Mike Lockwood                }
11427555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood            }
115580b64111788fd312697d4fe60017127877dadf4Mike Lockwood         } else {
11627555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood            Log.d(TAG, "mAccessory is null");
11727555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood        }
11827555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood    }
11927555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood
12027555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood    @Override
12127555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood    public void onPause() {
12227555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood        super.onPause();
12327555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood        if (mFileDescriptor != null) {
12427555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood            try {
12527555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood                mFileDescriptor.close();
12627555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood            } catch (IOException e) {
12727555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood            } finally {
12827555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood                mFileDescriptor = null;
12927555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood            }
13027555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood        }
13127555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood    }
13227555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood
13327555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood    @Override
13427555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood    public void onDestroy() {
135580b64111788fd312697d4fe60017127877dadf4Mike Lockwood        unregisterReceiver(mUsbReceiver);
13627555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood       super.onDestroy();
13727555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood    }
13827555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood
139580b64111788fd312697d4fe60017127877dadf4Mike Lockwood    private void openAccessory(UsbAccessory accessory) {
140015b1ecaec27b7cf5f1a78099d9ae34a0c3169f2Mike Lockwood        Log.d(TAG, "openAccessory: " + accessory);
141015b1ecaec27b7cf5f1a78099d9ae34a0c3169f2Mike Lockwood        mFileDescriptor = mUsbManager.openAccessory(accessory);
142580b64111788fd312697d4fe60017127877dadf4Mike Lockwood        if (mFileDescriptor != null) {
143580b64111788fd312697d4fe60017127877dadf4Mike Lockwood            FileDescriptor fd = mFileDescriptor.getFileDescriptor();
144580b64111788fd312697d4fe60017127877dadf4Mike Lockwood            mInputStream = new FileInputStream(fd);
145580b64111788fd312697d4fe60017127877dadf4Mike Lockwood            mOutputStream = new FileOutputStream(fd);
146580b64111788fd312697d4fe60017127877dadf4Mike Lockwood            Thread thread = new Thread(null, this, "AccessoryChat");
147580b64111788fd312697d4fe60017127877dadf4Mike Lockwood            thread.start();
148580b64111788fd312697d4fe60017127877dadf4Mike Lockwood            Log.d(TAG, "openAccessory succeeded");
149580b64111788fd312697d4fe60017127877dadf4Mike Lockwood        } else {
150580b64111788fd312697d4fe60017127877dadf4Mike Lockwood            Log.d(TAG, "openAccessory fail");
151580b64111788fd312697d4fe60017127877dadf4Mike Lockwood        }
152580b64111788fd312697d4fe60017127877dadf4Mike Lockwood    }
153580b64111788fd312697d4fe60017127877dadf4Mike Lockwood
15427555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood    public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
15527555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood        if (actionId == EditorInfo.IME_ACTION_DONE && mOutputStream != null) {
15627555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood            try {
15727555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood                mOutputStream.write(v.getText().toString().getBytes());
15827555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood            } catch (IOException e) {
15927555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood                Log.e(TAG, "write failed", e);
16027555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood            }
16127555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood            v.setText("");
16227555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood            return true;
16327555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood        }
16427555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood        Log.d(TAG, "onEditorAction " + actionId + " event: " + event);
16527555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood        return false;
16627555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood    }
16727555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood
16827555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood    public void run() {
16927555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood        int ret = 0;
17027555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood        byte[] buffer = new byte[16384];
17127555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood        while (ret >= 0) {
17227555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood            try {
17327555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood                ret = mInputStream.read(buffer);
17427555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood            } catch (IOException e) {
17527555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood                break;
17627555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood            }
17727555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood
17827555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood            if (ret > 0) {
17927555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood                Message m = Message.obtain(mHandler, MESSAGE_LOG);
18027555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood                String text = new String(buffer, 0, ret);
18127555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood                Log.d(TAG, "chat: " + text);
18227555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood                m.obj = text;
18327555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood                mHandler.sendMessage(m);
18427555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood            }
18527555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood        }
18627555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood        Log.d(TAG, "thread out");
18727555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood    }
18827555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood
18927555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood   Handler mHandler = new Handler() {
19027555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood        @Override
19127555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood        public void handleMessage(Message msg) {
19227555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood            switch (msg.what) {
19327555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood                case MESSAGE_LOG:
19427555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood                    mLog.setText(mLog.getText() + "\n" + (String)msg.obj);
19527555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood                    break;
19627555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood             }
19727555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood        }
19827555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood    };
19927555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood}
20027555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood
20127555315629ffce59a19bd03ba51a8323cc864b0Mike Lockwood
202