Android M 概率跳不过google开机向导原因分析

来源:互联网 发布:蓝驰创投 知乎 编辑:程序博客网 时间:2024/05/11 06:13

更新:

     google更新开机向导APK后,我们可以通过点击上一步,再重新进wifi界面.多试几次,可能就可以跳过连wifi界面了.(也有变态的解法,判断google的开机向导activity,延迟个5-10s启动),留给FRP service 更多时间.


      同时,再国内环境,如果插了SIM卡有数据连接的话,机器会一直卡在检查网络界面,不管以前是否登录过google账号.


原因是:

第一次eng刷机开机,机器初始任务多,手机运行慢,如果手机在10s内没有取到killswitchtoken是否存在的结果的话,wifi界面就没法跳过。

解决办法如下:

第一次开机完成稳定后,使用以下命令删除开机向导的缓存。

adb remount

adb shell rm -rfdata/data/com.google.android.setupwizard/

重新开机,问题应该会解决。


不行的话重复上面的步骤。


代码流程分析:

反编译google的开机向导后,我们从WifiSettingsWrapper.onStartSubactivity()里面可以知道,在这个方法返回true的时候NetworkRequirementHelper.isNetworkRequired()wifi界面是没法skip的。

往下跟到----->FrpHelper.isChallengeRequired() ------> FrpStatus. getFrpStatus()

public static FrpStatus getFrpStatus()

{

FrpTask localFrpTask = getFrpRequiredTask();

if ((localFrpTask.getStatus() != AsyncTask.Status.FINISHED) ||(localFrpTask.isCancelled()));

……

}

可以看出如果localFrpTask没有完成,或者localFrpTask已经cancel了的话,getFrpStatus()会返回null,同时isChallengeRequired会返回true,也就是wifi界面没法skip



同时FrpHelper在实例的时候就会loadFrpStatus()也就是会去在后台跑localFrpTask,也就是FrpTask,看FrpTask类的doInBackground方法。

protected FrpHelper.FrpStatus doInBackground(Void[]paramArrayOfVoid)

{

FrpHelper.FrpStatus localFrpStatus = new FrpHelper.FrpStatus();

this.mHandler.postDelayed(this.mTimeoutRunnable,10000L);

try

{

localFrpStatus.challengeRequired =FrpHelper.-get0(FrpHelper.this).isChallengeRequired();

localFrpStatus.supported =FrpHelper.-get0(FrpHelper.this).isChallengeSupported();

Log.i("SetupWizard.FrpHelper", "FRP status: "+ localFrpStatus);

this.mHandler.removeCallbacks(this.mTimeoutRunnable);

return localFrpStatus;

}

catch (NullPointerException localNullPointerException)

{

while (true)

Log.wtf("SetupWizard.FrpHelper", "Exceptiongetting FRP challenge state", localNullPointerException);

}

}


从黄色高亮的代码可以看出10s后,如果task没有完,就会执行mTimeoutRunnable

privatefinal Runnable mTimeoutRunnable = new Runnable()

{

public void run()

{

if (FrpHelper.FrpTask.this.getStatus() ==AsyncTask.Status.RUNNING)

FrpHelper.FrpTask.this.cancel(true);

}

};

mTimeoutRunnable里面会把这个后台taskcancel掉。


我们再返回看前面的getFrpStatus()方法,这个方法会返回null

我们再通过smail代码看isChallengeRequired()方法的返回值:


.method publicstatic isChallengeRequired()Z

.locals 2


.prologue

.line 54

invoke-static{},Lcom/google/android/setupwizard/util/FrpHelper;->getFrpStatus()Lcom/google/android/setupwizard/util/FrpHelper$FrpStatus;


move-result-object v0


.line 55

.local v0,"frpStatus":Lcom/google/android/setupwizard/util/FrpHelper$FrpStatus;

if-eqzv0, :cond_0


iget-booleanv1, v0,Lcom/google/android/setupwizard/util/FrpHelper$FrpStatus;->challengeRequired:Z


:goto_0

return v1


:cond_0

const/4 v1,0x1


goto:goto_0

.end method


关键地方就是if-eqzv0,:cond_0if-eqz意思是如果v0(frpStatus)是否等于Zreo,也就是null。恰好我们的frpStatus的值就是null。跟到cond_0,发现给了v1赋值1,也就是true,再跟到goto_0,这里直接把v1返回了,也就是返回了true

所以wifi界面就跳不过了。



从抓的log里面可以证实上述运行逻辑:


01-0616:55:02.269 I/SetupWizard.FrpHelper( 5151): FRP status: supported:true, challengeRequired: false

…….

01-0616:55:02.593 W/SetupWizard.FrpHelper( 5151):FRPtask cancelled, butchallengeRequired=false


我在AsyncTaskcancel(booleanmayInterruptIfRunning)方法里面打出的回调栈的log

01-0619:25:27.587 4109 4109 E fuyao : cancle call stackisjava.lang.Exception

01-0619:25:27.587 4109 4109 E fuyao : atandroid.os.AsyncTask.cancel(AsyncTask.java:482)

01-0619:25:27.587 4109 4109 E fuyao : atcom.google.android.setupwizard.util.FrpHelper$FrpTask$1.run(FrpHelper.java:127)

01-0619:25:27.587 4109 4109 E fuyao : atandroid.os.Handler.handleCallback(Handler.java:739)

01-0619:25:27.587 4109 4109 E fuyao : atandroid.os.Handler.dispatchMessage(Handler.java:95)

01-0619:25:27.587 4109 4109 E fuyao : atandroid.os.Looper.loop(Looper.java:148)

01-0619:25:27.587 4109 4109 E fuyao : atandroid.app.ActivityThread.main(ActivityThread.java:5417)

01-0619:25:27.587 4109 4109 E fuyao : atjava.lang.reflect.Method.invoke(Native Method)

01-0619:25:27.587 4109 4109 E fuyao : atcom.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)

01-0619:25:27.587 4109 4109 E fuyao : atcom.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)


PS:反编译后的java代码逻辑有些混乱,我们可以通过查看反编译的smali代码来帮助我们确认正常的逻辑

对比了AndroidLSetupwizard,是没有这个10s的要求的。



总结:

Google就是个坑- -

0 0