android GMS认证之testGoogleDuoPreloaded
7.1 GTS测试报了一个错
GtsPlacementTestCases - armeabi-v7a
Test Result Details
com.google.android.placement.gts.CoreGmsAppsTest#testGoogleDuoPreloaded fail junit.framework.AssertionFailedError: Mandatory app Hangouts not preloaded
问题浅探
从报错提示来看,就是强制要预置GMS应用Hangouts ,而检测手机说没有预置,所以报错。
真实的情况是这样的,客户要求一定要删除应用Hangouts ,加上应用Duo。
我们也可以从google/products/gms.mk文件看到如下说明:
# Note: Duo is mandatory for telephony devices, whereas Hangouts is for non-telephony devices.
也就是说对于电话设备,Duo应用是强制预装的,而对于非电话设备Hangouts 应用是强制预装的。
我们是手机电话设备,这符合要求,没有问题啊?为什么GTS测试会报错呢?
问题解决之千回百转
千回百转之高通技术支持
我提了一个case给高通,把这个情况说明了,高通给了一个解决方案,要我们装Hangouts 应用也内置一下,测试看什么情况?
我看到这个方法,觉得有点扯,内置Hangouts 应用,此测试项肯定可以PASS的,果然,内置Hangouts 应用测试,此项PASS,我把情况反馈,高通人员回复说现在可以PASS了,请我将此CASE关闭。我眼前一黑,这,问题没有解决就急着要关CASE。
(果然是屁股决定脑袋,你坐什么位置,脑子里就只关心自己的有利益相关的问题,高通人员心里只是关心CASE快点关闭,而问题有没有解决不是他们考虑的问题)
千回百转之GMS认证代理
客户提这种要求,那么此问题客户也应该是遇到过,我要软件项目经理帮忙去GMS代理咨询一下,有没有遇到这种情况,很快代理有回复了。
define android.hardware.telephony 这个feature如果打开了,应该不会出现这种问题。Hangout对于7.0/7.1的New telephone设备来说应该是optional的, 此处应该不会报错.我刚咨询了一下谷歌, 最近有要送测的7.1 New device, GTS没有这个问题(没有预置hangout).7.0的new device上没有hangout的设备, GTS也没有遇到这个问题.此处遇到的问题, 应该是设备被识别成了non-telephony的设备, 可以从这个方面去check.
事实上我们可以在GTS测试报告的device-info-files/FeatureDeviceInfo.deviceinfo.json文件中看到:
{ "name": "android.hardware.telephony", "type": "sdk", "available": true, "version": 0 },
也就是说android.hardware.telephony是支持的。
现在怎么办?
千回百转之自力更生
没有办法,还是自己再来分析。
先再看一下测试报的错误日志:
04-12 15:08:12 I/ConsoleReporter: [18c5ce29] Starting armeabi-v7a GtsPlacementTestCases with 1 test04-12 15:08:12 D/ModuleListener: ModuleListener.testStarted(com.google.android.placement.gts.CoreGmsAppsTest#testGoogleDuoPreloaded)04-12 15:08:12 D/ModuleListener: ModuleListener.testFailed(com.google.android.placement.gts.CoreGmsAppsTest#testGoogleDuoPreloaded, junit.framework.AssertionFailedError: Mandatory app Hangouts not preloadedat junit.framework.Assert.fail(Assert.java:50)at junit.framework.Assert.assertTrue(Assert.java:20)at com.google.android.placement.gts.CoreGmsAppsTest.testGoogleDuoPreloaded(CoreGmsAppsTest.java:228)at java.lang.reflect.Method.invoke(Native Method)at junit.framework.TestCase.runTest(TestCase.java:168)at junit.framework.TestCase.runBare(TestCase.java:134)at junit.framework.TestResult$1.protect(TestResult.java:115)at android.support.test.internal.runner.junit3.AndroidTestResult.runProtected(AndroidTestResult.java:77)at junit.framework.TestResult.run(TestResult.java:118)at android.support.test.internal.runner.junit3.AndroidTestResult.run(AndroidTestResult.java:55)at junit.framework.TestCase.run(TestCase.java:124)at android.support.test.internal.runner.junit3.NonLeakyTestSuite$NonLeakyTest.run(NonLeakyTestSuite.java:63)at android.support.test.internal.runner.junit3.AndroidTestSuite$1.run(AndroidTestSuite.java:97)at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:428)at java.util.concurrent.FutureTask.run(FutureTask.java:237)at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)at java.lang.Thread.run(Thread.java:761)
从这段日志,我们可以知道,是这android-gts/testcases/GtsPlacementTestCases.apk应用的测试。
GTS测试问题,有时候不好解决,为什么呢?一个关键的问题就是只在GTS的APK,而没有源码,导致我们分析问题,没有着力点,
没有关系,我就不信邪,我想看看到底是怎么回事?
现在就是要反编译APK,看看能不能找到源码,再来分析此问题。
我度娘了一个APK反编译工具,下载了三个APK反编译工具,用了一下,一个不能用,一个用不了,但是这个是可以完美的将代码反编译出来。有请这位哥哥:AndroidKiller_1.3.1:
有工具后,反编译的操作如此简单,我都不好意思说出来,直接给大家看看我们反编译后的代码界面吧:
那我们赶快搜索一下testGoogleDuoPreloaded方法,看看源码吧:
.method public testGoogleDuoPreloaded()V .locals 4 .prologue .line 217 invoke-direct {p0}, Lcom/google/android/placement/gts/CoreGmsAppsTest;->playStorePreloaded()Z move-result v0 if-nez v0, :cond_0 .line 218 const-string/jumbo v0, "CoreGmsAppsTest" const-string/jumbo v1, "Bypass as no Play Store preloaded." invoke-static {v0, v1}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I .line 219 return-void .line 222 :cond_0 iget-object v0, p0, Lcom/google/android/placement/gts/CoreGmsAppsTest;->mPackageManager:Landroid/content/pm/PackageManager; const-string/jumbo v1, "android.hardware.telephony" invoke-virtual {v0, v1}, Landroid/content/pm/PackageManager;->hasSystemFeature(Ljava/lang/String;)Z move-result v0 if-eqz v0, :cond_2 .line 223 invoke-direct {p0}, Lcom/google/android/placement/gts/CoreGmsAppsTest;->isNewProduct()Z move-result v0 if-eqz v0, :cond_1 .line 225 const-string/jumbo v0, "Mandatory app Google Duo not preloaded" const-string/jumbo v1, "com.google.android.apps.tachyon" invoke-direct {p0, v1}, Lcom/google/android/placement/gts/CoreGmsAppsTest;->isSystemApp(Ljava/lang/String;)Z move-result v1 invoke-static {v0, v1}, Lcom/google/android/placement/gts/CoreGmsAppsTest;->assertTrue(Ljava/lang/String;Z)V .line 216 :goto_0 return-void .line 228 :cond_1 const-string/jumbo v0, "Mandatory app Hangouts not preloaded" const-string/jumbo v1, "com.google.android.talk" invoke-direct {p0, v1}, Lcom/google/android/placement/gts/CoreGmsAppsTest;->isSystemApp(Ljava/lang/String;)Z move-result v1 invoke-static {v0, v1}, Lcom/google/android/placement/gts/CoreGmsAppsTest;->assertTrue(Ljava/lang/String;Z)V goto :goto_0 .line 232 :cond_2 const-string/jumbo v0, "Mandatory app Hangouts not preloaded" const-string/jumbo v1, "com.google.android.talk" invoke-direct {p0, v1}, Lcom/google/android/placement/gts/CoreGmsAppsTest;->isSystemApp(Ljava/lang/String;)Z move-result v1 invoke-static {v0, v1}, Lcom/google/android/placement/gts/CoreGmsAppsTest;->assertTrue(Ljava/lang/String;Z)V .line 234 const-string/jumbo v0, "Google Duo must not be preloaded without feature %s" const/4 v1, 0x1 new-array v1, v1, [Ljava/lang/Object; .line 235 const-string/jumbo v2, "android.hardware.telephony" const/4 v3, 0x0 aput-object v2, v1, v3 .line 234 invoke-static {v0, v1}, Ljava/lang/String;->format(Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/String; move-result-object v0 .line 235 const-string/jumbo v1, "com.google.android.apps.tachyon" invoke-direct {p0, v1}, Lcom/google/android/placement/gts/CoreGmsAppsTest;->isSystemApp(Ljava/lang/String;)Z move-result v1 .line 234 invoke-static {v0, v1}, Lcom/google/android/placement/gts/CoreGmsAppsTest;->assertFalse(Ljava/lang/String;Z)V goto :goto_0.end method
如果你说不知道怎么看反编译的源码,没有关系,非常简单,参考一下:
Android逆向反编译之smali基础
http://blog.csdn.net/sjim_/article/details/50443860
结合测试报错日志,我们直接看228行代码报错的地方:
.line 228 :cond_1const-string/jumbo v0, "Mandatory app Hangouts not preloaded"
此处就是报错提示的代码,那么我们只需要去确认一下228行代码上面做了一些什么工作就可以了。
检测Play Store应用是否内置
invoke-direct {p0}, Lcom/google/android/placement/gts/CoreGmsAppsTest;->playStorePreloaded()Z
我们当然是内置了Play Store应用,这个没有问题
检测设备feature(android.hardware.telephony)是否开启。
.line 222 :cond_0 iget-object v0, p0, Lcom/google/android/placement/gts/CoreGmsAppsTest;->mPackageManager:Landroid/content/pm/PackageManager; const-string/jumbo v1, "android.hardware.telephony" invoke-virtual {v0, v1}, Landroid/content/pm/PackageManager;->hasSystemFeature(Ljava/lang/String;)Z
这个我们有二个办法来确认,一个是上面说的方法来确认:
在GTS测试报告的device-info-files/FeatureDeviceInfo.deviceinfo.json文件中看到:
{ "name": "android.hardware.telephony", "type": "sdk", "available": true, "version": 0 },
另外一个办法是参考反编译代码来验证,非常简单,一行办法搞定:
Log.i(TAG, "hasSystemFeature:"+MainActivity.this.getPackageManager().hasSystemFeature("android.hardware.telephony"));
我们验证此feature是已经打开了。
检测设备是否是新设备。
.line 223invoke-direct {p0}, Lcom/google/android/placement/gts/CoreGmsAppsTest;->isNewProduct()Z
那我们再搜索一下方法isNewProduct()Z:
.method private isNewProduct()Z .locals 4 .prologue const/4 v1, 0x1 const/4 v2, 0x0 .line 100 const-string/jumbo v3, "ro.product.first_api_level" .line 99 invoke-static {v3, v2}, Landroid/os/SystemProperties;->getInt(Ljava/lang/String;I)I move-result v0 .line 101 .local v0, "firstApiLevel":I if-eqz v0, :cond_0 sget v3, Landroid/os/Build$VERSION;->SDK_INT:I if-ne v0, v3, :cond_1 :cond_0 :goto_0 return v1 :cond_1 move v1, v2 goto :goto_0.end method
从反编译后的源码,我们可以看到这就是比较二个值是否相等:
ro.product.first_api_levelLandroid/os/Build$VERSION;->SDK_INT
我从我们的设备来查看了一个系统属性:
[ro.product.first_api_level]: [24]
而再查看Landroid/os/Build$VERSION;->SDK_INT,在./frameworks/base/core/java/android/os/Build.java文件中,可以看到:
public static final int SDK_INT = SystemProperties.getInt( "ro.build.version.sdk", 0);
也就是系统属性:ro.build.version.sdk
我查看设备的ro.build.version.sdk值:
[ro.build.version.sdk]: [25]
看到了没,二个不相等,哈哈,问题定位到了,现在是7.1的设备SDK值是25,而ro.product.first_api_level还是24,没有及时更新过来。好了,搜索了一下代码,定位到:
./vendor/tinno/v3931/wik_fr/SUB_PROJECTS/orange/gms.mk
# OverridesPRODUCT_PROPERTY_OVERRIDES += \ ro.product.first_api_level=24 \ ro.setupwizard.require_network=OPTIONAL \ ro.setupwizard.mode=OPTIONAL \ ro.com.google.gmsversion=7.1_r3
将代码修改为:
# OverridesPRODUCT_PROPERTY_OVERRIDES += \ ro.product.first_api_level=25 \ ro.setupwizard.require_network=OPTIONAL \ ro.setupwizard.mode=OPTIONAL \ ro.com.google.gmsversion=7.1_r3
再编译验证,PASS。
此问题解决了。
自我感受
最后,结尾了,说几句自己的感受吧。说实在话,此BUG你也是前世造了什么孽,偏偏要落在我的手上,这叫天堂有路你不走,地狱无门你闯进来。如果你分到别人的名下还可以威风威风,当然在我的名下也是把我折腾了一番,但是最后,还是让我送你上路了。
解完此问题,有一种神鬼莫测,巧夺天工之感。
但是,你牛,你再牛有什么用,还不就是一个小程序员,别人只会觉得人就是把一个数字4改为了数字5,还不是一个没有什么影响力的底层小屌丝。这就是一个工作6年的程序员的心理微妙的变化。怎么办?
一个男人,白天他是那么的潇洒,其实他独自扛着一座大山。
责任,梦想,心胸,抱负,现在的有时候觉得程序员真的不是自己所再向往的,犹记得当年对手机,对软件开发的挚爱,现在已不再。
这就是为什么我好久没有更新技术博客的原因。
看来,我要再次打点行装,告别现在的拥有,去追寻那个新的梦想所在。
后话
又过了几个月,MTK的一个项目过GMS认证,忽然对ro.product.first_api_level有要求:
NOTE:
1. Do not declare the ro.product.first_api_level value at all if the build is the first factory ROM build of the product from July, 2017
————————————————-
Hi Keith,
New device第一版過認證的軟件 do not set ro.product.first_api_level
MR升級版本中 ro.product.first_api_level 值必須設為第一版 approved 軟件 api level一致的值
另外請將 Android.mk內容修改成右圖
partner_gms/apps/WebViewGoogle/Android.mk
从这,我们可以看出谷歌也认识到了自己的代码是有问题,已经有相关的规定,在处理此问题了。
更多相关文章
- Android 在代码中设置ProgressBar的style
- android判断用户是否已登陆详细代码
- Android 动态布局 (代码布局)
- android简易下拉刷新测试
- android 安装apk代码
- android 代码 退出程序
- android MediaPlayer 错误代码(error code)总结
- android开机启动代码