Android 允许USB调试弹窗是怎么弹出来的
通过 adb 调试直接安装应用到真机上,简单方便。
adb connect 192.168.1.1
adb connect 192.168.1.1:5555 //指定端口为 5555
在 AN 8.0 上,用上述命令adb调试真机时,首次连接会出现 “允许USB调试吗” 的弹窗,这个弹窗怎么出来的,源码一探究竟。
在串口调试工具敲命令 dumpsys activity activities | grep mResumedActivity
得知,
这个页面是 com.android.systemui/.usb.UsbDebuggingActivity
,
源码路径
frameworks/base/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java
关注 onClick
方法,调用了 IUsbManager
的 allowUsbDebugging
方法。
@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();
}
相关联的文件为:
frameworks/base/services/usb/java/com/android/server/usb/UsbService.java
frameworks/base/core/java/android/hardware/usb/IUsbManager.aidl
frameworks/base/services/usb/java/com/android/server/usb/UsbDeviceManager.java
frameworks/base/services/usb/java/com/android/server/usb/UsbDebuggingManager.java
1 查看 UsbService.java ,实际调用的是 UsbDeviceManager.allowUsbDebugging(alwaysAllow, publicKey)
;
private UsbDeviceManager mDeviceManager;
@Override
public void allowUsbDebugging(boolean alwaysAllow, String publicKey) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
mDeviceManager.allowUsbDebugging(alwaysAllow, publicKey);
}
2 查看 frameworks/base/services/usb/java/com/android/server/usb/UsbDeviceManager.java
,实际调用 UsbDebuggingManager.allowUsbDebugging(boolean alwaysAllow, String publicKey)
;
private UsbDebuggingManager mDebuggingManager;
public void allowUsbDebugging(boolean alwaysAllow, String publicKey) {
if (mDebuggingManager != null) {
mDebuggingManager.allowUsbDebugging(alwaysAllow, publicKey);
}
}
3 查看 frameworks/base/services/usb/java/com/android/server/usb/UsbDebuggingManager.java
,发出了 MESSAGE_ADB_ALLOW
消息;
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);
}
UsbDebuggingHandler
内容如下,启动了 UsbDebuggingThread
以及 Handler 收发消息流程。
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 UsbDebuggingThread();
mThread.start();
break;
case MESSAGE_ADB_DISABLED:
if (!mAdbEnabled)
break;
mAdbEnabled = false;
if (mThread != null) {
mThread.stopListening();
mThread = 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);
}
if (mThread != null) {
mThread.sendResponse("OK");
}
break;
}
case MESSAGE_ADB_DENY:
if (mThread != null) {
mThread.sendResponse("NO");
}
break;
case MESSAGE_ADB_CONFIRM: {
if ("trigger_restart_min_framework".equals(
SystemProperties.get("vold.decrypt"))) {
Slog.d(TAG, "Deferring adb confirmation until after vold decrypt");
if (mThread != null) {
mThread.sendResponse("NO");
}
break;
}
String key = (String)msg.obj;
String fingerprints = getFingerprints(key);
if ("".equals(fingerprints)) {
if (mThread != null) {
mThread.sendResponse("NO");
}
break;
}
mFingerprints = fingerprints;
startConfirmation(key, mFingerprints);
break;
}
case MESSAGE_ADB_CLEAR:
deleteKeyFile();
break;
}
}
}
其中 if (msg.arg1 == 1) { writeKey(key); }
就是如果勾选了 “一律允许这台计算机进行调试” ,则将对应的 key 保存到 data/misc/adb/adb_keys
文件里。
说到这里,弹窗的逻辑实现就知道了。
不对啊,还是没说弹窗怎么出来的。别急,继续。
将 UsbDebuggingManager.java
的 log 开关打开,
- private static final boolean DEBUG = false;
+ private static final boolean DEBUG = true;
首次执行 adb connect 会出现如下 log :
07-06 16:34:58.167 1570 2615 D UsbDebuggingManager: Received public key: QAAAAGkQ5x8ngNhLRdKw3vO6i8jRUZeQzah1weiQuMq1z1sjaB8Otto2ISD66X+sxmjxIj4CpTqIlGJxsfmn74yylU0menZepnLE4031e5E4sOT/07MAW+JtVipMTS1JareqAv5PCVof1tTzS5iy2L4iudG7POBMki39r4OCUKmpOlmMdZQBhR1ADpcK/rystSgJm9mpbWv38UN4KcNS+x5w0sKx/bNp3yJ/oY1hLWnWbHJDL0KMVChr7+Fb7hc9VwOUS5G4V1YkNaa7LTM7PHGN6WknevqIp2SxCvkE5J6/1FbtBWk/HGrf3fuPKoQEQmKQdVzm+ysN0ErZ1L6JnKu6mtZofb6wVEAODhVMWrWY3YhFt/IHucDTWkCByXcmERmHpkcLtGk6w8nq+6COpfFkRoX2ZP4IZUyn8aqI5Mm4xf95RwK6vVwNhFsYzp8RctD2qVWq5nL5iCwqp9n2i4etShmjNH/VFIpaoP/H5YXP8bMBnYjPfTU9kUYn0kpRgHHQ8kkiXrLJ5XFwrKFAv0pSK9W0kDJFsaRvkLb2H3EebqJnZdWEeTq0haBAMjoesbUI0lmxtJ9zaE5rsbh/NWXs/SlFHMvY3wH99b7ZH8UqBc4bJGDQd4oi8gKeXHLh574EmGf9G6/I+eV2zKgknL+RJtnhyc8FvS+SV8Suh9o5PjF6OVA4pwEAAQA= @unknown
依据 Received public key
关键字找到 UsbDebuggingManager --> UsbDebuggingThread
class UsbDebuggingThread extends Thread {
private boolean mStopped;
private LocalSocket mSocket;
private OutputStream mOutputStream;
private InputStream mInputStream;
UsbDebuggingThread() {
super(TAG);
}
@Override
public void run() {
if (DEBUG) Slog.d(TAG, "Entering thread");
while (true) {
synchronized (this) {
if (mStopped) {
if (DEBUG) Slog.d(TAG, "Exiting thread");
return;
}
try {
openSocketLocked();
} catch (Exception e) {
/* Don't loop too fast if adbd dies, before init restarts it */
SystemClock.sleep(1000);
}
}
try {
listenToSocket();
} catch (Exception e) {
/* Don't loop too fast if adbd dies, before init restarts it */
SystemClock.sleep(1000);
}
}
}
private void openSocketLocked() throws IOException {
try {
LocalSocketAddress address = new LocalSocketAddress(ADBD_SOCKET,
LocalSocketAddress.Namespace.RESERVED);
mInputStream = null;
if (DEBUG) Slog.d(TAG, "Creating socket");
mSocket = new LocalSocket();
mSocket.connect(address);
mOutputStream = mSocket.getOutputStream();
mInputStream = mSocket.getInputStream();
} catch (IOException ioe) {
closeSocketLocked();
throw ioe;
}
}
private void listenToSocket() throws IOException {
try {
byte[] buffer = new byte[BUFFER_SIZE];
while (true) {
int count = mInputStream.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 {
synchronized (this) {
closeSocketLocked();
}
}
}
private void closeSocketLocked() {
if (DEBUG) Slog.d(TAG, "Closing socket");
try {
if (mOutputStream != null) {
mOutputStream.close();
mOutputStream = null;
}
} catch (IOException e) {
Slog.e(TAG, "Failed closing output stream: " + e);
}
try {
if (mSocket != null) {
mSocket.close();
mSocket = null;
}
} catch (IOException ex) {
Slog.e(TAG, "Failed closing socket: " + ex);
}
}
/** Call to stop listening on the socket and exit the thread. */
void stopListening() {
synchronized (this) {
mStopped = true;
closeSocketLocked();
}
}
void sendResponse(String msg) {
synchronized (this) {
if (!mStopped && mOutputStream != null) {
try {
mOutputStream.write(msg.getBytes());
}
catch (IOException ex) {
Slog.e(TAG, "Failed to write response:", ex);
}
}
}
}
}
代码流程为 UsbDebuggingThread
通过 openSocketLocked()
开启 Socket 连接并且监听 listenToSocket()
,
收到 adb connect
消息后,发出 msg UsbDebuggingHandler.MESSAGE_ADB_CONFIRM
,
查看 UsbDebuggingHandler
可知,调用了 startConfirmation(key, mFingerprints);
private void startConfirmation(String key, String fingerprints) {
int currentUserId = ActivityManager.getCurrentUser();
UserHandle userHandle =
UserManager.get(mContext).getUserInfo(currentUserId).getUserHandle();
String componentString;
if (currentUserId == UserHandle.USER_OWNER) {
componentString = Resources.getSystem().getString(
com.android.internal.R.string.config_customAdbPublicKeyConfirmationComponent);
} else {
// If the current foreground user is not the primary user we send a different
// notification specific to secondary users.
componentString = Resources.getSystem().getString(
R.string.config_customAdbPublicKeyConfirmationSecondaryUserComponent);
}
ComponentName componentName = ComponentName.unflattenFromString(componentString);
if (startConfirmationActivity(componentName, userHandle, key, fingerprints)
|| startConfirmationService(componentName, userHandle, key, fingerprints)) {
return;
}
Slog.e(TAG, "unable to start customAdbPublicKeyConfirmation[SecondaryUser]Component "
+ componentString + " as an Activity or a Service");
}
/**
* @returns true if the componentName led to an Activity that was started.
*/
private boolean startConfirmationActivity(ComponentName componentName, UserHandle userHandle,
String key, String fingerprints) {
PackageManager packageManager = mContext.getPackageManager();
Intent intent = createConfirmationIntent(componentName, key, fingerprints);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if (packageManager.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY) != null) {
try {
mContext.startActivityAsUser(intent, userHandle);
return true;
} catch (ActivityNotFoundException e) {
Slog.e(TAG, "unable to start adb whitelist activity: " + componentName, e);
}
}
return false;
}
其中,com.android.internal.R.string.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>
<!-- Name of the activity that prompts the secondary user to acknowledge she/he needs to
switch to the primary user to enable USB debugging.
Can be customized for other product types -->
<string name="config_customAdbPublicKeyConfirmationSecondaryUserComponent"
>com.android.systemui/com.android.systemui.usb.UsbDebuggingSecondaryUserActivity</string>
这样就清楚了,最终根据包名信息 com.android.systemui/com.android.systemui.usb.UsbDebuggingActivity
打开了“允许USB调试吗” 页面。
总结如下:
1.开机后启动 UsbService ,UsbDebuggingThread 一直检测 adb 消息;
2.收到 adb connect 消息后,通过 UsbDebuggingHandler 调起 SystemUI 的 UsbDebuggingActivity 页面。
本文地址:https://blog.csdn.net/weixin_44021334/article/details/107161201
上一篇: JVM 常用配置参数(Java 8)
下一篇: 也有哭的权利