Hardware Android

//
//src\com\android\adb\AdbDevice.java
/*
 * 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.android.adb;
import android.hardware.usb.UsbConstants;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbEndpoint;
import android.hardware.usb.UsbInterface;
import android.hardware.usb.UsbRequest;
import android.util.SparseArray;
import java.util.LinkedList;
/* This class represents a USB device that supports the adb protocol. */
public class AdbDevice {
    private final AdbTestActivity mActivity;
    private final UsbDeviceConnection mDeviceConnection;
    private final UsbEndpoint mEndpointOut;
    private final UsbEndpoint mEndpointIn;
    private String mSerial;
    // pool of requests for the OUT endpoint
    private final LinkedList mOutRequestPool = new LinkedList();
    // pool of requests for the IN endpoint
    private final LinkedList mInRequestPool = new LinkedList();
    // list of currently opened sockets
    private final SparseArray mSockets = new SparseArray();
    private int mNextSocketId = 1;
    private final WaiterThread mWaiterThread = new WaiterThread();
    public AdbDevice(AdbTestActivity activity, UsbDeviceConnection connection,
            UsbInterface intf) {
        mActivity = activity;
        mDeviceConnection = connection;
        mSerial = connection.getSerial();
        UsbEndpoint epOut = null;
        UsbEndpoint epIn = null;
        // look for our bulk endpoints
        for (int i = 0; i < intf.getEndpointCount(); i++) {
            UsbEndpoint ep = intf.getEndpoint(i);
            if (ep.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK) {
                if (ep.getDirection() == UsbConstants.USB_DIR_OUT) {
                    epOut = ep;
                } else {
                    epIn = ep;
                }
            }
        }
        if (epOut == null || epIn == null) {
            throw new IllegalArgumentException("not all endpoints found");
        }
        mEndpointOut = epOut;
        mEndpointIn = epIn;
    }
    // return device serial number
    public String getSerial() {
        return mSerial;
    }
    // get an OUT request from our pool
    public UsbRequest getOutRequest() {
        synchronized(mOutRequestPool) {
            if (mOutRequestPool.isEmpty()) {
                UsbRequest request = new UsbRequest();
                request.initialize(mDeviceConnection, mEndpointOut);
                return request;
            } else {
                return mOutRequestPool.removeFirst();
            }
        }
    }
    // return an OUT request to the pool
    public void releaseOutRequest(UsbRequest request) {
        synchronized (mOutRequestPool) {
            mOutRequestPool.add(request);
        }
    }
    // get an IN request from the pool
    public UsbRequest getInRequest() {
        synchronized(mInRequestPool) {
            if (mInRequestPool.isEmpty()) {
                UsbRequest request = new UsbRequest();
                request.initialize(mDeviceConnection, mEndpointIn);
                return request;
            } else {
                return mInRequestPool.removeFirst();
            }
        }
    }
    public void start() {
        mWaiterThread.start();
        connect();
    }
    public AdbSocket openSocket(String destination) {
        AdbSocket socket;
        synchronized (mSockets) {
            int id = mNextSocketId++;
            socket = new AdbSocket(this, id);
            mSockets.put(id, socket);
        }
        if (socket.open(destination)) {
            return socket;
        } else {
            return null;
        }
    }
    private AdbSocket getSocket(int id) {
        synchronized (mSockets) {
            return mSockets.get(id);
        }
    }
    public void socketClosed(AdbSocket socket) {
        synchronized (mSockets) {
            mSockets.remove(socket.getId());
        }
    }
    // send a connect command
    private void connect() {
        AdbMessage message = new AdbMessage();
        message.set(AdbMessage.A_CNXN, AdbMessage.A_VERSION, AdbMessage.MAX_PAYLOAD, "host::\0");
        message.write(this);
    }
    // handle connect response
    private void handleConnect(AdbMessage message) {
        if (message.getDataString().startsWith("device:")) {
            log("connected");
            mActivity.deviceOnline(this);
        }
    }
    public void stop() {
        synchronized (mWaiterThread) {
            mWaiterThread.mStop = true;
        }
    }
    // dispatch a message from the device
    void dispatchMessage(AdbMessage message) {
        int command = message.getCommand();
        switch (command) {
            case AdbMessage.A_SYNC:
                log("got A_SYNC");
                break;
            case AdbMessage.A_CNXN:
                handleConnect(message);
                break;
            case AdbMessage.A_OPEN:
            case AdbMessage.A_OKAY:
            case AdbMessage.A_CLSE:
            case AdbMessage.A_WRTE:
                AdbSocket socket = getSocket(message.getArg1());
                if (socket == null) {
                    log("ERROR socket not found");
                } else {
                    socket.handleMessage(message);
                }
                break;
        }
    }
    void log(String s) {
        mActivity.log(s);
    }
    private class WaiterThread extends Thread {
        public boolean mStop;
        public void run() {
            // start out with a command read
            AdbMessage currentCommand = new AdbMessage();
            AdbMessage currentData = null;
            // FIXME error checking
            currentCommand.readCommand(getInRequest());
            while (true) {
                synchronized (this) {
                    if (mStop) {
                        return;
                    }
                }
                UsbRequest request = mDeviceConnection.requestWait();
                if (request == null) {
                    break;
                }
                AdbMessage message = (AdbMessage)request.getClientData();
                request.setClientData(null);
                AdbMessage messageToDispatch = null;
                if (message == currentCommand) {
                    int dataLength = message.getDataLength();
                    // read data if length > 0
                    if (dataLength > 0) {
                        message.readData(getInRequest(), dataLength);
                        currentData = message;
                    } else {
                        messageToDispatch = message;
                    }
                    currentCommand = null;
                } else if (message == currentData) {
                    messageToDispatch = message;
                    currentData = null;
                }
                if (messageToDispatch != null) {
                    // queue another read first
                    currentCommand = new AdbMessage();
                    currentCommand.readCommand(getInRequest());
                    // then dispatch the current message
                    dispatchMessage(messageToDispatch);
                }
                // put request back into the appropriate pool
                if (request.getEndpoint() == mEndpointOut) {
                    releaseOutRequest(request);
                } else {
                    synchronized (mInRequestPool) {
                        mInRequestPool.add(request);
                    }
                }
            }
        }
    }
}
//src\com\android\adb\AdbMessage.java
/*
 * 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.android.adb;
import android.hardware.usb.UsbRequest;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
/* This class encapsulates and adb command packet */
public class AdbMessage {
    // command names
    public static final int A_SYNC = 0x434e5953;
    public static final int A_CNXN = 0x4e584e43;
    public static final int A_OPEN = 0x4e45504f;
    public static final int A_OKAY = 0x59414b4f;
    public static final int A_CLSE = 0x45534c43;
    public static final int A_WRTE = 0x45545257;
    // ADB protocol version
    public static final int A_VERSION = 0x01000000;
    public static final int MAX_PAYLOAD = 4096;
    private final ByteBuffer mMessageBuffer;
    private final ByteBuffer mDataBuffer;
    public AdbMessage() {
        mMessageBuffer = ByteBuffer.allocate(24);
        mDataBuffer = ByteBuffer.allocate(MAX_PAYLOAD);
        mMessageBuffer.order(ByteOrder.LITTLE_ENDIAN);
        mDataBuffer.order(ByteOrder.LITTLE_ENDIAN);
    }
    // sets the fields in the command header
    public void set(int command, int arg0, int arg1, byte[] data) {
        mMessageBuffer.putInt(0, command);
        mMessageBuffer.putInt(4, arg0);
        mMessageBuffer.putInt(8, arg1);
        mMessageBuffer.putInt(12, (data == null ? 0 : data.length));
        mMessageBuffer.putInt(16, (data == null ? 0 : checksum(data)));
        mMessageBuffer.putInt(20, command ^ 0xFFFFFFFF);
        if (data != null) {
            mDataBuffer.put(data, 0, data.length);
        }
    }
    public void set(int command, int arg0, int arg1) {
        set(command, arg0, arg1, (byte[])null);
    }
    public void set(int command, int arg0, int arg1, String data) {
        // add trailing zero
        data += "\0";
        set(command, arg0, arg1, data.getBytes());
    }
    // returns the command's message ID
    public int getCommand() {
        return mMessageBuffer.getInt(0);
    }
    // returns command's first argument
    public int getArg0() {
        return mMessageBuffer.getInt(4);
    }
    // returns command's second argument
    public int getArg1() {
        return mMessageBuffer.getInt(8);
    }
    // returns command's data buffer
    public ByteBuffer getData() {
        return mDataBuffer;
    }
    // returns command's data length
    public int getDataLength() {
        return mMessageBuffer.getInt(12);
    }
    // returns command's data as a string
    public String getDataString() {
        int length = getDataLength();
        if (length == 0) return null;
        // trim trailing zero
        return new String(mDataBuffer.array(), 0, length - 1);
    }
    public boolean write(AdbDevice device) {
        synchronized (device) {
            UsbRequest request = device.getOutRequest();
            request.setClientData(this);
            if (request.queue(mMessageBuffer, 24)) {
                int length = getDataLength();
                if (length > 0) {
                    request = device.getOutRequest();
                    request.setClientData(this);
                    if (request.queue(mDataBuffer, length)) {
                        return true;
                    } else {
                        device.releaseOutRequest(request);
                        return false;
                    }
                }
                return true;
            } else {
                device.releaseOutRequest(request);
                return false;
            }
        }
    }
    public boolean readCommand(UsbRequest request) {
        request.setClientData(this);
        return request.queue(mMessageBuffer, 24);
    }
    public boolean readData(UsbRequest request, int length) {
        request.setClientData(this);
        return request.queue(mDataBuffer, length);
    }
    private static String extractString(ByteBuffer buffer, int offset, int length) {
        byte[] bytes = new byte[length];
        for (int i = 0; i < length; i++) {
            bytes[i] = buffer.get(offset++);
        }
        return new String(bytes);
    }
    @Override
    public String toString() {
        String commandName = extractString(mMessageBuffer, 0, 4);
        int dataLength = getDataLength();
        String result = "Adb Message: " + commandName + " arg0: " + getArg0() +
             " arg1: " + getArg1() + " dataLength: " + dataLength;
        if (dataLength > 0) {
            result += (" data: \"" + getDataString() + "\"");
        }
        return result;
    }
    private static int checksum(byte[] data) {
        int result = 0;
        for (int i = 0; i < data.length; i++) {
            int x = data[i];
            // dang, no unsigned ints in java
            if (x < 0) x += 256;
            result += x;
        }
        return result;
    }
}
//src\com\android\adb\AdbSocket.java
/*
 * 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.android.adb;
/* This class represents an adb socket.  adb supports multiple independent
 * socket connections to a single device.  Typically a socket is created
 * for each adb command that is executed.
 */
