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
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
{ - 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
- }