Android 5.0 Usb调试拦截分析及修改
當(dāng)我們調(diào)試安卓機(jī)器時(shí),第一次插上usb線,會(huì)彈出一個(gè)授權(quán)的對(duì)話框,(前提是打開了usb調(diào)試功能)點(diǎn)擊確認(rèn),才會(huì)允許調(diào)試.
如果我們想機(jī)器默認(rèn)就可以調(diào)試該怎么做呢?
如果我們想動(dòng)態(tài)攔截,需要用戶輸入帳號(hào)密碼,才確認(rèn)是否可以調(diào)試,該怎么做呢?或者只是單純的想改變這個(gè)不好看的UI,又該怎么做呢?
分析的源碼基于android 5.0.2_r1
前面所說(shuō)的情況1,想在默認(rèn)情況下就允許usb調(diào)試,需要修改源碼下的/build/core/main.mk文件,然后重新編譯,刷機(jī),具體請(qǐng)看:?
http://blog.csdn.net/fanmengke_im/article/details/28389439?utm_source=tuicool&utm_medium=referral
至于后面的那一種,就是我要說(shuō)的重點(diǎn),需要去看一看android源碼,然后做一些適當(dāng)?shù)男薷?首先,我們要找到關(guān)于usb的源碼,主要在/frameworks/base/services/java/目錄下,也就是這幾個(gè)文件:?
UsbDebuggingManager.java?
UsbDeviceManager.java?
UsbHostManager.java?
UsbService.java?
UsbSettingsManager.java
其中涉及到的一些資源文件在/frameworks/base/core/res/res/目錄下
尋找入口點(diǎn)
源碼與資源文件都在這了,從哪入手,我也是一頭霧水,還好,只有5個(gè)java文件,去讀一讀,看看有什么收獲.?
你會(huì)發(fā)現(xiàn),在UsbDebuggingmanager類中,你會(huì)發(fā)現(xiàn)有這樣的幾個(gè)方法:
startConfirmation(String key, String fingerprints)
startConfirmationActivity(ComponentName componentName, String key,
? ? ? ? ? ? String fingerprints)
startConfirmationService(ComponentName componentName, String key,
? ? ? ? ? ? String fingerprints)?
1
2
3
4
5
6
7
會(huì)不會(huì)就是這些方法彈出了對(duì)話框呢?繼續(xù)追蹤,發(fā)現(xiàn)startConfirmationActivity()和startConfirmationService()都是在startConfirmation()方法中調(diào)用的,現(xiàn)在我們來(lái)看下startConfirmation()方法:
首先通過(guò)資源文件拿到一個(gè)String類型的nameString,然后通過(guò)unflattenFromString()方法,傳入nameString得到一個(gè)ComponentName對(duì)象,那么nameString到底是什么呢?
在/frameworks/base/core/res/res/values/config.xml 文件中,我們看到:
原來(lái)ConponentName就是:?
包名為com.android.systemui?
組件為com.android.systemui.usb.UsbDebuggingActivity的類
彈窗UI在這修改
哦哦,原來(lái)我們彈出的授權(quán)對(duì)話框就是systemui app中的一個(gè)activity,如果你只是單純的想改變這個(gè)UI,你現(xiàn)在只要到/frameworks/base/packages/SystemUI/usb/目錄下,找到UsbDebuggingActivity這個(gè)類,修改它的布局文件即可.等會(huì)再來(lái)看下這個(gè)類,做了哪些事情.
繼續(xù)回到上面的分析,你會(huì)發(fā)現(xiàn)startConfirmation()方法在一個(gè)Handler被調(diào)用,什么情況下會(huì)出發(fā)這個(gè)Handler呢?原來(lái),UsbDebuggingManager實(shí)現(xiàn)了Runnable,在run()方法中開啟了一個(gè)LocalSocket,去讀取底層的usb信息,做出響應(yīng)的操作.至于該線程的開啟,也在Handler中,只要你調(diào)用了setAdbEnabled(),如果參數(shù)為true,就開啟該線程.
?
現(xiàn)在我們只要看看在哪個(gè)地方實(shí)例化了UsbDebuggingManager類,調(diào)用了setAdbEnabled()方法.
追蹤發(fā)現(xiàn)在UsbDeviceManager中,它的構(gòu)造方法中初始化了UsbDebuggingManager類.
可以看到會(huì)通過(guò)SystemProperties讀取ro.adb.secure 和 vold.decrypt的值,這兩個(gè)值,我請(qǐng)教了做rom的同事,說(shuō)這些值是在編譯的時(shí)候修改的,主要來(lái)區(qū)分user,eng版本,這兩個(gè)值主要就是來(lái)進(jìn)行是否進(jìn)行usb認(rèn)證機(jī)制的.
然后就初始化了UsbDeviceManager類,在看看調(diào)用mDebuggingManager.setAdbEnabled(mAdbEnabled)的地方.
也是在UsbDeviceManager的Handler中調(diào)用的,它注冊(cè)啦一個(gè)開機(jī)廣播,每次開機(jī)就會(huì)觸發(fā)它.代碼只截取了一小部分…
?
當(dāng)然,還有幾個(gè)地方調(diào)用了setAdbEnabled()方法,比如在這個(gè)Handler初始化的時(shí)候,我就沒(méi)有追蹤了,如果你有興趣,可以去調(diào)試下~
接下來(lái),繼續(xù)往上追蹤,看看UsbDeviceManager在哪被實(shí)例化了.它是通過(guò)UsbService的構(gòu)造方法來(lái)實(shí)例化的.
在UsbService這個(gè)類中,它是繼承自IUsbManager.Stub類的,也就是IUsbManager.aidl這個(gè)文件,它在/frameworks/base/core/java/android/hardware/usb/文件夾下,這個(gè)接口是@hide的,因?yàn)橥獠坎豢梢砸?文件內(nèi)容如下:
// 只摘錄了IUsbManager中的幾個(gè)方法
/** @hide */
interface IUsbManager{
? ? /* Allow USB debugging from the attached host. If alwaysAllow is true, add the
? ? ?* the public key to list of host keys that the user has approved.
? ? ?*/
? ? void allowUsbDebugging(boolean alwaysAllow, String publicKey);
? ? /* Deny USB debugging from the attached host */
? ? void denyUsbDebugging();
? ? /* Clear public keys installed for secure USB debugging */
? ? void clearUsbDebuggingKeys();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
看方法名就大致能猜出來(lái)該方法的作用,允許授權(quán),拒絕授權(quán),清除授權(quán).
在看看UsbService在哪被實(shí)例化?在UsbService中有一個(gè)Lifecycle靜態(tài)內(nèi)部類,繼承自SystemService,在onStart()方法中,實(shí)例化了UsbService類.
那是在何處調(diào)用了Lifecycle類呢?通過(guò)查找發(fā)現(xiàn),原來(lái)是在SystemService這個(gè)類調(diào)用的.
對(duì)于SystemService類,我也不是很了解,具體的相關(guān)信息可以去查詢.SystemService是android系統(tǒng)一個(gè)很重要的服務(wù),它是由zytote來(lái)初始化的,然后會(huì)啟動(dòng)android系統(tǒng)的一些必要服務(wù)和支持組件,地位相當(dāng)重要.直接看看代碼吧.
? ? private void run() {
? ? ? ? // If a device's clock is before 1970 (before 0), a lot of
? ? ? ? // APIs crash dealing with negative numbers, notably
? ? ? ? // java.io.File#setLastModified, so instead we fake it and
? ? ? ? // hope that time from cell towers or NTP fixes it shortly.
? ? ? ? if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {
? ? ? ? ? ? Slog.w(TAG, "System clock is before 1970; setting to 1970.");
? ? ? ? ? ? SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);
? ? ? ? }
? ? ? ? // Here we go!
? ? ? ? Slog.i(TAG, "Entered the Android system server!");
? ? ? ? EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN, SystemClock.uptimeMillis());
? ? ? ? // In case the runtime switched since last boot (such as when
? ? ? ? // the old runtime was removed in an OTA), set the system
? ? ? ? // property so that it is in sync. We can't do this in
? ? ? ? // libnativehelper's JniInvocation::Init code where we already
? ? ? ? // had to fallback to a different runtime because it is
? ? ? ? // running as root and we need to be the system user to set
? ? ? ? // the property. http://b/11463182
? ? ? ? SystemProperties.set("persist.sys.dalvik.vm.lib.2", VMRuntime.getRuntime().vmLibrary());
? ? ? ? // Enable the sampling profiler.
? ? ? ? if (SamplingProfilerIntegration.isEnabled()) {
? ? ? ? ? ? SamplingProfilerIntegration.start();
? ? ? ? ? ? mProfilerSnapshotTimer = new Timer();
? ? ? ? ? ? mProfilerSnapshotTimer.schedule(new TimerTask() {
? ? ? ? ? ? ? ? @Override
? ? ? ? ? ? ? ? public void run() {
? ? ? ? ? ? ? ? ? ? SamplingProfilerIntegration.writeSnapshot("system_server", null);
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }, SNAPSHOT_INTERVAL, SNAPSHOT_INTERVAL);
? ? ? ? }
? ? ? ? // Mmmmmm... more memory!
? ? ? ? VMRuntime.getRuntime().clearGrowthLimit();
? ? ? ? // The system server has to run all of the time, so it needs to be
? ? ? ? // as efficient as possible with its memory usage.
? ? ? ? VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);
? ? ? ? // Some devices rely on runtime fingerprint generation, so make sure
? ? ? ? // we've defined it before booting further.
? ? ? ? Build.ensureFingerprintProperty();
? ? ? ? // Within the system server, it is an error to access Environment paths without
? ? ? ? // explicitly specifying a user.
? ? ? ? Environment.setUserRequired(true);
? ? ? ? // Ensure binder calls into the system always run at foreground priority.
? ? ? ? BinderInternal.disableBackgroundScheduling(true);
? ? ? ? // Prepare the main looper thread (this thread).
? ? ? ? android.os.Process.setThreadPriority(
? ? ? ? ? ? ? ? android.os.Process.THREAD_PRIORITY_FOREGROUND);
? ? ? ? android.os.Process.setCanSelfBackground(false);
? ? ? ? Looper.prepareMainLooper();
? ? ? ? // Initialize native services.
? ? ? ? System.loadLibrary("android_servers");
? ? ? ? nativeInit();
? ? ? ? // Check whether we failed to shut down last time we tried.
? ? ? ? // This call may not return.
? ? ? ? performPendingShutdown();
? ? ? ? // Initialize the system context.
? ? ? ? createSystemContext();
? ? ? ? // Create the system service manager.
? ? ? ? mSystemServiceManager = new SystemServiceManager(mSystemContext);
? ? ? ? LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
? ? ? ? // Start services.
? ? ? ? try {
? ? ? ? ? ? startBootstrapServices();
? ? ? ? ? ? startCoreServices();
? ? ? ? ? ? startOtherServices();
? ? ? ? } catch (Throwable ex) {
? ? ? ? ? ? Slog.e("System", "******************************************");
? ? ? ? ? ? Slog.e("System", "************ Failure starting system services", ex);
? ? ? ? ? ? throw ex;
? ? ? ? }
? ? ? ? // For debug builds, log event loop stalls to dropbox for analysis.
? ? ? ? if (StrictMode.conditionallyEnableDebugLogging()) {
? ? ? ? ? ? Slog.i(TAG, "Enabled StrictMode for system server main thread.");
? ? ? ? }
? ? ? ? // Loop forever.
? ? ? ? Looper.loop();
? ? ? ? throw new RuntimeException("Main thread loop unexpectedly exited");
? ? }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
可以看到初始化很多東西,創(chuàng)建Context,加載android_servers,初始化主線程…最后調(diào)用了startBootstrapServices(),startCoreServices(),startOtherServices()方法,在這個(gè)方法中,啟動(dòng)了Lifecycle服務(wù).
這樣的話,整體流程就串起來(lái)了.?
1.首先android系統(tǒng)啟動(dòng),初始化了SystemServer?
2.在由SystemServer去啟動(dòng)UsbService$Lifecycle服務(wù),然后實(shí)例化UsbService?
3.在由UsbService初始化了UsbHostManager和UsbDeviceManager.?
4.然后UsbDeviceManager通過(guò)讀取ro.adb.secure和vold.decrypt的值,來(lái)判定是否開啟調(diào)試攔截流程(也就是初始化UsbDebuggingManager)?
5.如果初始化UsbDebuggingManager,它會(huì)一直監(jiān)聽(tīng)LocalSocketAddress(“adbd”, LocalSocketAddress.Namespace.RESERVED)這個(gè)端口,判斷是否彈出授權(quán)窗口
分析彈出授權(quán)的UI窗口
也就是UsbDebuggingActivity類,繼承自AlertActivity,我們主要看一些確認(rèn)和取消的事件.
通過(guò)ServiceManager得到一個(gè)IBinder對(duì)象,然后通過(guò)IBinder得到一個(gè)IUsbManager對(duì)象,這個(gè)就是前面所說(shuō)的aidl接口,UsbService實(shí)現(xiàn)了IUsbManager接口,調(diào)用allowUsbDebugging()和denyUsbDebugging(),同意授權(quán)和不同意授權(quán).
那我們?cè)诨剡^(guò)頭來(lái),看一看IUsbManager接口中的allowUsbDebugging()和denyUsbDebugging()的實(shí)現(xiàn).?
在UsbService中:
其實(shí)調(diào)用的是UsbDeviceManager中的方法:
最終發(fā)現(xiàn)原來(lái)調(diào)用的是UsbDebuggingManager中的方法:
最終,找到了原來(lái)所有的操作還是在它的UsbDebuggingHandler中,如果授權(quán)成功了,會(huì)向文件中寫入這個(gè)key和相關(guān)信息,然后通過(guò)上面所說(shuō)的Socket寫入一條”O(jiān)K”這樣的信息.如果取消授權(quán),會(huì)通過(guò)Socket寫入一條”NO”這樣的信息.到此,整個(gè)流程就走完了.
至于Socket的另一端,暫時(shí)沒(méi)有去尋找它,據(jù)個(gè)人估計(jì),可能與驅(qū)動(dòng)方面有關(guān).(咱待研究)
定制調(diào)試攔截
1.如果你只是想改動(dòng)彈出的UI,只需要修改UsbDebuggingActivity的布局文件就可以了.
2.如該想改動(dòng)相關(guān)邏輯,就需要在UsbDebuggingManager類中改動(dòng),是否彈窗,或者根本不想用systemui里面的Activity,都可以在這里面進(jìn)行改動(dòng).?
不過(guò)上層如果想要授權(quán)的話,需要調(diào)用IUsbManager的授權(quán)和取消授權(quán)方法.?
如果獲取不到該類或者它的實(shí)現(xiàn)類UsbService(好像是因?yàn)镮UsbManager是@hide,我沒(méi)有試過(guò)),建議你仿照IUsbManager.adil文件,上下層都去實(shí)現(xiàn)其中的幾個(gè)重要方法,就可以拿來(lái)用了.
3.如果你根本想不攔截調(diào)試授權(quán)的話,就需要在main.mk文件中做一些相應(yīng)的修改了,具體的話,可以去網(wǎng)上搜一下.
4.當(dāng)然,如果你修改UsbDeviceManager類的,在初始化的時(shí)候給它再加一個(gè)判斷條件的話,也可以顯示自由攔截功能.
暫時(shí)就研究到這了,因?yàn)楣拘枰ㄖ七@東西,等需求有變化了,可能需要在做研究,到時(shí)候在補(bǔ)充吧~
相關(guān)文章:?
android4.4 debug調(diào)試授權(quán)攔截(替換掉 允許USB調(diào)試嗎? UI)?
Android 如何開啟與關(guān)閉adb 的認(rèn)證機(jī)制(google adb secure) (adb RSA 指紋認(rèn)證)?
Android 下的usb框架及功能點(diǎn)?
Android設(shè)備adb授權(quán)的原理
---------------------?
作者:zhou_lee?
來(lái)源:CSDN?
原文:https://blog.csdn.net/u012301841/article/details/53200172?
版權(quán)聲明:本文為博主原創(chuàng)文章,轉(zhuǎn)載請(qǐng)附上博文鏈接!
總結(jié)
以上是生活随笔為你收集整理的Android 5.0 Usb调试拦截分析及修改的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 【译】LXC and LXD: Expl
- 下一篇: 【译】Easily Build Andr