public class AdbSocket {
    private final AdbDevice mDevice;
    private final int mId;
    private int mPeerId;
    public AdbSocket(AdbDevice device, int id) {
        mDevice = device;
        mId = id;
    }
    public int getId() {
        return mId;
    }
    public boolean open(String destination) {
        AdbMessage message = new AdbMessage();
        message.set(AdbMessage.A_OPEN, mId, 0, destination);
        if (! message.write(mDevice)) {
            return false;
        }
        synchronized (this) {
            try {
                wait();
            } catch (InterruptedException e) {
                return false;
            }
        }
        return true;
    }
    public void handleMessage(AdbMessage message) {
        switch (message.getCommand()) {
            case AdbMessage.A_OKAY:
                mPeerId = message.getArg0();
                synchronized (this) {
                    notify();
                }
                break;
            case AdbMessage.A_WRTE:
                mDevice.log(message.getDataString());
                sendReady();
                break;
        }
    }
    private void sendReady() {
        AdbMessage message = new AdbMessage();
        message.set(AdbMessage.A_OKAY, mId, mPeerId);
        message.write(mDevice);
    }
}
//src\com\android\adb\AdbTestActivity.java
/*
 * 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.android.adb;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Rect;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbInterface;
import android.hardware.usb.UsbManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.TextView;
/* Main activity for the adb test program */
public class AdbTestActivity extends Activity {
    private static final String TAG = "AdbTestActivity";
    private TextView mLog;
    private UsbManager mManager;
    private UsbDevice mDevice;
    private UsbDeviceConnection mDeviceConnection;
    private UsbInterface mInterface;
    private AdbDevice mAdbDevice;
    private static final int MESSAGE_LOG = 1;
    private static final int MESSAGE_DEVICE_ONLINE = 2;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.adb);
        mLog = (TextView)findViewById(R.id.log);
        mManager = (UsbManager)getSystemService(Context.USB_SERVICE);
        // check for existing devices
        for (UsbDevice device :  mManager.getDeviceList().values()) {
            UsbInterface intf = findAdbInterface(device);
            if (setAdbInterface(device, intf)) {
                break;
            }
        }
        // listen for new devices
        IntentFilter filter = new IntentFilter();
        filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
        filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
        registerReceiver(mUsbReceiver, filter);
    }
    @Override
    public void onDestroy() {
        unregisterReceiver(mUsbReceiver);
        setAdbInterface(null, null);
        super.onDestroy();
    }
    public void log(String s) {
        Message m = Message.obtain(mHandler, MESSAGE_LOG);
        m.obj = s;
        mHandler.sendMessage(m);
    }
    private void appendLog(String text) {
        Rect r = new Rect();
        mLog.getDrawingRect(r);
        int maxLines = r.height() / mLog.getLineHeight() - 1;
        text = mLog.getText() + "\n" + text;
        // see how many lines we have
        int index = text.lastIndexOf('\n');
        int count = 0;
        while (index > 0 && count <= maxLines) {
            count++;
            index = text.lastIndexOf('\n', index - 1);
        }
        // truncate to maxLines
        if (index > 0) {
            text = text.substring(index + 1);
        }
        mLog.setText(text);
    }
    public void deviceOnline(AdbDevice device) {
        Message m = Message.obtain(mHandler, MESSAGE_DEVICE_ONLINE);
        m.obj = device;
        mHandler.sendMessage(m);
    }
    private void handleDeviceOnline(AdbDevice device) {
        log("device online: " + device.getSerial());
        device.openSocket("shell:exec logcat");
    }
    // Sets the current USB device and interface
    private boolean setAdbInterface(UsbDevice device, UsbInterface intf) {
        if (mDeviceConnection != null) {
            if (mInterface != null) {
                mDeviceConnection.releaseInterface(mInterface);
                mInterface = null;
            }
            mDeviceConnection.close();
            mDevice = null;
            mDeviceConnection = null;
        }
        if (device != null && intf != null) {
            UsbDeviceConnection connection = mManager.openDevice(device);
            if (connection != null) {
                log("open succeeded");
                if (connection.claimInterface(intf, false)) {
                    log("claim interface succeeded");
                    mDevice = device;
                    mDeviceConnection = connection;
                    mInterface = intf;
                    mAdbDevice = new AdbDevice(this, mDeviceConnection, intf);
                    log("call start");
                    mAdbDevice.start();
                    return true;
                } else {
                    log("claim interface failed");
                    connection.close();
                }
            } else {
                log("open failed");
            }
        }
        if (mDeviceConnection == null && mAdbDevice != null) {
            mAdbDevice.stop();
            mAdbDevice = null;
        }
        return false;
    }
    // searches for an adb interface on the given USB device
    static private UsbInterface findAdbInterface(UsbDevice device) {
        Log.d(TAG, "findAdbInterface " + device);
        int count = device.getInterfaceCount();
        for (int i = 0; i < count; i++) {
            UsbInterface intf = device.getInterface(i);
            if (intf.getInterfaceClass() == 255 && intf.getInterfaceSubclass() == 66 &&
                    intf.getInterfaceProtocol() == 1) {
                return intf;
            }
        }
        return null;
    }
    BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action)) {
                UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
                UsbInterface intf = findAdbInterface(device);
                if (intf != null) {
                    log("Found adb interface " + intf);
                    setAdbInterface(device, intf);
                }
            } else if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)) {
                UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
                String deviceName = device.getDeviceName();
                if (mDevice != null && mDevice.equals(deviceName)) {
                    log("adb interface removed");
                    setAdbInterface(null, null);
                }
            }
        }
    };
    Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MESSAGE_LOG:
                    appendLog((String)msg.obj);
                    break;
                case MESSAGE_DEVICE_ONLINE:
                    handleDeviceOnline((AdbDevice)msg.obj);
                    break;
            }
        }
    };
}
//
//res\layout\adb.xml


    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    >
            android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginTop="25dp"
        android:textSize="18sp"
        android:textColor="#ffffffff"
        />

//
//res\xml\device_filter.xml