Android USB安全调试
Android 4.2.2 引入了USB安全调试方面的内容,当启用安全调试的时候,只有被用户认证过的主机才可以通过Android SDK自带的ADB工具经由USB连接来访问设备的内部构件。
下面以android-4.3_r3.1源码分析其实现:
首先打 usb调试界面在systemui中的UsbDebuggingActivity.java实现:

public class UsbDebuggingActivity extends AlertActivity
implements DialogInterface.OnClickListener {
private static final String TAG = "UsbDebuggingActivity"; private CheckBox mAlwaysAllow;
private UsbDisconnectedReceiver mDisconnectedReceiver;
private String mKey; @Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle); if (SystemProperties.getInt("service.adb.tcp.port", 0) == 0) {
mDisconnectedReceiver = new UsbDisconnectedReceiver(this);
} Intent intent = getIntent();
String fingerprints = intent.getStringExtra("fingerprints");
mKey = intent.getStringExtra("key"); if (fingerprints == null || mKey == null) {
finish();
return;
} final AlertController.AlertParams ap = mAlertParams;
ap.mTitle = getString(R.string.usb_debugging_title);
ap.mIconId = com.android.internal.R.drawable.ic_dialog_usb;
ap.mMessage = getString(R.string.usb_debugging_message, fingerprints);
ap.mPositiveButtonText = getString(android.R.string.ok);
ap.mNegativeButtonText = getString(android.R.string.cancel);
ap.mPositiveButtonListener = this;
ap.mNegativeButtonListener = this; // add "always allow" checkbox
LayoutInflater inflater = LayoutInflater.from(ap.mContext);
View checkbox = inflater.inflate(com.android.internal.R.layout.always_use_checkbox, null);
mAlwaysAllow = (CheckBox)checkbox.findViewById(com.android.internal.R.id.alwaysUse);
mAlwaysAllow.setText(getString(R.string.usb_debugging_always));
ap.mView = checkbox; setupAlert();
} private class UsbDisconnectedReceiver extends BroadcastReceiver {
private final Activity mActivity;
public UsbDisconnectedReceiver(Activity activity) {
mActivity = activity;
} @Override
public void onReceive(Context content, Intent intent) {
String action = intent.getAction();
if (!UsbManager.ACTION_USB_STATE.equals(action)) {
return;
}
boolean connected = intent.getBooleanExtra(UsbManager.USB_CONNECTED, false);
if (!connected) {
mActivity.finish();
}
}
} @Override
public void onStart() {
super.onStart();
IntentFilter filter = new IntentFilter(UsbManager.ACTION_USB_STATE);
registerReceiver(mDisconnectedReceiver, filter);
} @Override
protected void onStop() {
if (mDisconnectedReceiver != null) {
unregisterReceiver(mDisconnectedReceiver);
}
super.onStop();
} @Override
public void onClick(DialogInterface dialog, int which) {
boolean allow = (which == AlertDialog.BUTTON_POSITIVE);
boolean alwaysAllow = allow && mAlwaysAllow.isChecked();
try {
IBinder b = ServiceManager.getService(USB_SERVICE);
IUsbManager service = IUsbManager.Stub.asInterface(b);
if (allow) {
service.allowUsbDebugging(alwaysAllow, mKey);
} else {
service.denyUsbDebugging();
}
} catch (Exception e) {
Log.e(TAG, "Unable to notify Usb service", e);
}
finish();
}
}
其主要功能实现于UsbDebuggingManager.java中:

