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

/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.android.server.wifi;
import android.annotation.NonNull;
import android.content.Context;
import android.util.Log;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
/**
 * Wrapper for context to override getResources method. Resources for wifi mainline jar needs to be
 * fetched from the resources APK.
 */
public class WifiHelp {
    private static final String TAG = "WifiHelp";
    public static FutureTask<Context> mFutureTask;
    private static WifiHelp sInstance = null;
    private WifiHelp() {
        Log.i(TAG, "WifiHelp getInstance construct");
    }
    public static WifiHelp getInstance() {
        Log.i(TAG, "WifiHelp getInstance");
        if (sInstance==null){

            sInstance=new WifiHelp();
        }
        Log.i(TAG, "WifiHelp getInstance end, sInstance = " + sInstance);
        return sInstance;
    }
    public Context getContext() {
        Log.i(TAG, "getContext, sInstance = " + sInstance + " mFutureTask = " + mFutureTask);
        Context context = null;
        try {
            context = mFutureTask.get();
            Log.i(TAG, "getContext, context = " + context);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        return context;
    }
    class MyCallable implements Callable<Context> {
        private Context mContext;
        private static final String WIFI_OVERLAY_JAVA_PKG_NAME = "com.android.wifi.resources";
        public MyCallable(@NonNull Context context) {
            mContext = context;
            Log.i(TAG, "MyCallable construct context = " + context);
        }
        public Context call() throws Exception {
            if (mContext == null) {
                Log.i(TAG, "MyCallable, mContext is null");
                return null;
            }
            Log.i(TAG, "MyCallable in thread");
            Context result = mContext.createPackageContext(WIFI_OVERLAY_JAVA_PKG_NAME, 0);
            Log.i(TAG, "MyCallable in thread, package context = " + result);
            return result;
        }
    }
    public void createPackageContext(Context context) {
        Log.i(TAG, "createPackageContext, sInstance = " + sInstance + " param context = " + context);
        mFutureTask = new FutureTask<>(new MyCallable(context));
        new Thread(mFutureTask).start();
        Log.i(TAG, "createPackageContext thread start, mFutureTask = " + mFutureTask);
    }
}

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

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

    public Resources getResources() {
        if (mWifiResourcesFromApk == null) {
            Log.i(TAG, "getResources, mWifiResourcesFromApk is null");
            //Context resourcesApkContext = getResourcesApkContext();
            Context resourcesApkContext = WifiHelp.getInstance().getContext();
            if (resourcesApkContext != null) {
                Log.i(TAG, "getResources, mWifiResourcesFromApk is valid");
                mWifiResourcesFromApk = resourcesApkContext.getResources();
            }
        }

        return mWifiResourcesFromApk;
    }

然后在另一个仓库:

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

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

    public void createWifiContextAhead(String className, String path) {
        Slog.i(TAG, "createWifiContextAhead");
        PathClassLoader pathClassLoader = mLoadedPaths.get(path);
        if (pathClassLoader == null) {
            // NB: the parent class loader should always be the system server class loader.
            // Changing it has implications that require discussion with the mainline team.
            pathClassLoader = new PathClassLoader(path, this.getClass().getClassLoader());
            mLoadedPaths.put(path, pathClassLoader);
        }
        final Class<?> wifiServiceClass = loadClassFromLoader(className, pathClassLoader);
        try {
            Slog.i(TAG, "createWifiContextAhead, mContext = " + mContext);
            Method method = wifiServiceClass.getDeclaredMethod("getInstance", null);
            Object service = method.invoke(null, null);
            Method method1 = wifiServiceClass.getDeclaredMethod("createPackageContext", Context.class);
            method1.invoke(service, mContext);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

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

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

        // Start services.
        try {
            t.traceBegin("StartServices");
            startBootstrapServices(t);
            // put wifiHelp here as is must depend on the packagemanager service up, wangqingyuan
            Slog.e("system_server", "wifiContext create ahead of time, avoid wifiservice up consume too much time");
            mSystemServiceManager.createWifiContextAhead("com.android.server.wifi.WifiHelp", WIFI_APEX_SERVICE_JAR_PATH);
            startCoreServices(t);
            startOtherServices(t);
        } catch (Throwable ex) {
            Slog.e("System", "******************************************");
            Slog.e("System", "************ Failure starting system services", ex);
            throw ex;
        } finally {
            t.traceEnd(); // StartServices
        }


版权声明:本文为yudelian原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。