android5.1的USB授权弹框流程分析
一、在UsbDebuggingManager类中
1、文件位置:frameworks/base/services/usb/java/com/android/server/usb/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;
private final Context mContext;
private final Handler mHandler;
private Thread mThread;
private boolean mAdbEnabled = false;
private String mFingerprints;
private LocalSocket mSocket = null;
private OutputStream mOutputStream = null;
public UsbDebuggingManager(Context context) {
mHandler = new UsbDebuggingHandler(FgThread.get().getLooper());
mContext = context;
}
2、这是一个Runnable线程,先看看里面有哪些功能,然后再看在哪里调用的;
3、首先构造函数中new了一个UsbDebuggingHandler消息对象;
@Override
public void run() {
while (mAdbEnabled) {
try {
listenToSocket();
} catch (Exception e) {
/* Don't loop too fast if adbd dies, before init restarts it */
SystemClock.sleep(1000);
}
}
}
4、在run方法中,有一个监听Socket的方法-listenToSocket(),这个方法中有一个while循环,一直监听弹框之后用户点击的处理事件。
private void listenToSocket() throws IOException {
try {
byte[] buffer = new byte[BUFFER_SIZE];
LocalSocketAddress address = new LocalSocketAddress(ADBD_SOCKET,
LocalSocketAddress.Namespace.RESERVED);
InputStream inputStream = null;
mSocket = new LocalSocket();
mSocket.connect(address);
mOutputStream = mSocket.getOutputStream();
inputStream = mSocket.getInputStream();
while (true) {
int count = inputStream.read(buffer);
if (count < 0) {
break;
}
if (buffer[0] == 'P' && buffer[1] == 'K') {
String key = new String(Arrays.copyOfRange(buffer, 2, count));
Slog.d(TAG, "Received public key: " + key);
Message msg = mHandler.obtainMessage(UsbDebuggingHandler.MESSAGE_ADB_CONFIRM);
msg.obj = key;
mHandler.sendMessage(msg);
}
else {
Slog.e(TAG, "Wrong message: " + (new String(Arrays.copyOfRange(buffer, 0, 2))));
break;
}
}
} finally {
closeSocket();
}
}
5、一直监听,当有p和k出现的时候,就开始弹出adb usb调试的授权弹框;发送消息,并有一个key的字符创从buffer中取出;消息ID:UsbDebuggingHandler.MESSAGE_ADB_CONFIRM
case MESSAGE_ADB_CONFIRM: {
String key = (String)msg.obj;
String fingerprints = getFingerprints(key);
if ("".equals(fingerprints)) {
sendResponse("NO");
break;
}
mFingerprints = fingerprints;
startConfirmation(key, mFingerprints);
break;
}
6、startConfirmation(key, mFingerprints);启动确认弹框,需要传入两个参数;
private void startConfirmation(String key, String fingerprints) {
String nameString = Resources.getSystem().getString(
com.android.internal.R.string.config_customAdbPublicKeyConfirmationComponent);
ComponentName componentName = ComponentName.unflattenFromString(nameString);
if (startConfirmationActivity(componentName, key, fingerprints)
|| startConfirmationService(componentName, key, fingerprints)) {
return;
}
Slog.e(TAG, "unable to start customAdbPublicKeyConfirmationComponent "
+ nameString + " as an Activity or a Service");
}
7、开始启动弹框的activity,通过资源字符串获取启动的包名和类名:config_customAdbPublicKeyConfirmationComponent
字段,在frameworks/base/core/res/res/values/config.xml中有定义:
<!-- Name of the activity or service that prompts the user to reject, accept, or whitelist
an adb host's public key, when an unwhitelisted host connects to the local adbd.
Can be customized for other product types -->
<string name="config_customAdbPublicKeyConfirmationComponent"
>com.android.systemui/com.android.systemui.usb.UsbDebuggingActivity</string>
8、可以看出,这个弹框是系统的systemui应用弹出来的,这就好办了,直接查看这个类:UsbDebuggingActivity
9、frameworks/base/services/usb/java/com/android/server/usb/UsbDeviceManager.java中有调用这个类
二、分析UsbDebuggingActivity类
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.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();
}
1、通过一系列的判断,最终显示这个activity;
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();
}
}
}
2、同时注册了一个广播,这个广播就监听USB的状态而已;
@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();
}
3、当点击确认的时候,需要走的流程,首先是获取IBinder对象,可以看出是通过Binder来进行授权的传递,授权需要有一个权限入门:mKey,同时这个类中也需要声明一个权限:
<!-- started from UsbDebuggingManager -->
<activity android:name=".usb.UsbDebuggingActivity"
android:permission="android.permission.MANAGE_USB"
android:theme="@style/Theme.SystemUI.Dialog.Alert"
android:finishOnCloseSystemDialogs="true"
android:excludeFromRecents="true">
</activity>
4、这个权限是在SystemUI中声明的;
三、分析IUsbManager.aidl类和UsbService类
路径:frameworks/base/services/usb/java/com/android/server/usb/UsbService.java
路径:frameworks/base/core/java/android/hardware/usb/IUsbManager.aidl
IBinder b = ServiceManager.getService(USB_SERVICE);
IUsbManager service = IUsbManager.Stub.asInterface(b);
if (allow) {
service.allowUsbDebugging(alwaysAllow, mKey);
} else {
service.denyUsbDebugging();
}
1、此类是Binder类,进程之间相互调用的类,也就是说在server和client之间能够调用的类,这个类很重要,继续上面的分析,
可以看出IUsbManager.allowUsbDebugging();调用此方法,实际上,就是调用UsbService.java中的方法
/**
* UsbService manages all USB related state, including both host and device support.
* Host related events and calls are delegated to UsbHostManager, and device related
* support is delegated to UsbDeviceManager.
*/
public class UsbService extends IUsbManager.Stub {
public static class Lifecycle extends SystemService {
private UsbService mUsbService;
public Lifecycle(Context context) {
super(context);
}
@Override
public void onStart() {
mUsbService = new UsbService(getContext());
publishBinderService(Context.USB_SERVICE, mUsbService);
}
2、类UsbService.java继承IUsbManager.Stub类,也就是IUsbManager.aidl,当调用IUsbManager.allowUsbDebugging()时,实际上调用的是UsbService.java中的代码如下:
private static final String TAG = "UsbService";
private final Context mContext;
private UsbDeviceManager mDeviceManager;
private UsbHostManager mHostManager;
..................
@Override
public void allowUsbDebugging(boolean alwaysAllow, String publicKey) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
mDeviceManager.allowUsbDebugging(alwaysAllow, publicKey);
}
@Override
public void denyUsbDebugging() {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
mDeviceManager.denyUsbDebugging();
}
3、由代码看出,UsbService类,实质上是调用UsbDeviceManager和UsbHostManager类中的方法,至此,我们分析这个两个类即可,不必专门来分析UsbService了,
四、分析UsbDeviceManager.java类
1、继上面调用的方法:UsbDeviceManager.allowUsbDebugging(alwaysAllow, publicKey);分析:
public void allowUsbDebugging(boolean alwaysAllow, String publicKey) {
if (mDebuggingManager != null) {
mDebuggingManager.allowUsbDebugging(alwaysAllow, publicKey);
}
}
public void denyUsbDebugging() {
if (mDebuggingManager != null) {
mDebuggingManager.denyUsbDebugging();
}
}
2、这个方法又转调到了UsbDebuggingManager.allowUsbDebugging的方法;
public void allowUsbDebugging(boolean alwaysAllow, String publicKey) {
Message msg = mHandler.obtainMessage(UsbDebuggingHandler.MESSAGE_ADB_ALLOW);
msg.arg1 = alwaysAllow ? 1 : 0;
msg.obj = publicKey;
mHandler.sendMessage(msg);
}
public void denyUsbDebugging() {
mHandler.sendEmptyMessage(UsbDebuggingHandler.MESSAGE_ADB_DENY);
}
3、发送一个消息给handler;然后继续
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;
}
4、这里把key写入到文件中,然后发送一个ok字符给socket字节流中,就可以连接adb了,这个字节流是可以在有system权限的应用中监听的;
至此,简单的USB弹框授权就完成了!