public class UsbDebuggingManager implements Runnable {
private static final String TAG = "UsbDebuggingManager";
private static final boolean DEBUG = false;
private final String ADBD_SOCKET = "adbd";
private final String ADB_DIRECTORY = "misc/adb";
private final String ADB_KEYS_FILE = "adb_keys";
private final int BUFFER_SIZE = 4096;
...
class UsbDebuggingHandler extends Handler {
private static final int MESSAGE_ADB_ENABLED = 1;
private static final int MESSAGE_ADB_DISABLED = 2;
private static final int MESSAGE_ADB_ALLOW = 3;
private static final int MESSAGE_ADB_DENY = 4;
private static final int MESSAGE_ADB_CONFIRM = 5;
private static final int MESSAGE_ADB_CLEAR = 6;
public UsbDebuggingHandler(Looper looper) {
super(looper);
}
public void handleMessage(Message msg) {
switch (msg.what) {
case MESSAGE_ADB_ENABLED:
if (mAdbEnabled)
break;
mAdbEnabled = true;
mThread = new Thread(UsbDebuggingManager.this);
mThread.start();
break;
case MESSAGE_ADB_DISABLED:
if (!mAdbEnabled)
break;
mAdbEnabled = false;
closeSocket();
try {
mThread.join();
} catch (Exception ex) {
}
mThread = null;
mOutputStream = null;
mSocket = null;
break;
case MESSAGE_ADB_ALLOW: {
String key = (String)msg.obj;
String fingerprints = getFingerprints(key);
if (!fingerprints.equals(mFingerprints)) {
Slog.e(TAG, "Fingerprints do not match. Got "
+ fingerprints + ", expected " + mFingerprints);
break;
}
if (msg.arg1 == 1) {
writeKey(key);
}
sendResponse("OK");
break;
}
case MESSAGE_ADB_DENY:
sendResponse("NO");
break;
case MESSAGE_ADB_CONFIRM: {
String key = (String)msg.obj;
mFingerprints = getFingerprints(key);
showConfirmationDialog(key, mFingerprints);
break;
}
case MESSAGE_ADB_CLEAR:
deleteKeyFile();
break;
}
}
}
private String getFingerprints(String key) {
String hex = "0123456789ABCDEF";
StringBuilder sb = new StringBuilder();
MessageDigest digester;
try {
digester = MessageDigest.getInstance("MD5");
} catch (Exception ex) {
Slog.e(TAG, "Error getting digester: " + ex);
return "";
}
byte[] base64_data = key.split("\\s+")[0].getBytes();
byte[] digest = digester.digest(Base64.decode(base64_data, Base64.DEFAULT));
for (int i = 0; i < digest.length; i++) {
sb.append(hex.charAt((digest[i] >> 4) & 0xf));
sb.append(hex.charAt(digest[i] & 0xf));
if (i < digest.length - 1)
sb.append(":");
}
return sb.toString();
}
private void showConfirmationDialog(String key, String fingerprints) {
Intent dialogIntent = new Intent();
dialogIntent.setClassName("com.android.systemui",
"com.android.systemui.usb.UsbDebuggingActivity");
dialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
dialogIntent.putExtra("key", key);
dialogIntent.putExtra("fingerprints", fingerprints);
try {
mContext.startActivity(dialogIntent);
} catch (ActivityNotFoundException e) {
Slog.e(TAG, "unable to start UsbDebuggingActivity");
}
}
private File getUserKeyFile() {
File dataDir = Environment.getDataDirectory();
File adbDir = new File(dataDir, ADB_DIRECTORY);
if (!adbDir.exists()) {
Slog.e(TAG, "ADB data directory does not exist");
return null;
}
return new File(adbDir, ADB_KEYS_FILE);
}
private void writeKey(String key) {
try {
File keyFile = getUserKeyFile();
if (keyFile == null) {
return;
}
if (!keyFile.exists()) {
keyFile.createNewFile();
FileUtils.setPermissions(keyFile.toString(),
FileUtils.S_IRUSR | FileUtils.S_IWUSR |
FileUtils.S_IRGRP, -1, -1);
}
FileOutputStream fo = new FileOutputStream(keyFile, true);
fo.write(key.getBytes());
fo.write('\n');
fo.close();
}
catch (IOException ex) {
Slog.e(TAG, "Error writing key:" + ex);
}
}
private void deleteKeyFile() {
File keyFile = getUserKeyFile();
if (keyFile != null) {
keyFile.delete();
}
}
可见,若要删除特定连接Android设备的电脑只能删除Android设备中的文件:/data/misc/adb/adb_keys,或将Android设备强制刷机。
Android USB安全调试的更多相关文章
- 在Mac系统上配置Android真机调试环境
在Mac系统上配置Android真机调试环境 mac上配置安卓环境还说挺方便的,真机调试也比win上要好一些.win上被各种软件强行安装了xxx助手. 在mac上就了一个干净的感觉. 下载Androi ...
- 在android设备上调试ionic应用
方法1: ionic run android -l -c 将会在console中输出日志信息 方法2: (1).使用usb连接android设备,并打开android设备的调试功能 (2).在chro ...
- chrome inspect 远程调测:Chrome on Android之一 普通调试
本文PC环境: Chrome: 版本 33.0.1750.22 dev MAC OS:OS X 10.9.1 特别注意:Chrome DevToolsl使用时会联接到appspot.com,而此网址被 ...
- I.MX6 Android USB Touch eGTouchA.ini文件存放
/******************************************************************** * I.MX6 Android USB Touch eGTo ...
- android usb Host模式下与usb Hid 设备的通信
做android 与USB HID设备的通信有段时间了,总结一下遇到的问题和解决方法: 1,第一次遇到的问题:android 版本低不支持usb hid, 被要求做相关项目的时候,就从mUsbMana ...
- 杭州蓝松科技推出的安卓端的USB转串口调试助手, 欢迎下载使用
杭州蓝松科技推出的安卓端的USB转串口调试助手, 欢迎下载使用 下载地址:http://files.cnblogs.com/guobaPlayer/%E8%93%9D%E6%9D%BEUSB%E4%B ...
- [Android] [putty连接Android设备] [Android设备网络调试]
file: system/core/adb/adb.c line: 921 /* for the device, start the usb transport if the ** android u ...
- Unity Profiler连接Android真机调试
Profiler在Editor模式就可以观看性能消耗,但是毕竟电脑配置高,跟手机真机环境还是有区别.实际开发中的优化还是推荐用真机测试. 因为IOS一般比Android手机的配置高,在Android平 ...
- Android内存泄露调试
Android 内存泄漏调试 一.概述 如果我们编写的代码当中有太多的对内存使用不当的地方,难免会使得我们的设备运行缓慢,甚至是死机.为了能够使得 Android 应用程序安全且快速的运行, Andr ...
随机推荐
- U3D 实现子弹发射效果
首先,这里子弹要模拟的相似的话,用2D刚体比较好,会有重力,自由落体运动. using UnityEngine; using System.Collections; public class gun ...
- 开源的Android开发框架-------PowerFramework使用心得(四)数据库管理DBFarmer
DBFarmer是PowerFramework数据库管理工具的集合. 可以进行对象的存储,添加了setter和getter的参数会被收录到数据库中,每个参数作为一个项,int类型的id或_id会被作为 ...
- listview的动态加载数据问题
1:调用adapter.notifyDataSetChanged()却不起作用 原因可能有一下几点 1.数据源没有更新,调用notifyDataSetChanged无效. 2.数据源更新了,但是它指向 ...
- Encapsulation.
Access control is often referred to as implementation hiding. Wrapping data and methods within class ...
- ORACLE多表关联UPDATE 语句
转载至:http://blog.itpub.net/29378313/viewspace-1064069/ 为了方便起见,建立了以下简单模型,和构造了部分测试数据:在某个业务受理子系统BSS中, SQ ...
- ORACLE 数据库简单测试
ORACLE 数据库简单测试 操作系统:Windows 7 – ORACLE:oracle database 10.2.0.4 一.目的 测试 启动监听程序.数据库 非同一个用户的情况,用户是否可以 ...
- Base64的用法
如果要对一些图片进行保存,把他的文件名变成乱码,不让用户把他删掉,可以用Base64把他删掉用法如下: //获取访问图片的路径 String path=editText.getText().toStr ...
- 1. mybatis批量插入数据
通过list <insert id="saveByList" useGeneratedKeys="true" parameterType="ja ...
- iOS图片的伪裁剪(改变图片的像素值)
0x00 原理 利用一张图片事先画好的图片(以下称为蒙板),盖在要被裁剪的的图片上,然后遍历蒙板上的像素点,修改被裁剪图片对应位置的像素的色值即可得到一些我们想要的不规则图片了(比如人脸) 0x01 ...
- 极简主义,对逻辑操作符||和&&深度运用的理解
丧心病狂的代码压缩好像违背了愉快阅读的本真,所以刨根问底想要了解个究竟,最后发现这不只是前端大牛装逼卖萌的绝技,也是代码洁癖爱好者的利器,毕竟这样看上去确实蛮优雅的; 一开始,我们接触到的代码是这样的 ...