android GMS认证之testGoogleDuoPreloaded_第1张图片

7.1 GTS测试报了一个错

android GMS认证之testGoogleDuoPreloaded_第2张图片

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

有工具后,反编译的操作如此简单,我都不好意思说出来,直接给大家看看我们反编译后的代码界面吧:

android GMS认证之testGoogleDuoPreloaded_第3张图片

那我们赶快搜索一下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

这里写图片描述

从这,我们可以看出谷歌也认识到了自己的代码是有问题,已经有相关的规定,在处理此问题了。

更多相关文章

  1. Android 在代码中设置ProgressBar的style
  2. android判断用户是否已登陆详细代码
  3. Android 动态布局 (代码布局)
  4. android简易下拉刷新测试
  5. android 安装apk代码
  6. android 代码 退出程序
  7. android MediaPlayer 错误代码(error code)总结
  8. android开机启动代码

随机推荐

  1. 工作累了,用java写个游戏吧!开源一款游戏引
  2. Python2和3字符编码的区别
  3. Java如何获取方法参数具体名称?这是个好问
  4. Java线程池「异常处理」正确姿势:有病就得
  5. 一些好用的Java小库儿
  6. 数字类型内置方法
  7. 格式化输出的三种方式
  8. 流程控制之for循环
  9. 必看!java后端,亮剑诛仙(最全知识点)
  10. 解析Java横死之谜,气定神闲看花开花落