diff --git a/app/src/main/java/com/android/trongvu/atcommander/ExecuteAsRootBase.java b/app/src/main/java/com/android/trongvu/atcommander/ExecuteAsRootBase.java new file mode 100644 index 0000000..436805f --- /dev/null +++ b/app/src/main/java/com/android/trongvu/atcommander/ExecuteAsRootBase.java @@ -0,0 +1,139 @@ +package com.android.trongvu.atcommander; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; + +import android.util.Log; + +public class ExecuteAsRootBase +{ + public static String TAG = ExecuteAsRootBase.class.getSimpleName(); + public static boolean canRunRootCommands() + { + boolean retval = false; + Process suProcess; + + try + { + suProcess = Runtime.getRuntime().exec("su"); + + DataOutputStream os = new DataOutputStream(suProcess.getOutputStream()); + DataInputStream osRes = new DataInputStream(suProcess.getInputStream()); + + if (null != os && null != osRes) + { + // Getting the id of the current user to check if this is root + os.writeBytes("id\n"); + os.flush(); + + String currUid = osRes.readLine(); + Log.d(TAG, "currUid = " + currUid); + boolean exitSu = false; + if (null == currUid) + { + retval = false; + exitSu = false; + Log.d(TAG, "Can't get root access or denied by user"); + } + else if (true == currUid.contains("uid=0")) + { + retval = true; + exitSu = true; + Log.d(TAG, "Root access granted"); + } + else + { + retval = false; + exitSu = true; + Log.d(TAG, "Root access rejected: " + currUid); + } + + if (exitSu) + { + os.writeBytes("exit\n"); + os.flush(); + } + } + suProcess.waitFor(); + } + catch (Exception e) + { + // Can't get root ! + // Probably broken pipe exception on trying to write to output stream (os) after su failed, meaning that the device is not rooted + + retval = false; + Log.d(TAG, "Root access rejected [" + e.getClass().getName() + "] : " + e.getMessage()); + } + + return retval; + } + + public static final boolean execute() + { + boolean retval = false; + + try + { + ArrayList commands = getCommandsToExecute(); + if (null != commands && commands.size() > 0) + { + Process suProcess = Runtime.getRuntime().exec("su"); + + DataOutputStream os = new DataOutputStream(suProcess.getOutputStream()); + + // Execute commands that require root access + for (String currCommand : commands) + { + os.writeBytes(currCommand + "\n"); + os.flush(); + } + + os.writeBytes("exit\n"); + os.flush(); + + try + { + int suProcessRetval = suProcess.waitFor(); + if (255 != suProcessRetval) + { + // Root access granted + retval = true; + } + else + { + // Root access denied + retval = false; + } + } + catch (Exception ex) + { + Log.e(TAG, "Error executing root action", ex); + } + } + } + catch (IOException ex) + { + Log.w(TAG, "Can't get root access", ex); + } + catch (SecurityException ex) + { + Log.w(TAG, "Can't get root access", ex); + } + catch (Exception ex) + { + Log.w(TAG, "Error executing internal operation", ex); + } + + return retval; + } + protected static ArrayList getCommandsToExecute() { + // TODO Auto-generated method stub + // by default, if there is no input value for configuration_switch, + // Apple device will use configuration #4 and Samsung device will use configuration #2 + String [] commands = new String[] {"configuration_switch"}; + return new ArrayList(Arrays.asList(commands)); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/android/trongvu/atcommander/MainActivity.java b/app/src/main/java/com/android/trongvu/atcommander/MainActivity.java index 78a48b7..c7d4805 100644 --- a/app/src/main/java/com/android/trongvu/atcommander/MainActivity.java +++ b/app/src/main/java/com/android/trongvu/atcommander/MainActivity.java @@ -1,12 +1,5 @@ package com.android.trongvu.atcommander; -import java.util.HashMap; -import java.util.Iterator; - -import com.example.androidshell.R; -import com.felhr.usbserial.UsbSerialDevice; -import com.felhr.usbserial.UsbSerialInterface; - import android.app.Activity; import android.app.PendingIntent; import android.content.BroadcastReceiver; @@ -28,16 +21,65 @@ import android.widget.TextView; import android.widget.Toast; +import com.example.androidshell.R; +import com.felhr.usbserial.UsbSerialDevice; +import com.felhr.usbserial.UsbSerialInterface; + +import java.util.HashMap; +import java.util.Iterator; + public class MainActivity extends Activity { + public static final String ACTION_USB_PERMISSION = "com.android.trongvu.atcommander.USB_PERMISSION"; + public static final String LOG_TAG = "ATCommander"; + private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() { + + public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); + if (ACTION_USB_PERMISSION.equals(action)) { + UsbDevice dev = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE); + if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) { + connectUSBDevice(dev); + } else { + Log.d(LOG_TAG, "permission denied for accessory " + dev); + } + } + } + }; EditText input; Button btn; TextView out; ScrollView mScrollView; String command; + UsbDevice dev = null; + UsbDeviceConnection mUsbDeviceConnection = null; + UsbManager mUsbManager = null; + Handler mHandler = new Handler(); + UsbSerialDevice serialPort = null; private PendingIntent mPermissionIntent; - public static final String ACTION_USB_PERMISSION = "com.android.trongvu.atcommander.USB_PERMISSION"; - public static final String LOG_TAG = "ATCommander"; + private boolean isConnected = false; + private UsbSerialInterface.UsbReadCallback mCallback = new UsbSerialInterface.UsbReadCallback() { + @Override + public void onReceivedData(final byte[] arg0) { + mHandler.post(new Runnable() { + @Override + public void run() { + // TODO Auto-generated method stub + out.append(new String(arg0) + "\n"); + } + }); + // we could not scroll till the end right after set text + // so we wait for 100ms before scrolling + mHandler.postDelayed(new Runnable() { + @Override + public void run() { + // TODO Auto-generated method stub + mScrollView.fullScroll(ScrollView.FOCUS_DOWN); + } + }, 100); + } + }; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -56,7 +98,7 @@ public void onClick(View arg0) { input.setOnEditorActionListener(new TextView.OnEditorActionListener() { @Override public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { - if(actionId == EditorInfo.IME_ACTION_DONE){ + if (actionId == EditorInfo.IME_ACTION_DONE) { onExecute(btn); return true; } @@ -65,57 +107,38 @@ public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { }); } - private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() { - - public void onReceive(Context context, Intent intent) { - String action = intent.getAction(); - if (ACTION_USB_PERMISSION.equals(action)) { - synchronized (this) { - UsbDevice dev = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE); - - if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) { - if (dev != null) { - Log.i(LOG_TAG, "open device"); - mUsbDeviceConnection = mUsbManager.openDevice(dev); - serialPort = UsbSerialDevice.createUsbSerialDevice(dev, mUsbDeviceConnection); - if (serialPort == null) { - Log.i(LOG_TAG, "open Serial port == null"); - mUsbDeviceConnection.close(); - return; - } - Log.i(LOG_TAG, "open Serial port != null"); - if (!serialPort.open()) { - Log.i(LOG_TAG, "open Serial port open failed"); - mUsbDeviceConnection.close(); - return; - } - // Devices are opened with default values, Usually - // 9600,8,1,None,OFF - // CDC driver default values 115200,8,1,None,OFF - Log.i(LOG_TAG, "open Serial port opened"); - serialPort.setBaudRate(115200); - serialPort.setDataBits(UsbSerialInterface.DATA_BITS_8); - serialPort.setStopBits(UsbSerialInterface.STOP_BITS_1); - serialPort.setParity(UsbSerialInterface.PARITY_NONE); - serialPort.setFlowControl(UsbSerialInterface.FLOW_CONTROL_OFF); - serialPort.read(mCallback); - Toast.makeText(getApplicationContext(), "AT ready", Toast.LENGTH_SHORT).show(); - isConnected = true; - } - } else { - Log.d(LOG_TAG, "permission denied for accessory " + dev); - } + private void connectUSBDevice(UsbDevice dev) { + synchronized (this) { + if (dev != null) { + Log.i(LOG_TAG, "open device"); + mUsbDeviceConnection = mUsbManager.openDevice(dev); + serialPort = UsbSerialDevice.createUsbSerialDevice(dev, mUsbDeviceConnection); + if (serialPort == null) { + Log.i(LOG_TAG, "open Serial port == null"); + mUsbDeviceConnection.close(); + return; + } + Log.i(LOG_TAG, "open Serial port != null"); + if (!serialPort.open()) { + Log.i(LOG_TAG, "open Serial port open failed"); + mUsbDeviceConnection.close(); + return; } + // Devices are opened with default values, Usually + // 9600,8,1,None,OFF + // CDC driver default values 115200,8,1,None,OFF + Log.i(LOG_TAG, "open Serial port opened"); + serialPort.setBaudRate(115200); + serialPort.setDataBits(UsbSerialInterface.DATA_BITS_8); + serialPort.setStopBits(UsbSerialInterface.STOP_BITS_1); + serialPort.setParity(UsbSerialInterface.PARITY_NONE); + serialPort.setFlowControl(UsbSerialInterface.FLOW_CONTROL_OFF); + serialPort.read(mCallback); + Toast.makeText(getApplicationContext(), "AT ready", Toast.LENGTH_SHORT).show(); + isConnected = true; } } - }; - - UsbDevice dev = null; - UsbDeviceConnection mUsbDeviceConnection = null; - UsbManager mUsbManager = null; - Handler mHandler = new Handler(); - UsbSerialDevice serialPort = null; - private boolean isConnected = false; + } private void onExecute(View arg0) { // send AT command @@ -137,7 +160,7 @@ private void onExecute(View arg0) { input.setText(""); } } - + @Override protected void onResume() { IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION); @@ -148,15 +171,15 @@ protected void onResume() { mUsbManager.getDeviceList(); HashMap deviceList = mUsbManager.getDeviceList(); Iterator deviceIterator = deviceList.values().iterator(); - + //dev block, check if is there any CDC devices while (deviceIterator.hasNext()) { UsbDevice tmp = deviceIterator.next(); - out.append("vid = " + Integer.toHexString(tmp.getVendorId()) + ":" + - " pid = " + Integer.toHexString(tmp.getProductId()) + - " isCdcDevice = " + UsbSerialDevice.isCdcDevice(tmp) + "\n"); + out.append("vid = " + Integer.toHexString(tmp.getVendorId()) + ":" + + " pid = " + Integer.toHexString(tmp.getProductId()) + + " isCdcDevice = " + UsbSerialDevice.isCdcDevice(tmp) + "\n"); } - + //reset to 1st position deviceIterator = deviceList.values().iterator(); while (deviceIterator.hasNext()) { @@ -169,7 +192,15 @@ protected void onResume() { Log.i(LOG_TAG, "dev != null, switch mode"); //new ExecuteAsRootBase().execute(); // we should request permision here - mUsbManager.requestPermission(dev, mPermissionIntent); + if(!mUsbManager.hasPermission(dev)) { + if(ExecuteAsRootBase.canRunRootCommands()){ + //we can run root command, so change configuration before request permission + ExecuteAsRootBase.execute(); + } + mUsbManager.requestPermission(dev, mPermissionIntent); + }else{ + connectUSBDevice(dev); + } } @Override @@ -177,27 +208,11 @@ protected void onPause() { // TODO Auto-generated method stub super.onPause(); unregisterReceiver(mUsbReceiver); - } - - private UsbSerialInterface.UsbReadCallback mCallback = new UsbSerialInterface.UsbReadCallback() { - @Override - public void onReceivedData(final byte[] arg0) { - mHandler.post(new Runnable() { - @Override - public void run() { - // TODO Auto-generated method stub - out.append(new String(arg0) + "\n"); - } - }); - // we could not scroll till the end right after set text - // so we wait for 100ms before scrolling - mHandler.postDelayed(new Runnable() { - @Override - public void run() { - // TODO Auto-generated method stub - mScrollView.fullScroll(ScrollView.FOCUS_DOWN); - } - }, 100); + if(serialPort != null){ + serialPort.close(); } - }; + if(mUsbDeviceConnection != null){ + mUsbDeviceConnection.close(); + } + } }