簽名異常導致自動化apk無法啟動
遇到的問題做個記錄~
問題背景:生產原因需要切換程式碼分支,由原分支CTV_Baseline_6681_MP2切換到CTV_Baseline_6681_MP3,而兩個分支的進版tag不一樣;Apk是從同事手中拿到的,通過預裝在system分割槽下的方式進行客製化。
問題描述:將客製化修改內容手動移植到MP3分支,編譯升級軟體後發現在factory_mode下自動化apk無法自啟動。
分析過程:
遇到問題之後,通過Uart連線主機板,在su許可權下執行logcat命令(此命令不做過濾,會輸出所有的資訊內容)獲取軟體輸出日誌;其中發現一句
1 10-29 11:07:54.297 3061 3257 W ActivityManager: Unable to start service Intent { act=com.tpv.newfactorytest.FactoryTestService pkg=com.tpv.newfactorytest } U=0: not found
顯示FactoryTestService這個服務沒有找到,猜測可能是apk沒有預裝或者是FactoryTestService這個服務沒有註冊;
先查看了apk的預裝情況,在system分割槽中有TPVFactest_0810.apk,data分割槽下有com.tpv.newfactorytest包名目錄;然後拿到了apk的原始碼,該服務有在AndroidManifest.xml檔案中註冊
1 <service 2 3 android:name="com.tpv.newfactorytest.FactoryTestService" 4 5 android:enabled="true" 6 7 android:exported="true" > 8 9 <intent-filter> 10 11 <action android:name="com.tpv.newfactorytest.FactoryTestService" /> 12 13 </intent-filter> 14 15 </service>
嘗試手動通過命令am startservice -n com.tpv.newfactorytest/.FactoryTestService
接著重新檢視logcat發現com.tpv.newfactorytest(pid=4812)被殺掉了;
1 10-29 11:08:00.986 3057 3600 I ActivityManager: Process com.tpv.newfactorytest (pid 4812) has died: fore SVC 2 3 10-29 11:08:00.988 3057 3600 W ActivityManager: Scheduling restart of crashed service com.tpv.newfactorytest/.FactoryTestService in 7536ms 4 5 10-29 11:08:00.998 3057 3109 W ActivityManager: setHasOverlayUi called on unknown pid: 4812 6 7 10-29 11:08:01.032 3057 3102 W libprocessgroup: kill(-4812, 9) failed: No such process 8 9 10-29 11:08:01.032 3057 3102 I libprocessgroup: Successfully killed process cgroup uid 1000 pid 4812 in 46ms
使用過濾功能把該程序的資訊過濾出來,捕捉到關鍵資訊點
1 10-29 11:07:57.920 4812 4812 E : can not found class define:com/mediatek/twoworlds/tv/model/MtkTvAudioInfoBase 2 3 10-29 11:07:57.921 4812 4812 F .newfactorytes: thread.cc:2148] No pending exception expected: java.lang.ClassNotFoundException: Didn't find class "com.mediatek.twoworlds.tv.model.MtkTvAudioInfoBase" on path: DexPathList[[zip file "/system/framework/org.apache.http.legacy.boot.jar", zip file "/system/app/TPVFactest_0810/TPVFactest_0810.apk"],nativeLibraryDirectories=[/system/app/TPVFactest_0810/lib/arm, /system/app/TPVFactest_0810/TPVFactest_0810.apk!/lib/armeabi, /system/lib, /system/product/lib, /system/lib, /system/product/lib]]
發現應用在庫檔案中找不到com.mediatek.twoworlds.tv.model.MtkTvAudioInfoBase這個類而丟擲了java.lang.ClassNotFoundException異常。
1 at java.lang.Class dalvik.system.BaseDexClassLoader.findClass(java.lang.String) (BaseDexClassLoader.java:134) 2 3 at java.lang.Class java.lang.ClassLoader.loadClass(java.lang.String, boolean) (ClassLoader.java:379) 4 5 at java.lang.Class java.lang.ClassLoader.loadClass(java.lang.String) (ClassLoader.java:312) 6 7 at java.lang.String java.lang.Runtime.nativeLoad(java.lang.String, java.lang.ClassLoader) (Runtime.java:-2) 8 9 at void java.lang.Runtime.loadLibrary0(java.lang.ClassLoader, java.lang.String) (Runtime.java:1014) 10 11 at void java.lang.System.loadLibrary(java.lang.String) (System.java:1669) 12 13 at void com.mediatek.twoworlds.tv.TVNative.<clinit>() (TVNative.java:77) 14 15 at int com.mediatek.twoworlds.tv.TVNative.getMinMaxConfigValue_native(int, java.lang.String) (TVNative.java:-2) 16 17 at int com.mediatek.twoworlds.tv.TVNativeWrapper.getMinMaxConfigValue_native(int, java.lang.String) (TVNativeWrapper.java:523) 18 19 at int com.mediatek.twoworlds.tv.MtkTvConfigBase.getMinMaxConfigValue(int, java.lang.String) (MtkTvConfigBase.java:231) 20 21 at int com.mediatek.twoworlds.tv.MtkTvConfigBase.getMinMaxConfigValue(java.lang.String) (MtkTvConfigBase.java:196) 22 23 at void com.mediatek.twoworlds.factory.MtkTvFApiDisplayBase.<init>() (MtkTvFApiDisplayBase.java:328) 24 25 at void com.mediatek.twoworlds.factory.MtkTvFApiDisplay.<init>() (MtkTvFApiDisplay.java:19) 26 27 at com.mediatek.twoworlds.factory.MtkTvFApiDisplay com.mediatek.twoworlds.factory.MtkTvFApiDisplay.getInstance() (MtkTvFApiDisplay.java:26) 28 29 at void com.tpv.newfactorytest.manager.PictureManager.<init>(android.content.Context) (PictureManager.java:44) 30 31 at com.tpv.newfactorytest.manager.PictureManager com.tpv.newfactorytest.manager.PictureManager.getInstance(android.content.Context) (PictureManager.java:87) 32 33 at void com.tpv.newfactorytest.manager.CommandExecutor.init() (CommandExecutor.java:189) 34 35 at void com.tpv.newfactorytest.manager.CommandExecutor.<init>(android.content.Context) (CommandExecutor.java:170) 36 37 at void com.tpv.newfactorytest.FactoryTestService.initial() (FactoryTestService.java:135) 38 39 at void com.tpv.newfactorytest.FactoryTestService.onCreate() (FactoryTestService.java:61) 40 41 at void android.app.ActivityThread.handleCreateService(android.app.ActivityThread$CreateServiceData) (ActivityThread.java:3532) 42 43 at void android.app.ActivityThread.access$1300(android.app.ActivityThread, android.app.ActivityThread$CreateServiceData) (ActivityThread.java:199) 44 45 at void android.app.ActivityThread$H.handleMessage(android.os.Message) (ActivityThread.java:1666) 46 47 at void android.os.Handler.dispatchMessage(android.os.Message) (Handler.java:106) 48 49 at void android.os.Looper.loop() (Looper.java:193) 50 51 at void android.app.ActivityThread.main(java.lang.String[]) (ActivityThread.java:6669) 52 53 at java.lang.Object java.lang.reflect.Method.invoke(java.lang.Object, java.lang.Object[]) (Method.java:-2) 54 55 at void com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run() (RuntimeInit.java:493) 56 57 at void com.android.internal.os.ZygoteInit.main(java.lang.String[]) (ZygoteInit.java:866)
通過反查程式碼MtkTvAudioInfoBase類在TvNative.java中有呼叫,但是呼叫路徑都正常;到這裡路被堵死了。
通過請教同事才知道,MTK平臺兩份程式碼進版tag不一樣,簽名有差異,會導致底層so庫檔案路徑有差異;
最後重新使用MP3分支進行簽名替換之後可以正常執行。