• android wifiService 启动慢的问题规避记录


    frameworks/base/services/java/com/android/server/SystemServer.java

    因为wifiservice在system_server里启动,在这儿监测的时间,总共用了2s,暂时高通基线只用了100多ms, 与高通基线代码无任何修改,所以wifiservice代码本身的代码没问题

    最后经各种加日志分析,发现是一个获取wifiContext对象的时候,用了2s

    尝试解决办法一:

    使用了android 系统的perf来监测system_server的各个线程使用情况,想知道哪个具体的加载函数出的问题,但是貌似没怎么生效

    尝试解决办法二:

    1、尝试将WifiContext获取的时候使用另一个线程获取,但是后面会遇到各种crash

    2、尝试在Wifiservice构造的时候延迟,会发生后续WifiScanService的crash

    尝试解决办法三:

    1、尝试在system_server一开始的时候获取WifiContext资源,然后在Wifiservice的启动的时候将mContext对象传进WifiService里,结果发现WifiService通过jar包加载,无法传入参数

    2、尝试在system_server一开始的时候创建WifiContext资源,将这个资源对象写入一个单例里,然后使用资源对象的时候,阻塞的获取,但是因为创建对象的地方放在了PackageManage

     service启动之前,所以出现了各种crash,尤其是在get的时候crash,

    3、最后成功的是,基于解决办法三里的2, 创建的时候放在PackageManageService启动之后

    首先创建一个WifiHelper.java, 用一个线程获取资源,另一个线程可以获取到拿到的资源

    frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiHelp.java

    1. /*
    2. * Copyright (C) 2019 The Android Open Source Project
    3. *
    4. * Licensed under the Apache License, Version 2.0 (the "License");
    5. * you may not use this file except in compliance with the License.
    6. * You may obtain a copy of the License at
    7. *
    8. * http://www.apache.org/licenses/LICENSE-2.0
    9. *
    10. * Unless required by applicable law or agreed to in writing, software
    11. * distributed under the License is distributed on an "AS IS" BASIS,
    12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13. * See the License for the specific language governing permissions and
    14. * limitations under the License.
    15. */
    16. package com.android.server.wifi;
    17. import android.annotation.NonNull;
    18. import android.content.Context;
    19. import android.util.Log;
    20. import java.util.concurrent.Callable;
    21. import java.util.concurrent.ExecutionException;
    22. import java.util.concurrent.FutureTask;
    23. /**
    24. * Wrapper for context to override getResources method. Resources for wifi mainline jar needs to be
    25. * fetched from the resources APK.
    26. */
    27. public class WifiHelp {
    28. private static final String TAG = "WifiHelp";
    29. public static FutureTask mFutureTask;
    30. private static WifiHelp sInstance = null;
    31. private WifiHelp() {
    32. Log.i(TAG, "WifiHelp getInstance construct");
    33. }
    34. public static WifiHelp getInstance() {
    35. Log.i(TAG, "WifiHelp getInstance");
    36. if (sInstance==null){
    37. sInstance=new WifiHelp();
    38. }
    39. Log.i(TAG, "WifiHelp getInstance end, sInstance = " + sInstance);
    40. return sInstance;
    41. }
    42. public Context getContext() {
    43. Log.i(TAG, "getContext, sInstance = " + sInstance + " mFutureTask = " + mFutureTask);
    44. Context context = null;
    45. try {
    46. context = mFutureTask.get();
    47. Log.i(TAG, "getContext, context = " + context);
    48. } catch (InterruptedException e) {
    49. e.printStackTrace();
    50. } catch (ExecutionException e) {
    51. e.printStackTrace();
    52. }
    53. return context;
    54. }
    55. class MyCallable implements Callable {
    56. private Context mContext;
    57. private static final String WIFI_OVERLAY_JAVA_PKG_NAME = "com.android.wifi.resources";
    58. public MyCallable(@NonNull Context context) {
    59. mContext = context;
    60. Log.i(TAG, "MyCallable construct context = " + context);
    61. }
    62. public Context call() throws Exception {
    63. if (mContext == null) {
    64. Log.i(TAG, "MyCallable, mContext is null");
    65. return null;
    66. }
    67. Log.i(TAG, "MyCallable in thread");
    68. Context result = mContext.createPackageContext(WIFI_OVERLAY_JAVA_PKG_NAME, 0);
    69. Log.i(TAG, "MyCallable in thread, package context = " + result);
    70. return result;
    71. }
    72. }
    73. public void createPackageContext(Context context) {
    74. Log.i(TAG, "createPackageContext, sInstance = " + sInstance + " param context = " + context);
    75. mFutureTask = new FutureTask<>(new MyCallable(context));
    76. new Thread(mFutureTask).start();
    77. Log.i(TAG, "createPackageContext thread start, mFutureTask = " + mFutureTask);
    78. }
    79. }

    frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiContext.java

    禁掉直接获取资源,而是调用WifiHelper的获取资源

    1. public Resources getResources() {
    2. if (mWifiResourcesFromApk == null) {
    3. Log.i(TAG, "getResources, mWifiResourcesFromApk is null");
    4. //Context resourcesApkContext = getResourcesApkContext();
    5. Context resourcesApkContext = WifiHelp.getInstance().getContext();
    6. if (resourcesApkContext != null) {
    7. Log.i(TAG, "getResources, mWifiResourcesFromApk is valid");
    8. mWifiResourcesFromApk = resourcesApkContext.getResources();
    9. }
    10. }
    11. return mWifiResourcesFromApk;
    12. }

    然后在另一个仓库:

    frameworks/base/services/core/java/com/android/server/SystemServiceManager.java

    仿照这里的使用反射的函数:startServiceFromJar,通过反射调用到另一个包里,即WifiHelper

    1. public void createWifiContextAhead(String className, String path) {
    2. Slog.i(TAG, "createWifiContextAhead");
    3. PathClassLoader pathClassLoader = mLoadedPaths.get(path);
    4. if (pathClassLoader == null) {
    5. // NB: the parent class loader should always be the system server class loader.
    6. // Changing it has implications that require discussion with the mainline team.
    7. pathClassLoader = new PathClassLoader(path, this.getClass().getClassLoader());
    8. mLoadedPaths.put(path, pathClassLoader);
    9. }
    10. final Class wifiServiceClass = loadClassFromLoader(className, pathClassLoader);
    11. try {
    12. Slog.i(TAG, "createWifiContextAhead, mContext = " + mContext);
    13. Method method = wifiServiceClass.getDeclaredMethod("getInstance", null);
    14. Object service = method.invoke(null, null);
    15. Method method1 = wifiServiceClass.getDeclaredMethod("createPackageContext", Context.class);
    16. method1.invoke(service, mContext);
    17. } catch (NoSuchMethodException e) {
    18. e.printStackTrace();
    19. } catch (InvocationTargetException e) {
    20. e.printStackTrace();
    21. } catch (IllegalAccessException e) {
    22. e.printStackTrace();
    23. }
    24. }

    frameworks/base/services/java/com/android/server/SystemServer.java

    在startCoreServices之前,是经过验证可以放的地方,太靠前可能会导致wifiscanservice崩溃

    1. // Start services.
    2. try {
    3. t.traceBegin("StartServices");
    4. startBootstrapServices(t);
    5. // put wifiHelp here as is must depend on the packagemanager service up, wangqingyuan
    6. Slog.e("system_server", "wifiContext create ahead of time, avoid wifiservice up consume too much time");
    7. mSystemServiceManager.createWifiContextAhead("com.android.server.wifi.WifiHelp", WIFI_APEX_SERVICE_JAR_PATH);
    8. startCoreServices(t);
    9. startOtherServices(t);
    10. } catch (Throwable ex) {
    11. Slog.e("System", "******************************************");
    12. Slog.e("System", "************ Failure starting system services", ex);
    13. throw ex;
    14. } finally {
    15. t.traceEnd(); // StartServices
    16. }

  • 相关阅读:
    IPMP、PMP、CPMP三个证书该如何选择,有什么区别,哪个对于工作上的
    RK3568开发笔记(三):瑞芯微RK3588芯片介绍,入手开发板的核心板介绍
    MongoDB命令汇总
    生成式人工智能在软件开发过程现代化中的作用
    C# 连接mysql数据库ADO.NET模式, 数据绑定到datagridview控件上,设置部分列隐藏
    软件系统开发|公众号都有哪些展现形式?
    EcmaScript6全新语法特性-----EcmaScript6
    通用接口适配器使用文档须知
    Go 使用Viper处理Go应用程序的配置
    CPU、GPU、NPU的区别
  • 原文地址:https://blog.csdn.net/yudelian/article/details/127960589