针对Android系统,几乎目前市面上的设备终端启动速度都在40s以上,明显满足车载系统平台启动速度的要求,本文将根据项目经过从针对各个部分系统启动速度优化方面进行说明,以及优化的原则问题。本文以MTK平台为例进行说明
1、proloader和lk(bootloader)部分
这个部分的优化原则:
尽快可的加快系统进入内核的速度,针对一些没必须的模块可以不进行加载,能够保证尽快进入内核并能够稳定启动内核即可。毕竟bootloader主要是针对CPU+DDR+cache+EMMC+clock等部分初始化,以及准备内核启动参数和部分外设驱动(如串口)初始化等工作,其它部分基本不需要进行加载。
如MTK平台代码,我们可以将proloader和lk代码中针对两个部分的模块初始化时的时间统计信息开关关闭,同时将不需要加载的程序代码、打印日志等优化掉,将大幅增加preloader+lk的启动速度,如下:
LK部分:
1)vendor\mediatek\proprietary\bootable\bootloader\lk\project\evb3561sv_w_no2.mk
##DEBUG := 2
DEBUG := 0
2)vendor\mediatek\proprietary\bootable\bootloader\lk\target\evb3561sv_w_no2\rules.mk
##LK_PROFILING := yes
LK_PROFILING := no
3)vendor\mediatek\proprietary\bootable\bootloader\lk\kernel\main.c
//优化掉两个函数中一些打印日志,然后按照两个函数中的一些调用进一步优化
void kmain(void)
{
#if !defined(MACH_FPGA) && !defined(SB_LK_BRINGUP)
boot_time = get_timer(0);
#endif
// get us into some sort of thread context
thread_init_early();
// early arch stuff
arch_early_init();
// do any super early platform initialization
platform_early_init();
#if defined(MACH_FPGA) || defined(SB_LK_BRINGUP)
boot_time = get_timer(0);
#endif
// do any super early target initialization
target_early_init();
dprintf(INFO, "welcome to lk\n\n");
// deal with any static constructors
//dprintf(SPEW, "calling constructors\n");
call_constructors();
// bring up the kernel heap
//dprintf(SPEW, "initializing heap\n");
heap_init();
// initialize the threading system
//dprintf(SPEW, "initializing threads\n");
thread_init();
// initialize the dpc system
//dprintf(SPEW, "initializing dpc\n");
dpc_init();
// initialize kernel timers
//dprintf(SPEW, "initializing timers\n");
timer_init();
#ifdef MTK_LK_IRRX_SUPPORT
mtk_ir_init(0);
#endif
#if (!ENABLE_NANDWRITE)
// create a thread to complete system initialization
//dprintf(SPEW, "creating bootstrap completion thread\n");
thread_resume(thread_create("bootstrap2", &bootstrap2, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
// enable interrupts
exit_critical_section();
// become the idle thread
thread_become_idle();
#else
bootstrap_nandwrite();
#endif
}
int main(void);
static int bootstrap2(void *arg)
{
dprintf(SPEW, "top of bootstrap2()\n");
arch_init();
// XXX put this somewhere else
#if WITH_LIB_BIO
bio_init();
#endif
//#if WITH_LIB_FS
fs_init();
//#endif
// initialize the rest of the platform
//dprintf(SPEW, "initializing platform\n");
platform_init();
// initialize the target
//dprintf(SPEW, "initializing target\n");
target_init();
//dprintf(SPEW, "calling apps_init()\n");
apps_init();
return 0;
}
其它部分根据系统运行过程中的打印信息进一步优化
preloader:
1)vendor\mediatek\proprietary\bootable\bootloader\preloader\custom\8227LGO_demo\8227LGO_demo.mk
MTK_EMMC_SUPPORT_OTP=no
ATC_BOOTTIME_OPTIMIZATION=yes
2)vendor\mediatek\proprietary\bootable\bootloader\preloader\platform\ac8227l\feature.mak
####add for boottime by zhaojr
ifeq ("$(ATC_BOOTTIME_OPTIMIZATION)","yes")
C_OPTION += -DFLYAUDIO_BOOTTIME_OPTIMIZATION
endif
之后就可以针对系统模块进行优化,当需要打开的时候直接将ATC_BOOTTIME_OPTIMIZATION=no 即可。
3、内核部分
原则:
1)、内核裁剪
裁剪内核模块不需要的外设驱动,如手机系统中的NFC、震动器、sensor、摄像头sensor、LCD兼容驱动(不存在的)等、音频通路中没有使用的映射、网络模块、系统调试模块在系统配置中的选项、nandflash、MTD等模块
2)、去掉设备树中系统没涉及到的模块的配置,只保留系统使用的部分
3)、优化内核启动过程中驱动的初始化部分,尽可能的加快驱动初始化程序执行的速度,将驱动初始化时报的错误部分优化掉 (因为系统没用到)。
4)、调整内核外设模块的启动优先级顺序,这个要根据具体项目在确定
5、尝试将CPU调整到最高频率来(CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE)执行,注意很有可能导致系统高温没法过车规。一般使用CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE这种模式
6、如果系统没有使用selinux,可以将Selinux模块优化掉。注意:目前Andorid设备很少不用selinux的,尽量不要将其优化掉。
内核部分具体应该怎么优化,本文中将不再一一例举,具体项目具体分析,坚持以上原则即可。
4、ramdisk.img的优化
我们拿到主芯片原厂给的BSP代码包的时候,原始的ramdisk.img一般是不能满足我们要求的,代码中存在很多我们用不到的代码模块和init启动初始化的代码,我们需要将其优化掉,并且要保证不能影响系统的正常使用。
如:
1)优化掉init初始化进程中不需要加载的脚本,如led相关的红绿蓝相对的初始化、sensor相关、IPOD相关、ril相关、系统无用的服务、保存在的设备节点等以及device目录的系统配置项等。如果进一步优化可以针对系统设备节点生成逻辑进行优化,加快系统设备节点的生成。
2)如果系统没使用random和selinux,可以在init初始化进程进入加载的时候将其优化掉,不进行加载,可以大幅增加启动启动速度。
3)关闭init初始化进程输出的日志信息,一般情况下init进程将系统加载的服务,事件等,初始化相关的全部打印到串口中,如果全部输出,系统启动会很慢,我们将其关闭,只要在需要的时候在本地机器上调试时认为打开即可,如下:
system\core\init\Android.mk
# add for mtk init
ifneq ($(BUILD_MTK_LDVT), yes)
##init_options += -DMTK_INIT //去掉该编译选项
endif
system\core\init\init.cpp
int main(int argc, char** argv) {
if (!strcmp(basename(argv[0]), "ueventd")) {
return ueventd_main(argc, argv);
}
if (!strcmp(basename(argv[0]), "watchdogd")) {
return watchdogd_main(argc, argv);
}
// Clear the umask.
umask(0);
add_environment("PATH", _PATH_DEFPATH);
bool is_first_stage = (argc == 1) || (strcmp(argv[1], "--second-stage") != 0);
// Get the basic filesystem setup we need put together in the initramdisk
// on / and then we'll let the rc file figure out the rest.
if (is_first_stage) {
mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755");
mkdir("/dev/pts", 0755);
mkdir("/dev/socket", 0755);
mount("devpts", "/dev/pts", "devpts", 0, NULL);
mount("proc", "/proc", "proc", 0, NULL);
mount("sysfs", "/sys", "sysfs", 0, NULL);
}
// We must have some place other than / to create the device nodes for
// kmsg and null, otherwise we won't be able to remount / read-only
// later on. Now that tmpfs is mounted on /dev, we can actually talk
// to the outside world.
open_devnull_stdio();
klog_init();
//klog_set_level(KLOG_NOTICE_LEVEL);
klog_set_level(KLOG_WARNING_LEVEL); //输出日志设置成警告级别
...............................
}
system\core\init\init_parser.cpp
static void parse_new_section(struct parse_state *state, int kw,
int nargs, char **args)
{
// printf("[ %s %s ]\n", args[0], //去掉打印日志
// nargs > 1 ? args[1] : "");
switch(kw) {
............
}
int init_parse_config_file(const char* path) {
INFO("Parsing %s...\n", path);
Timer t;
std::string data;
if (!read_file(path, &data)) {
return -1;
}
data.push_back('\n'); // TODO: fix parse_config.
parse_config(path, data);
//dump_parser_state(); //去掉打印状态
NOTICE("(Parsing %s took %.2fs.)\n", path, t.duration());
return 0;
}
system\core\init\ueventd_parser.cpp
static void parse_new_section(struct parse_state *state, int kw,
int nargs, char **args)
{
// printf("[ %s %s ]\n", args[0], //去掉打印
// nargs > 1 ? args[1] : "");
switch(kw) {
case K_subsystem:
state->context = parse_subsystem(state, nargs, args);
if (state->context) {
state->parse_line = parse_line_subsystem;
return;
}
break;
}
state->parse_line = parse_line_no_op;
}
int ueventd_parse_config_file(const char *fn)
{
std::string data;
if (!read_file(fn, &data)) {
return -1;
}
data.push_back('\n'); // TODO: fix parse_config.
parse_config(fn, data);
//dump_parser_state(); //去掉打印状态
return 0;
}
system\core\rootdir\init.rc
on init
sysclktz 0
loglevel 3 //设置日志输出级别为3:警告级别
write /proc/bootprof "init: start"
.................................
5、Android framework层的优化
针对Android OS代码部分,系统启动过程中比较耗时的主要有系统类和资源的预加载、系统服务的加载、系统包扫描和Activity加载注册几个部分比较耗时,我在系统优化的时候主要关注这几个部分。
1、系统类和资源的预加载
针对这个部分,我们Android系统在启动的过程中并不是所有的类和资源都会用到,真正的Android系统只要用到其中的一部分,我们可以将资源和类分成两个部分,使用多线程的方式进行加载(系统启动时进行多进程加载,加快系统启动速度的目的),具体代码修改如下(AndroidM):
1)将系统原来的preloaded-classes文件分解成两个文件,优化加载preloaded-classes文件,而preloaded-classes2文件加在另外进程中加载,如下:
没优化之前的类文件:
frameworks\base\preloaded-classes (https://pan.baidu.com/s/1sJWm3GF3VEEmNNvUEOvKbg PWD:x7o6)
修改之后的类文件:
frameworks\base\preloaded-classes (https://pan.baidu.com/s/1JRWTgmt8FdsgrmcIglAIsQ PWD:rg6z)
frameworks\base\preloaded-classes2(https://pan.baidu.com/s/1xWjfenNFsjnfffgMZJRBIA PWD: i92a)
代码修改如下:
device\mediatek\common\device.mk
#add for preloaded-classes2, by zhaojr-20180614 //加入以下代码
PRODUCT_COPY_FILES += $(call add-to-product-copy-files-if-exists,\
frameworks/base/preloaded-classes2:system/etc/preloaded-classes2)
#property for enable/disable preloaded-classes2, by zhaojr-20180614
#PRODUCT_PROPERTY_OVERRIDES += persist.flyaudio.preload=1
frameworks\base\core\java\com\android\internal\os\ZygoteInit.java
public class ZygoteInit {
private static final String TAG = "Zygote";
..............................
.............................
static void preload() {
Log.d(TAG, "begin preload");
//zhaojr-20180614:Modify for Boottime
/***
Log.i(TAG1, "preloadMappingTable() -- start ");
PluginLoader.preloadPluginInfo(); //去掉这行
Log.i(TAG1, "preloadMappingTable() -- end ");
preloadClasses();
preloadResources();
preloadOpenGL();
preloadSharedLibraries();
preloadTextResources();
// Ask the WebViewFactory to do any initialization that must run in the zygote process,
// for memory sharing purposes.
WebViewFactory.prepareWebViewInZygote();
***/
ExecutorService executorService = Executors.newFixedThreadPool(sNThreads);
//add by zhaojr-20180614 //创建一个线程进行加载//添加代码
executorService.submit(new Runnable() {
@Override
public void run() {
PluginLoader.preloadPluginInfo();
}
});
//end
executorService.submit(new Runnable() {
@Override
public void run() {
preloadClasses();
}
});
......................
private static boolean startSystemServer(String abiList, String socketName)
throws MethodAndArgsCaller, RuntimeException {
long capabilities = posixCapabilitiesAsBits(
OsConstants.CAP_BLOCK_SUSPEND,
OsConstants.CAP_KILL,
OsConstants.CAP_NET_ADMIN,
OsConstants.CAP_NET_BIND_SERVICE,
OsConstants.CAP_NET_BROADCAST,
OsConstants.CAP_NET_RAW,
OsConstants.CAP_SYS_MODULE,
OsConstants.CAP_SYS_NICE,
OsConstants.CAP_SYS_RESOURCE,
OsConstants.CAP_SYS_TIME,
OsConstants.CAP_SYS_TTY_CONFIG
);
..............................
/* For child process */
if (pid == 0) {
if (hasSecondZygote(abiList)) {
waitForSecondaryZygote(socketName);
}
handleSystemServerProcess(parsedArgs);
} else if (pid > 0) {
/// by zhaojr-20180614: start secondary stage class preloading //添加以下代码,进行第二阶段资源加载
//if ("1".equals(SystemProperties.get("persist.flyaudio.preload", "0"))) {
Thread secLoadThread = new Thread(new preoadSecondaryStageClasses());
secLoadThread.start();
// }
}
return true;
}
.........................................
public static void main(String argv[]) {
try {
RuntimeInit.enableDdms();
/// M: Added for BOOTPROF
//MTPROF_DISABLE = "1".equals(SystemProperties.get("ro.mtprof.disable"));
MTPROF_DISABLE = false;
// Start profiling the zygote initialization.
SamplingProfilerIntegration.start();
...................................
/// M: Added for BOOTPROF
addBootEvent(new String("Zygote:Preload End"));
//add by zhaojr-20180614: set zygote priority to default, in-case been changed when booting for boottime optimize //添加以下代码
android.os.Process.setThreadPriority(
android.os.Process.THREAD_PRIORITY_DEFAULT);
//end
if (startSystemServer) {
startSystemServer(abiList, socketName);
}
Log.i(TAG, "Accepting command socket connections");
runSelectLoop(abiList);
closeServerSocket();
.................
}
}
//add by zhaojr //添加第二阶段的线程执行函数,用来加载preloaded-classes2资源文件
/**
* The path of a file that contains secondary stage classes to preload.
*/
private static final String PRELOADED_CLASSES2 = "/system/etc/preloaded-classes2";
/**
* Thread to load classes that has been intenionally missed during preloadClasses()
* @add by zhaojr-20180614
*/
public static class preoadSecondaryStageClasses implements Runnable {
public preoadSecondaryStageClasses() {}
@Override
public void run() {
InputStream is;
try {
is = new FileInputStream(PRELOADED_CLASSES2);
} catch (FileNotFoundException e) {
Log.e(TAG, "Couldn't find " + PRELOADED_CLASSES2 + ".");
return;
}
Log.i(TAG, "Preloading classes2...");
long startTime = SystemClock.uptimeMillis();
/// Added for BOOTPROF
int count = 0;
try {
BufferedReader br
= new BufferedReader(new InputStreamReader(is), 256);
String line;
while ((line = br.readLine()) != null) {
// Skip comments and blank lines.
line = line.trim();
if (line.startsWith("#") || line.equals("")) {
continue;
}
try {
if (false) {
Log.v(TAG, "Preloading " + line + "...");
}
// Load and explicitly initialize the given class. Use
// Class.forName(String, boolean, ClassLoader) to avoid repeated stack lookups
// (to derive the caller's class-loader). Use true to force initialization, and
// null for the boot classpath class-loader (could as well cache the
// class-loader of this class in a variable).
Class.forName(line, true, null);
count++;
} catch (ClassNotFoundException e) {
Log.w(TAG, "Class not found for preloading: " + line);
} catch (UnsatisfiedLinkError e) {
Log.w(TAG, "Problem preloading " + line + ": " + e);
} catch (Throwable t) {
Log.e(TAG, "Error preloading " + line + ".", t);
if (t instanceof Error) {
throw (Error) t;
}
if (t instanceof RuntimeException) {
throw (RuntimeException) t;
}
throw new RuntimeException(t);
}
}
Log.i(TAG, "...preloaded " + count + " classes2 in "
+ (SystemClock.uptimeMillis()-startTime) + "ms.");
} catch (IOException e) {
Log.e(TAG, "Error reading " + PRELOADED_CLASSES + ".", e);
} finally {
IoUtils.closeQuietly(is);
}
}
}
//end add
}
2)修改虚拟机的配置参数(因为我们的系统内存是2G),如下:
device\atc\evb3561sv_w_no2\system.prop
# 2GB DRAM recommended heap
dalvik.vm.dex2oat-Xms=32m
dalvik.vm.dex2oat-Xmx=512m
dalvik.vm.dex2oat-swap=false
dalvik.vm.heapgrowthlimit=128m
dalvik.vm.heapmaxfree=8m
dalvik.vm.heapminfree=512k
dalvik.vm.heapsize=256m
dalvik.vm.heapstartsize=16m
dalvik.vm.heaptargetutilization=0.75
dalvik.vm.image-dex2oat-Xms=64m
dalvik.vm.image-dex2oat-Xmx=64m
修改成:
# 2GB DRAM recommended heap
dalvik.vm.dex2oat-Xms=32m
dalvik.vm.dex2oat-Xmx=512m
dalvik.vm.dex2oat-swap=false
#dalvik.vm.heapgrowthlimit=128m
dalvik.vm.heapgrowthlimit=192m
dalvik.vm.heapmaxfree=8m
dalvik.vm.heapminfree=512k
dalvik.vm.heapsize=256m
dalvik.vm.heapstartsize=16m
dalvik.vm.heaptargetutilization=0.75
dalvik.vm.image-dex2oat-Xms=64m
dalvik.vm.image-dex2oat-Xmx=64m
ro.config.max_starting_bg=20 //目的防止系统启动时luncher启动时候会黑屏一段时间之后才显示,即系统启动时可以同时启动20这进程并行加载
3)修改Activity服务,进行多线程加载系统APK,代码修改如下:
frameworks\base\services\core\java\com\android\server\am\ActivityManagerService.java
public ActivityManagerService(Context systemContext) {
mContext = systemContext;
mFactoryTest = FactoryTest.getMode();
mSystemThread = ActivityThread.currentActivityThread();
Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
mHandlerThread = new ServiceThread(TAG,
android.os.Process.THREAD_PRIORITY_FOREGROUND, false /*allowIo*/);
mHandlerThread.start();
mHandler = new MainHandler(mHandlerThread.getLooper());
mUiHandler = new UiHandler();
mFgBroadcastQueue = new BroadcastQueue(this, mHandler,
"foreground", BROADCAST_FG_TIMEOUT, false);
mBgBroadcastQueue = new BroadcastQueue(this, mHandler,
"background", BROADCAST_BG_TIMEOUT, true);
mBroadcastQueues[0] = mFgBroadcastQueue;
mBroadcastQueues[1] = mBgBroadcastQueue;
mServices = new ActiveServices(this);
mProviderMap = new ProviderMap(this);
// TODO: Move creation of battery stats service outside of activity manager service.
File dataDir = Environment.getDataDirectory();
File systemDir = new File(dataDir, "system");
systemDir.mkdirs();
try {
if (SystemProperties.get("ro.have_aee_feature").equals("1")) {
exceptionLog = new ExceptionLog();
}
} catch (Exception e) {
// AEE disabled or failed to allocate AEE object, no need to show message
}
mBatteryStatsService = new BatteryStatsService(systemDir, mHandler);
mBatteryStatsService.getActiveStatistics().readLocked();
mBatteryStatsService.scheduleWriteToDisk();
mOnBattery = DEBUG_POWER ? true
: mBatteryStatsService.getActiveStatistics().getIsOnBattery();
mBatteryStatsService.getActiveStatistics().setCallback(this);
mProcessStats = new ProcessStatsService(this, new File(systemDir, "procstats"));
mAppOpsService = new AppOpsService(new File(systemDir, "appops.xml"), mHandler);
mGrantFile = new AtomicFile(new File(systemDir, "urigrants.xml"));
// User 0 is the first and only user that runs at boot.
mStartedUsers.put(UserHandle.USER_OWNER, new UserState(UserHandle.OWNER, true));
mUserLru.add(UserHandle.USER_OWNER);
updateStartedUserArrayLocked();
GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
mTrackingAssociations = "1".equals(SystemProperties.get("debug.track-associations"));
mConfiguration.setToDefaults();
mConfiguration.setLocale(Locale.getDefault());
mConfigurationSeq = mConfiguration.seq = 1;
/// flyaudio by zhaojr-20180614: Boottime optimize
//mProcessCpuTracker.init(); //去掉这个部分,放到后面进行多线程加载
mCompatModePackages = new CompatModePackages(this, systemDir, mHandler);
mIntentFirewall = new IntentFirewall(new IntentFirewallInterface(), mHandler);
mRecentTasks = new RecentTasks(this);
mStackSupervisor = new ActivityStackSupervisor(this, mRecentTasks);
mTaskPersister = new TaskPersister(systemDir, mStackSupervisor, mRecentTasks);
mProcessCpuThread = new Thread("CpuTracker") {
@Override
public void run() {
while (true) {
try {
try {
synchronized(this) {
final long now = SystemClock.uptimeMillis();
long nextCpuDelay = (mLastCpuTime.get()+MONITOR_CPU_MAX_TIME)-now;
long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
//Slog.i(TAG, "Cpu delay=" + nextCpuDelay
// + ", write delay=" + nextWriteDelay);
if (nextWriteDelay < nextCpuDelay) {
nextCpuDelay = nextWriteDelay;
}
if (nextCpuDelay > 0) {
mProcessCpuMutexFree.set(true);
this.wait(nextCpuDelay);
}
}
} catch (InterruptedException e) {
}
updateCpuStatsNow();
} catch (Exception e) {
Slog.e(TAG, "Unexpected exception collecting process stats", e);
}
}
}
};
Watchdog.getInstance().addMonitor(this);
Watchdog.getInstance().addThread(mHandler);
/// M: BMW. Init the mMwActivityMonitor @{
if (MultiWindowProxy.isSupported()) {
mMwActivityMonitor = new MwActivityMonitor(mContext, this);
}
/// @}
}
public void setSystemServiceManager(SystemServiceManager mgr) {
mSystemServiceManager = mgr;
}
public void setInstaller(Installer installer) {
mInstaller = installer;
}
private void start() {
Process.removeAllProcessGroups();
/// flyaudio by zhaojr-20180614: Boottime optimize
//mProcessCpuThread.start();
mHandler.post(new Runnable() { //add satrt
@Override
public void run() {
mProcessCpuTracker.init(); //add 在此处进行加载
mProcessCpuThread.start();
} //add
}); //add
mBatteryStatsService.publish(mContext);
mAppOpsService.publish(mContext);
Slog.d("AppOps", "AppOpsService published");
LocalServices.addService(ActivityManagerInternal.class, new LocalService());
.......................
}
.............................
}
.....................................
void enableScreenAfterBoot() {
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_ENABLE_SCREEN,
SystemClock.uptimeMillis());
mWindowManager.enableScreenAfterBoot();
synchronized (this) {
/*if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) { //暂时去掉这个部分代码,放到系统启动完成后进行加载
try {
List apps = AppGlobals.getPackageManager().
getPersistentApplications(STOCK_PM_FLAGS);
if (apps != null) {
int N = apps.size();
int i;
for (i=0; i<N; i++) {
ApplicationInfo info
= (ApplicationInfo)apps.get(i);
if (info != null &&
!info.packageName.equals("android")) {
addAppLocked(info, false, null ); //ABI override
}
}
}
} catch (RemoteException ex) {
// pm is in same process, this will never happen.
}
}
try {
if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
Slog.e(TAG, "UIDs on the system are inconsistent, you need to wipe your"
+ " data partition or your device will be unstable.");
mUiHandler.obtainMessage(SHOW_UID_ERROR_MSG).sendToTarget();
}
} catch (RemoteException e) {
}
if (!Build.isBuildConsistent()) {
Slog.e(TAG, "Build fingerprint is not consistent, warning user");
mUiHandler.obtainMessage(SHOW_FINGERPRINT_ERROR_MSG).sendToTarget();
}
long ident = Binder.clearCallingIdentity();
try {
Intent intent = new Intent(Intent.ACTION_USER_STARTED);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
| Intent.FLAG_RECEIVER_FOREGROUND);
intent.putExtra(Intent.EXTRA_USER_HANDLE, mCurrentUserId);
broadcastIntentLocked(null, null, intent,
null, null, 0, null, null, null, AppOpsManager.OP_NONE,
null, false, false, MY_PID, Process.SYSTEM_UID, mCurrentUserId);
intent = new Intent(Intent.ACTION_USER_STARTING);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
intent.putExtra(Intent.EXTRA_USER_HANDLE, mCurrentUserId);
broadcastIntentLocked(null, null, intent,
null, new IIntentReceiver.Stub() {
@Override
public void performReceive(Intent intent, int resultCode, String data,
Bundle extras, boolean ordered, boolean sticky, int sendingUser)
throws RemoteException {
}
}, 0, null, null,
new String[] {INTERACT_ACROSS_USERS}, AppOpsManager.OP_NONE,
null, true, false, MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL);
} catch (Throwable t) {
Slog.wtf(TAG, "Failed sending first user broadcasts", t);
} finally {
Binder.restoreCallingIdentity(ident);
}
*/ /暂时去掉这个部分代码,放到系统启动完成后进行加载
updateEventDispatchingLocked();
}
}
final void finishBooting() {
synchronized (this) {
if (!mBootAnimationComplete) {
mCallFinishBooting = true;
return;
}
mCallFinishBooting = false;
/// M: ALPS01959279 Ensure do finishBooting once. @{
if (mDoneFinishBooting) {
Slog.w(TAG, "Skip duplicated finish booting! mBooting = " + mBooting);
return;
}
/// @}
/// flyaudio by zhaojr-20180614: medify for Boottime optimize
//系统启动已经完成,进行之前优化代码的加载
if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
try {
List apps = AppGlobals.getPackageManager().
getPersistentApplications(STOCK_PM_FLAGS);
if (apps != null) {
int N = apps.size();
int i;
for (i=0; i<N; i++) {
ApplicationInfo info
= (ApplicationInfo)apps.get(i);
if (info != null &&
!info.packageName.equals("android")) {
addAppLocked(info, false, null /* ABI override */);
}
}
}
} catch (RemoteException ex) {
// pm is in same process, this will never happen.
}
}
try {
if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
Slog.e(TAG, "UIDs on the system are inconsistent, you need to wipe your"
+ " data partition or your device will be unstable.");
mUiHandler.obtainMessage(SHOW_UID_ERROR_MSG).sendToTarget();
}
} catch (RemoteException e) {
}
if (!Build.isBuildConsistent()) {
Slog.e(TAG, "Build fingerprint is not consistent, warning user");
mUiHandler.obtainMessage(SHOW_FINGERPRINT_ERROR_MSG).sendToTarget();
}
long ident = Binder.clearCallingIdentity();
try {
Intent intent = new Intent(Intent.ACTION_USER_STARTED);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
| Intent.FLAG_RECEIVER_FOREGROUND);
intent.putExtra(Intent.EXTRA_USER_HANDLE, mCurrentUserId);
broadcastIntentLocked(null, null, intent,
null, null, 0, null, null, null, AppOpsManager.OP_NONE,
null, false, false, MY_PID, Process.SYSTEM_UID, mCurrentUserId);
intent = new Intent(Intent.ACTION_USER_STARTING);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
intent.putExtra(Intent.EXTRA_USER_HANDLE, mCurrentUserId);
broadcastIntentLocked(null, null, intent,
null, new IIntentReceiver.Stub() {
@Override
public void performReceive(Intent intent, int resultCode, String data,
Bundle extras, boolean ordered, boolean sticky, int sendingUser)
throws RemoteException {
}
}, 0, null, null,
new String[] {INTERACT_ACROSS_USERS}, AppOpsManager.OP_NONE,
null, true, false, MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL);
} catch (Throwable t) {
Slog.wtf(TAG, "Failed sending first user broadcasts", t);
} finally {
Binder.restoreCallingIdentity(ident);
}
/// end flyaudio by zhaojr-20180614: medify for Boottime optimize
}
//开始标记系统启动完成
/// M: ALPS02042538 Avoid re-do odex after alarm snooze.
markBootComplete();
...................................
..............................................
4)优化系统服务,代码修改如下:
frameworks\base\services\java\com\android\server\SystemServer.java
/// flyaudio by zhaojr-20180614: Boottime optimize //添加
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
//end add
public final class SystemServer {
private static final String TAG = "SystemServer";
private static final String ENCRYPTING_STATE = "trigger_restart_min_framework";
private static final String ENCRYPTED_STATE = "1";
private static final long SNAPSHOT_INTERVAL = 60 * 60 * 1000; // 1hr
// The earliest supported time. We pick one day into 1970, to
// give any timezone code room without going into negative time.
private static final long EARLIEST_SUPPORTED_TIME = 86400 * 1000;
/// flyaudio by zhaojr-20180614: Boottime optimize//创建一个线程池
private static final int sNThreads = Runtime.getRuntime().availableProcessors() + 1;
ExecutorService mSystemServerInitThreadPool;
//end add
/*
* Implementation class names. TODO: Move them to a codegen class or load
* them from the build system somehow.
*/
private static final String BACKUP_MANAGER_SERVICE_CLASS =
"com.android.server.backup.BackupManagerService$Lifecycle";
............................................
public SystemServer() {
// Check for factory test mode.
mFactoryTestMode = FactoryTest.getMode();
/// flyaudio by zhaojr-20180614: Boottime optimize
mSystemServerInitThreadPool = Executors.newFixedThreadPool(sNThreads); //添加
}
private void run() {
// If a device's clock is before 1970 (before 0), a lot of
// APIs crash dealing with negative numbers, notably
// java.io.File#setLastModified, so instead we fake it and
// hope that time from cell towers or NTP fixes it shortly.
if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {
Slog.w(TAG, "System clock is before 1970; setting to 1970.");
SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);
}
.......................................................
......................................
/// flyaudio by zhaojr-20180614: Boottime optimize //优化掉,系统没用到
/*if ("1".equals(SystemProperties.get("ro.flyaudio_enhancement_cts"))) {
Build.ensureFingerprintProperty();
}
*/
......................................
//M:Add for low storage feature,to delete the reserver file.@{
/// flyaudio by zhaojr-20180614: Boottime optimize
mSystemServerInitThreadPool.submit(new Runnable() { //add
@Override
public void run() {//add end
try { //在子进程中加载
Runtime.getRuntime().exec("rm -r /data/piggybank");
} catch (IOException e) {
Slog.e(TAG, "system server init delete piggybank fail" + e);
}
} //add
}); //add end
///@}
.......................................
private void startOtherServices() {
final Context context = mSystemContext;
AccountManagerService accountManager = null;
ContentService contentService = null;
//VibratorService vibrator = null;//去掉震动器
IAlarmManager alarm = null;
IMountService mountService = null;
NetworkManagementService networkManagement = null;
NetworkStatsService networkStats = null;
NetworkPolicyManagerService networkPolicy = null;
ConnectivityService connectivity = null;
NetworkScoreService networkScore = null;
NsdService serviceDiscovery= null;
WindowManagerService wm = null;
UsbService usb = null;
SerialService serial = null;
NetworkTimeUpdateService networkTimeUpdater = null;
CommonTimeManagementService commonTimeMgmtService = null;
InputManagerService inputManager = null;
TelephonyRegistry telephonyRegistry = null;
//ConsumerIrService consumerIr = null;
AudioService audioService = null;
MmsServiceBroker mmsService = null;
/// flyaudio by zhaojr-20180614: Boottime optimize
//EntropyMixer entropyMixer = null; //去掉,系统没用到
CameraService cameraService = null;
...................................................
try {
Slog.i(TAG, "Reading configuration...");
SystemConfig.getInstance();
Slog.i(TAG, "Scheduling Policy");
ServiceManager.addService("scheduling_policy", new SchedulingPolicyService());
mSystemServiceManager.startService(TelecomLoaderService.class);
Slog.i(TAG, "Telephony Registry");
telephonyRegistry = new TelephonyRegistry(context);
ServiceManager.addService("telephony.registry", telephonyRegistry);
/// flyaudio by zhaojr-20180614: medify for Boottime optimize
//Slog.i(TAG, "Entropy Mixer");
//entropyMixer = new EntropyMixer(context); //移除掉
.....................................
Slog.i(TAG, "System Content Providers");
mActivityManagerService.installSystemProviders();
/// flyaudio by zhaojr-20180614: medify for Boottime optimize
/* //移除掉,系统没用到
Slog.i(TAG, "Vibrator Service");
vibrator = new VibratorService(context);
ServiceManager.addService("vibrator", vibrator);
Slog.i(TAG, "Consumer IR Service");
consumerIr = new ConsumerIrService(context);
ServiceManager.addService(Context.CONSUMER_IR_SERVICE, consumerIr);
*/
....................................
// Skip Bluetooth if we have an emulator kernel
// TODO: Use a more reliable check to see if this product should
// support Bluetooth - see bug 988521
/*if (isEmulator) { /// flyaudio by zhaojr-20180614: medify for Boottime optimize //仿真器,用不到,移除
Slog.i(TAG, "No Bluetooh Service (emulator)");
} else */if (mFactoryTestMode == FactoryTest.FACTORY_TEST_LOW_LEVEL) {
Slog.i(TAG, "No Bluetooth Service (factory test)");
} else if (!context.getPackageManager().hasSystemFeature
(PackageManager.FEATURE_BLUETOOTH)) {
Slog.i(TAG, "No Bluetooth Service (Bluetooth Hardware Not Present)");
} else if (disableBluetooth) {
Slog.i(TAG, "Bluetooth Service disabled by config");
} else {
Slog.i(TAG, "Bluetooth Service");
mSystemServiceManager.startService(BluetoothService.class);
}
} catch (RuntimeException e) {
........................................
.....................................
/// M: Start DataShaping Service @{
if ("1".equals(SystemProperties.get("persist.mtk.datashaping.support"))) {
try {
Slog.i(TAG, "Start DataShaping Service");
mSystemServiceManager.startService(DATASHPAING_SERVICE_CLASS);
} catch (Throwable e){
Slog.e(TAG, "Failure to start DataShaping Service", e);
}
}
/// @}
}
/// flyaudio by zhaojr-20180614: medify for Boottime optimize
/*if (!disableNonCoreServices) {//去掉,系统用不到
try {
Slog.i(TAG, "UpdateLock Service");
ServiceManager.addService(Context.UPDATE_LOCK_SERVICE,
new UpdateLockService(context));
} catch (Throwable e) {
reportWtf("starting UpdateLockService", e);
}
}*/
/*
* MountService has a few dependencies: Notification Manager and
* AppWidget Provider. Make sure MountService is completely started
* first before continuing.
*/
if (mountService != null && !mOnlyCore) {
try {
mountService.waitForAsecScan();
} catch (RemoteException ignored) {
}
}
......................................
if ("1".equals(SystemProperties.get("ro.mtk_sensorhub_support"))) {
try {
Slog.d(TAG, "SensorHubService");
ServiceManager.addService(ISensorHubManager.SENSORHUB_SERVICE,
new SensorHubService(context));
} catch (Throwable e) {
Slog.e(TAG, "starting SensorHub Service", e);
}
}
///@}
/// flyaudio by zhaojr-20180614: medify for Boottime optimize
/*if (!disableNonCoreServices) { //移除掉,系统用不到
mSystemServiceManager.startService(DockObserver.class);
}
try {
Slog.i(TAG, "Wired Accessory Manager");
// Listen for wired headset changes
inputManager.setWiredAccessoryCallbacks(
new WiredAccessoryManager(context, inputManager));
} catch (Throwable e) {
reportWtf("starting WiredAccessoryManager", e);
}*/
if (!disableNonCoreServices) {
if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_MIDI)) {
// Start MIDI Manager service
mSystemServiceManager.startService(MIDI_SERVICE_CLASS);
}
.............................................
...........................................
if (!disableNonCoreServices) {
ServiceManager.addService(GraphicsStatsService.GRAPHICS_STATS_SERVICE,
new GraphicsStatsService(context));
}
// Enable this service for CTS test
/// flyaudio by zhaojr-20180614: medify for Boottime optimize //移除掉,系统用不到
//if ("1".equals(SystemProperties.get("ro.flyaudio_enhancement_cts"))) {
// if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_PRINTING)) {
// mSystemServiceManager.startService(PRINT_MANAGER_SERVICE_CLASS);
// }
// }
mSystemServiceManager.startService(RestrictionsManagerService.class);
mSystemServiceManager.startService(MediaSessionService.class);
if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_HDMI_CEC)) {
mSystemServiceManager.startService(HdmiControlService.class);
}
/// flyaudio by zhaojr-20180614: medify for Boottime optimize//移除掉,系统用不到
//if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_LIVE_TV)) {
// mSystemServiceManager.startService(TvInputManagerService.class);
//}
if (!disableNonCoreServices) {
try {
Slog.i(TAG, "Media Router Service");
mediaRouter = new MediaRouterService(context);
ServiceManager.addService(Context.MEDIA_ROUTER_SERVICE, mediaRouter);
} catch (Throwable e) {
reportWtf("starting MediaRouterService", e);
}
mSystemServiceManager.startService(TrustManagerService.class);
/// flyaudio by zhaojr-20180614: medify for Boottime optimize//移除掉,系统用不到
// if ("1".equals(SystemProperties.get("ro.flyaudio_enhancement_cts"))) {
// mSystemServiceManager.startService(FingerprintService.class);
// }
try {
Slog.i(TAG, "BackgroundDexOptService");
BackgroundDexOptService.schedule(context, 0);
} catch (Throwable e) {
reportWtf("starting BackgroundDexOptService", e);
}
}
..................................................
/// M: add for HDMI feature @{
/// flyaudio remove by zhaojr-20180614: medify for Boottime optimize
/*if (!disableNonCoreServices //系统没有使用HDMI,移除
&& SystemProperties.get("ro.mtk_hdmi_support").equals("1")) {
try {
Slog.i(TAG, "HDMI Manager Service");
hdmiManager = new MtkHdmiManagerService(context);
ServiceManager.addService(Context.HDMI_SERVICE,
hdmiManager.asBinder());
} catch (Throwable e) {
Slog.e(TAG, "Failure starting MtkHdmiManager", e);
}
}*/
/// @}
........................................................
// MMS service broker
mmsService = mSystemServiceManager.startService(MmsServiceBroker.class);
// It is now time to start up the app processes...
/*
try { //移除震动器服务
vibrator.systemReady();
} catch (Throwable e) {
reportWtf("making Vibrator Service ready", e);
}
*/
if (lockSettings != null) {
try {
lockSettings.systemReady();
} catch (Throwable e) {
reportWtf("making Lock Settings Service ready", e);
}
}
..................................
......................................
try {
// TODO: use boot phase
mPowerManagerService.systemReady(mActivityManagerService.getAppOpsService());
} catch (Throwable e) {
reportWtf("making Power Manager Service ready", e);
}
/// flyaudio medify by zhaojr-20180614: medify for Boottime optimize
mSystemServerInitThreadPool.submit(new Runnable() { //add start //包管理服务在子进程中运行
@Override
public void run() { //add end
try {
mPackageManagerService.systemReady();
} catch (Throwable e) {
reportWtf("making Package Manager Service ready", e);
}
}//add stsrt
}); //add end
try {
// TODO: use boot phase and communicate these flags some other way
mDisplayManagerService.systemReady(safeMode, mOnlyCore);
} catch (Throwable e) {
reportWtf("making Display Manager Service ready", e);
}
..................................
try {
startSystemUi(context);
} catch (Throwable e) {
reportWtf("starting System UI", e);
}
/// flyaudio medify by zhaojr-20180614: medify for Boottime optimize
//将一些服务移到主线程中执行,这些需要在系统启动时候一定要先启动,其它的服务另启动一个线程进行加载
try {
if (locationF != null) locationF.systemRunning();
if (ansF != null) ansF.systemRunning();
} catch (Throwable e) {
reportWtf("Notifying Location Service running", e);
}
try {
if (wallpaperF != null) wallpaperF.systemRunning();
} catch (Throwable e) {
reportWtf("Notifying WallpaperService running", e);
}
try {
if (audioServiceF != null) audioServiceF.systemReady();
} catch (Throwable e) {
reportWtf("Notifying AudioService running", e);
}
// It is now okay to let the various system services start their
// third party code...
mSystemServiceManager.startBootPhase(
SystemService.PHASE_THIRD_PARTY_APPS_CAN_START);
//end medify by zhaojr-20180614
try {
if (xserviceF != null) xserviceF.systemRunning();
} catch (Throwable e) {
reportWtf("Notifying X Service running", e);
}
}
}); //add zhaojr /// flyaudio medify by zhaojr-20180614: medify for Boottime optimize
mSystemServerInitThreadPool.submit(new Runnable() {
@Override
public void run() { //end add
try {
if (networkScoreF != null) networkScoreF.systemReady();
} catch (Throwable e) {
reportWtf("making Network Score Service ready", e);
}
....................................
try {
if (mmsServiceF != null) mmsServiceF.systemRunning();
} catch (Throwable e) {
reportWtf("Notifying MmsService running", e);
}
Slog.i(TAG, "WebViewFactory preparation");//将第一阶段的服务移到到后面来加载
WebViewFactory.prepareWebViewInSystemServer();
/// M: add for PerfService feature @{
................
});
//add by zhaojr-20180614
mSystemServerInitThreadPool.shutdown();//完成后关闭线程
//add end
/// M: RecoveryManagerService @{
try {
if (mRecoveryManagerService != null) {
mRecoveryManagerService.stopBootMonitor();
}
} catch (Throwable e) {
reportWtf("Failure Stop Boot Monitor", e);
}
/// @}
5、如果系统是冷启动,不用开关机休眠逻辑的话,需要优化电源管理服务,否则会直接导致系统重启,修改如下:
frameworks\base\services\core\java\com\android\server\power\PowerManagerService.java
//ATC add begin:
private int mScreenBrightSetting;
private int mScreenContrastSetting;
private int mScreenHueSetting;
private int mScreenSaturationSetting;
//ATC add end.
..................................
private void updateIsPoweredLocked(int dirty) {
if ((dirty & DIRTY_BATTERY_STATE) != 0) {
final boolean wasPowered = mIsPowered;
final int oldPlugType = mPlugType;
final boolean oldLevelLow = mBatteryLevelLow;
//修改以下的电源管理方式,主要针对电池,即可电池电量处于100%,充电器一直插着
//mIsPowered = mBatteryManagerInternal.isPowered(BatteryManager.BATTERY_PLUGGED_ANY);
//mPlugType = mBatteryManagerInternal.getPlugType();
//mBatteryLevel = mBatteryManagerInternal.getBatteryLevel();
//mBatteryLevelLow = mBatteryManagerInternal.getBatteryLevelLow();
mIsPowered = true;
mPlugType = BatteryManager.BATTERY_PLUGGED_AC;
mBatteryLevel = 100;
mBatteryLevelLow = false;
if (DEBUG_SPEW) {
Slog.d(TAG, "updateIsPoweredLocked: wasPowered=" + wasPowered
+ ", mIsPowered=" + mIsPowered
+ ", oldPlugType=" + oldPlugType
+ ", mPlugType=" + mPlugType
+ ", mBatteryLevel=" + mBatteryLevel);
}
............................
..............................
}
}
private void updateStayOnLocked(int dirty) {
if ((dirty & (DIRTY_BATTERY_STATE | DIRTY_SETTINGS)) != 0) {
final boolean wasStayOn = mStayOn;
if (mStayOnWhilePluggedInSetting != 0
&& !isMaximumScreenOffTimeoutFromDeviceAdminEnforcedLocked()) {
//mStayOn = mBatteryManagerInternal.isPowered(mStayOnWhilePluggedInSetting);
mStayOn = true; //充电器是一直插入
} else {
mStayOn = false;
}
if (mStayOn != wasStayOn) {
mDirty |= DIRTY_STAY_ON;
}
}
}
private boolean isBeingKeptAwakeLocked() {
//keep system awake //保持系统一直唤醒状态中
return true;
//end keep system awake
/*
return mStayOn
|| mProximityPositive
|| (mWakeLockSummary & WAKE_LOCK_STAY_AWAKE) != 0
|| (mUserActivitySummary & (USER_ACTIVITY_SCREEN_BRIGHT
| USER_ACTIVITY_SCREEN_DIM)) != 0
|| mScreenBrightnessBoostInProgress;
*/
}
修改:
device/atc/ac83xx_evb/system.prop
frameworks\base\services\core\java\com\android\server\BatteryService.java
针对冷启动,没有使用休眠和唤醒的修改:
device/atc/ac83xx_evb/system.prop 添加:
# add by zhaojr for battery
persist.sys.battery.invalid=true
frameworks\base\services\core\java\com\android\server\BatteryService.java 修改如下:
public final class BatteryService extends SystemService {
private static final String TAG = BatteryService.class.getSimpleName();
.................................................
private BatteryProperties mBatteryProps = new BatteryProperties(); //添加属性读取变量
..............................................
//private Led mLed; //去掉充电时led的显示
................................
private boolean mBootCompleted = false;
//power s
private boolean mSwitcher = false; //定义切换开关
//power e
public BatteryService(Context context) {
super(context);
mContext = context;
mHandler = new Handler(true /*async*/);
// mLed = new Led(context, getLocalService(LightsManager.class)); //去掉led
mBatteryStats = BatteryStatsService.getService();
...................................................
// watch for invalid charger messages if the invalid_charger switch exists
if (new File("/sys/devices/virtual/switch/invalid_charger/state").exists()) {
mInvalidChargerObserver.startObserving(
"DEVPATH=/devices/virtual/switch/invalid_charger");
}
//power s //添加
if (SystemProperties.getBoolean("persist.sys.battery.invalid", false)) {
mSwitcher = true;
}
//power e
}
@Override
public void onStart() {
/* //系统冷启动应当从来不执行以下代码
IBinder b = ServiceManager.getService("batteryproperties");
final IBatteryPropertiesRegistrar batteryPropertiesRegistrar =
IBatteryPropertiesRegistrar.Stub.asInterface(b);
try {
batteryPropertiesRegistrar.registerListener(new BatteryListener());
} catch (RemoteException e) {
// Should never happen.
}
*/
if (SystemProperties.get("ro.mtk_ipo_support").equals("1")) {
IntentFilter filter = new IntentFilter();
filter.addAction(IPO_POWER_ON);
filter.addAction(IPO_POWER_OFF);
mContext.registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (IPO_POWER_ON.equals(intent.getAction())) {
mIPOShutdown = false;
mIPOBoot = true;
// Let BatteryService to handle low battery warning.
mLastBatteryLevel = mLowBatteryWarningLevel + 1;
update(mBatteryProps);
} else
if (IPO_POWER_OFF.equals(intent.getAction())) {
mIPOShutdown = true;
}
}
}, filter);
}
mBatteryProps.chargerWirelessOnline = false;
mBatteryProps.chargerAcOnline = false;
mBatteryProps.chargerUsbOnline = false;
mBatteryProps.batteryLevel = 0;
mBatteryProps.batteryLevel_smb = 0;
mBatteryProps.batteryStatus = 1;
mBatteryProps.batteryStatus_smb = 1;
mBatteryProps.batteryHealth = 1;
mBatteryProps.batteryPresent = false;
mBatteryProps.batteryPresent_smb = false;
mBatteryProps.batteryVoltage = 0;
mBatteryProps.batteryTemperature = 0;
mBatteryProps.batteryTechnology = "AC";
update(new BatteryProperties());
// publishBinderService("battery", new BinderService());
publishLocalService(BatteryManagerInternal.class, new LocalService());
}
....................................
private void update(BatteryProperties props) {
synchronized (mLock) {
if (!mUpdatesStopped) {
//mBatteryProps = props; //优化
props = mBatteryProps;
if (SystemProperties.get("ro.mtk_ipo_support").equals("1")) {
if (mIPOShutdown)
return;
}
// Process the new values.
if (mBootCompleted)
processValuesLocked(false);
} else {
mLastBatteryProps.set(props);
}
}
}
..............................................
if (mLastBatteryVoltage != mBatteryProps.batteryVoltage) {
Log.d(TAG, "mBatteryVoltage=" + mBatteryProps.batteryVoltage + ", batteryLevel=" + mBatteryProps.batteryLevel_smb);
}
// Update the battery LED
// mLed.updateLightsLocked(); //不显示电池充电电量
// Let the battery stats keep track of the current level.
................................................
private final class LocalService extends BatteryManagerInternal {
@Override
public boolean isPowered(int plugTypeSet) {
synchronized (mLock) {
//power s //修改
// Because this is Vehicle power, so we return true for isPowered.
if (mSwitcher) {
return true; //Return to Ture forever
} else {
return isPoweredLocked(plugTypeSet);
}
}
}
@Override
public int getPlugType() {
synchronized (mLock) {
//power s //充电器一直插入
//Because this is Vehicle power, so we return "BATTERY_PLUGGED_AC" for plugtype.
if (mSwitcher) {
return BatteryManager.BATTERY_PLUGGED_AC;
} else {
return mPlugType;
}
//power e
}
}
@Override
public int getBatteryLevel() {
synchronized (mLock) {
//power s //电池电量显示100%
//Because this is Vehicle power, so we return "100%" for batterylevel.
if (mSwitcher) {
return 100;
} else {
return mBatteryProps.batteryLevel;
}
//power e
}
}
@Override
public boolean getBatteryLevelLow() {
synchronized (mLock) {
//power s //不是低电量
//Because this is Vehicle power, so we always return false for batterylevellow.
if (mSwitcher) {
return false;
} else {
return mBatteryLevelLow;
}
//power e
}
}
6、将本地防火墙放到系统启动完成之后再加载,具体修改如下:
1)添加一个优化全局开关
device\atc\evb3561sv_w_no2\ProjectConfig.mk
AUTO_ADD_GLOBAL_DEFINE_BY_NAME = ATC_BOOTTIME_OPTIMIZATION
............................
#Boot Time Optimization
ATC_BOOTTIME_OPTIMIZATION = yes
.....................................
2)修改本地网络模块
system\netd\server\Android.mk 添加以下编译开关
ifeq ($(strip $(ATC_BOOTTIME_OPTIMIZATION)),yes)
LOCAL_CFLAGS += -DBOOTTIME_OPTIMIZATION
endif
添加接口函数:
修改:system\netd\server\FirewallController.h
class FirewallController {
public:
FirewallController();
int setupIptablesHooks(void);
/* Added by Ce.Gao. */
#ifdef BOOTTIME_OPTIMIZATION //添加公共接口函数
int setupIptablesHooksOnBoot(void);
#endif
/* End of addtions by Ce.Gao. */
int enableFirewall(FirewallType);
int disableFirewall(void);
int isFirewallEnabled(void);
............................
private:
FirewallType mFirewallType;
int attachChain(const char*, const char*);
int detachChain(const char*, const char*);
int createChain(const char*, const char*, FirewallType);
/* Added by Ce.Gao. */
#ifdef BOOTTIME_OPTIMIZATION //添加私有接口函数
int createChainOnBoot(const char*, FirewallType);
#endif
/* End of addtions by Ce.Gao. */
FirewallType getFirewallType(ChildChain);
int refreshPkgUidList(const char *file_path, int uid, bool add);
};
函数实现:
修改:system\netd\server\FirewallController.cpp
/**
* Added by Ce.Gao.
* This function calling "createChainOnBoot" is used on boot to accelerate netd starting speed.
*/
#ifdef BOOTTIME_OPTIMIZATION //接口实现
int FirewallController::setupIptablesHooksOnBoot(void) {
int res = 0;
// child chains are created but not attached, they will be attached explicitly.
FirewallType firewallType = getFirewallType(DOZABLE);
res |= createChainOnBoot(LOCAL_DOZABLE, firewallType);
firewallType = getFirewallType(STANDBY);
res |= createChainOnBoot(LOCAL_STANDBY, firewallType);
return res;
}
#endif
/**
* End of addtions by Ce.Gao.
*/
int FirewallController::setupIptablesHooks(void) {
int res = 0;
/* Add macro #ifndef by Ce.Gao. */
/**
* This part is added by MTK to enhance firewall.
* Delete this part to fasten netd running speed when optimizing boot time.
*/
#ifndef BOOTTIME_OPTIMIZATION //启动阶段先去掉防火墙加载
/*********************************************************************
* mtk03594: Support tencent firewall
* mount child chain,FIREWALL_MOBILE and FIREWALL_WIFI, to FIREWALL
*********************************************************************/
res |= execIptables(V4V6, "-F", FIREWALL, NULL);
res |= execIptables(V4V6, "-A", FIREWALL, "-o", "ppp+", "-j", FIREWALL_MOBILE, NULL);
res |= execIptables(V4V6, "-A", FIREWALL, "-o", "ccmni+", "-j", FIREWALL_MOBILE, NULL);
res |= execIptables(V4V6, "-A", FIREWALL, "-o", "ccemni+", "-j", FIREWALL_MOBILE, NULL);
res |= execIptables(V4V6, "-A", FIREWALL, "-o", "usb+", "-j", FIREWALL_MOBILE, NULL);
res |= execIptables(V4V6, "-A", FIREWALL, "-o", "cc2mni+", "-j", FIREWALL_MOBILE, NULL);
res |= execIptables(V4V6, "-A", FIREWALL, "-o", "wlan+", "-j", FIREWALL_WIFI, NULL);
#endif
/* End of addtions by Ce.Gao. */
// child chains are created but not attached, they will be attached explicitly.
FirewallType firewallType = getFirewallType(DOZABLE);
res |= createChain(LOCAL_DOZABLE, LOCAL_INPUT, firewallType);
firewallType = getFirewallType(STANDBY);
res |= createChain(LOCAL_STANDBY, LOCAL_INPUT, firewallType);
return res;
}
.................................
/**
* Added by Ce.Gao.
* This function is used on boot to accelerate netd starting speed.
* When system is booting, the iptables rules are clean.
* It is not nessesary to clear iptables chains before adding them.
*/
#ifdef BOOTTIME_OPTIMIZATION
int FirewallController::createChainOnBoot(const char* childChain, FirewallType type) {
int res = 0;
res |= execIptables(V4V6, "-t", TABLE, "-N", childChain, NULL);
if (type == WHITELIST) {
// Allow ICMPv6 packets necessary to make IPv6 connectivity work. http://b/23158230 .
for (size_t i = 0; i < ARRAY_SIZE(ICMPV6_TYPES); i++) {
res |= execIptables(V6, "-A", childChain, "-p", "icmpv6", "--icmpv6-type",
ICMPV6_TYPES[i], "-j", "RETURN", NULL);
}
// create default white list for system uid range
char uidStr[16];
sprintf(uidStr, "0-%d", AID_APP - 1);
res |= execIptables(V4V6, "-A", childChain, "-m", "owner", "--uid-owner",
uidStr, "-j", "RETURN", NULL);
// create default rule to drop all traffic
res |= execIptables(V4V6, "-A", childChain, "-j", "DROP", NULL);
}
return res;
}
#endif
/**
* End of addtions by Ce.Gao.
*/
修改:system\netd\server\CommandListener.h
class CommandListener : public FrameworkListener {
static TetherController *sTetherCtrl;
static NatController *sNatCtrl;
static PppController *sPppCtrl;
static SoftapController *sSoftapCtrl;
static BandwidthController *sBandwidthCtrl;
static IdletimerController *sIdletimerCtrl;
static InterfaceController *sInterfaceCtrl;
static ResolverController *sResolverCtrl;
static FirewallController *sFirewallCtrl;
static ClatdController *sClatdCtrl;
static StrictController *sStrictCtrl;
static PPPOEController *sPPPOECtrl;
static NetInfoListener *sNetInfo;
static IPv6TetherController *sIPv6TetherCtrl;
static ThroughputMonitor *sThroughputMonitor;
static ThrottleController *sThrottleCtrl;
/* M: HetComm Feature */
static DualOnController *sDualOnCtrl;
public:
static NetworkController *sNetCtrl;
CommandListener();
virtual ~CommandListener() {}
/* Added by Ce.Gao. */
#ifdef BOOTTIME_OPTIMIZATION //添加接口
static void setupNetworkRulesOnBoot(void);
#endif
/* End of addtions by Ce.Gao. */
private:
.....................................
修改:system\netd\server\CommandListener.cpp
static const char* FILTER_INPUT[] = {
// Bandwidth should always be early in input chain, to make sure we
// correctly count incoming traffic against data plan.
BandwidthController::LOCAL_INPUT,
/* Add macro #ifndef by Ce.Gao. */
#ifndef BOOTTIME_OPTIMIZATION
// mtk03594: Support enhanced firewall @{ //将防火墙去掉
FirewallController::FIREWALL,
///@}
#endif
/* End of addtions by Ce.Gao. */
FirewallController::LOCAL_INPUT,
NULL,
};
............................................
.............................................
static const char* FILTER_OUTPUT[] = {
OEM_IPTABLES_FILTER_OUTPUT,
/* Add macro #ifndef by Ce.Gao. */
#ifndef BOOTTIME_OPTIMIZATION
// mtk03594: Support enhanced firewall @{
FirewallController::FIREWALL,
///@}
#endif
/* End of addtions by Ce.Gao. */
FirewallController::LOCAL_OUTPUT,
StrictController::LOCAL_OUTPUT,
BandwidthController::LOCAL_OUTPUT,
NULL,
};
......................................
......................................
/* Add macro #ifndef by Ce.Gao. */
/**
* This part is added by MTK to implement HetComm feature.
* Delete this unnesessary part when optimizing boot time.
*/
#ifndef BOOTTIME_OPTIMIZATION
/* M: HetComm Feature */
static const char* MANGLE_OUTPUT[] = {
DualOnController::LOCAL_MANGLE_OUTPUT,
NULL,
};
#endif
/* End of addtions by Ce.Gao. */
..................................................
static const char* NAT_POSTROUTING[] = {
NatController::LOCAL_NAT_POSTROUTING,
/* Add macro #ifndef by Ce.Gao. */
#ifndef BOOTTIME_OPTIMIZATION
DualOnController::LOCAL_NAT_POSTROUTING,
#endif
/* End of addtions by Ce.Gao. */
NULL,
};
/* Add macro #ifndef by Ce.Gao. */
#ifndef BOOTTIME_OPTIMIZATION
// mtk03594: Support enhanced firewall @{
static const char* FILTER_FIREWALL[] = {
FirewallController::FIREWALL_MOBILE,
FirewallController::FIREWALL_WIFI,
NULL,
};
///@}
#endif
/* End of addtions by Ce.Gao. */
/**
* Added by Ce.Gao.
* This function is used on boot to accelerate netd starting speed.
* When system is booting, the iptables rules are clean.
* It is not nessesary to clear iptables chains before adding them.
*/
#ifdef BOOTTIME_OPTIMIZATION
static void createChildChainsOnBoot(IptablesTarget target, const char* table, const char* parentChain,
const char** childChains) {
const char** childChain = childChains;
do {
/**
* Iptables rules are clean on boot.
* There is no need to clear chains.
* Ignore cleaning rules operations to speed up.
*/
execIptables(target, "-t", table, "-N", *childChain, NULL);
execIptables(target, "-t", table, "-A", parentChain, "-j", *childChain, NULL);
} while (*(++childChain) != NULL);
}
#endif
static const char* NAT_POSTROUTING[] = {
NatController::LOCAL_NAT_POSTROUTING,
/* Add macro #ifndef by Ce.Gao. */
#ifndef BOOTTIME_OPTIMIZATION
DualOnController::LOCAL_NAT_POSTROUTING,
#endif
/* End of addtions by Ce.Gao. */
NULL,
};
/* Add macro #ifndef by Ce.Gao. */
#ifndef BOOTTIME_OPTIMIZATION
// mtk03594: Support enhanced firewall @{
static const char* FILTER_FIREWALL[] = {
FirewallController::FIREWALL_MOBILE,
FirewallController::FIREWALL_WIFI,
NULL,
};
///@}
#endif
/* End of addtions by Ce.Gao. */
/**
* Added by Ce.Gao.
* This function is used on boot to accelerate netd starting speed.
* When system is booting, the iptables rules are clean.
* It is not nessesary to clear iptables chains before adding them.
*/
#ifdef BOOTTIME_OPTIMIZATION
static void createChildChainsOnBoot(IptablesTarget target, const char* table, const char* parentChain,
const char** childChains) {
const char** childChain = childChains;
do {
/**
* Iptables rules are clean on boot.
* There is no need to clear chains.
* Ignore cleaning rules operations to speed up.
*/
execIptables(target, "-t", table, "-N", *childChain, NULL);
execIptables(target, "-t", table, "-A", parentChain, "-j", *childChain, NULL);
} while (*(++childChain) != NULL);
}
#endif
/**
* End of addtions by Ce.Gao.
*/
..................................
CommandListener::CommandListener() :
FrameworkListener("netd", true) {
/* Added by Ce.Gao. */
#ifdef BOOTTIME_OPTIMIZATION //添加
char value[PROPERTY_VALUE_MAX];
#endif
/* End of addtions by Ce.Gao. */
registerCmd(new InterfaceCmd());
registerCmd(new IpFwdCmd());
registerCmd(new TetherCmd());
registerCmd(new NatCmd());
registerCmd(new ListTtysCmd());
registerCmd(new PppdCmd());
registerCmd(new SoftapCmd());
registerCmd(new BandwidthControlCmd());
registerCmd(new IdletimerControlCmd());
registerCmd(new ResolverCmd());
registerCmd(new FirewallCmd());
registerCmd(new ClatdCmd());
registerCmd(new NetworkCommand());
registerCmd(new StrictCmd());
registerCmd(new Ipv6FwdCmd());
registerCmd(new IPv6TetherCmd());
registerCmd(new ThroughputCmd());
registerCmd(new PPPOEctlCmd());
registerCmd(new NetInfoCmd());
/* M: HetComm Feature */
registerCmd(new DualOnCmd());
/* M: HetComm Feature */
if (!sDualOnCtrl)
sDualOnCtrl = new DualOnController();
if (!sIPv6TetherCtrl)
sIPv6TetherCtrl = new IPv6TetherController();
if (!sNetInfo)
sNetInfo = new NetInfoListener();
if (!sThroughputMonitor)
sThroughputMonitor = new ThroughputMonitor();
if (!sThrottleCtrl)
sThrottleCtrl = new ThrottleController();
if (!sNetCtrl)
sNetCtrl = new NetworkController();
if (!sTetherCtrl)
sTetherCtrl = new TetherController();
if (!sNatCtrl)
sNatCtrl = new NatController();
if (!sPppCtrl)
sPppCtrl = new PppController();
if (!sSoftapCtrl)
sSoftapCtrl = new SoftapController();
if (!sBandwidthCtrl)
sBandwidthCtrl = new BandwidthController();
if (!sIdletimerCtrl)
sIdletimerCtrl = new IdletimerController();
if (!sResolverCtrl)
sResolverCtrl = new ResolverController();
if (!sFirewallCtrl)
sFirewallCtrl = new FirewallController();
if (!sInterfaceCtrl)
sInterfaceCtrl = new InterfaceController();
if (!sClatdCtrl)
sClatdCtrl = new ClatdController(sNetCtrl);
if (!sStrictCtrl)
sStrictCtrl = new StrictController();
/**
* Added by Ce.Gao.
* When system is booting, the iptables rules are clean.
* Call the special "setupNetworkRulesOnBoot" function
* to accelerate netd starting speed.
*/
#ifdef BOOTTIME_OPTIMIZATION
property_get("sys.boot_completed", value, "0");
if (!strcmp(value, "0")){ /* The system is booting. */
setupNetworkRulesOnBoot();
return;
}
#endif
/**
* End of addtions by Ce.Gao.
*/
/*
* This is the only time we touch top-level chains in iptables; controllers
* should only mutate rules inside of their children chains, as created by
* the constants above.
*
* Modules should never ACCEPT packets (except in well-justified cases);
* they should instead defer to any remaining modules using RETURN, or
* otherwise DROP/REJECT.
*/
// Create chains for children modules
createChildChains(V4V6, "filter", "INPUT", FILTER_INPUT);
createChildChains(V4V6, "filter", "FORWARD", FILTER_FORWARD);
createChildChains(V4V6, "filter", "OUTPUT", FILTER_OUTPUT);
createChildChains(V4V6, "raw", "PREROUTING", RAW_PREROUTING);
createChildChains(V4V6, "mangle", "POSTROUTING", MANGLE_POSTROUTING);
createChildChains(V4, "mangle", "FORWARD", MANGLE_FORWARD);
createChildChains(V4, "nat", "PREROUTING", NAT_PREROUTING);
createChildChains(V4, "nat", "POSTROUTING", NAT_POSTROUTING);
// Let each module setup their child chains
setupOemIptablesHook();
/* Add macro #ifndef by Ce.Gao. */
/**
* This part is added by MTK to implement HetComm and enhanced firewall.
* Delete this unnesessary part when optimizing boot time.
*/
#ifndef BOOTTIME_OPTIMIZATION //优化
/* M: HetComm Feature */
createChildChains(V4, "mangle", "OUTPUT", MANGLE_OUTPUT);
// Support enhanced firewall @{
createChildChains(V4V6, "filter", "firewall", FILTER_FIREWALL);
///@}
#endif
/* End of addtions by Ce.Gao. */
/* When enabled, DROPs all packets except those matching rules. */
sFirewallCtrl->setupIptablesHooks();
/* Does DROPs in FORWARD by default */
sNatCtrl->setupIptablesHooks();
/*
* Does REJECT in INPUT, OUTPUT. Does counting also.
* No DROP/REJECT allowed later in netfilter-flow hook order.
*/
sBandwidthCtrl->setupIptablesHooks();
/*
* Counts in nat: PREROUTING, POSTROUTING.
* No DROP/REJECT allowed later in netfilter-flow hook order.
*/
sIdletimerCtrl->setupIptablesHooks();
sBandwidthCtrl->enableBandwidthControl(false);
if (int ret = RouteController::Init(NetworkController::LOCAL_NET_ID)) {
ALOGE("failed to initialize RouteController (%s)", strerror(-ret));
}
/* Add macro #ifndef by Ce.Gao. */
/**
* This part is added by MTK to implement HetComm Feature.
* Delete this unnesessary part when optimizing boot time.
*/
#ifndef BOOTTIME_OPTIMIZATION //优化
/* M: HetComm Feature */
sDualOnCtrl->setupIptablesHooks();
#endif
/* End of addtions by Ce.Gao. */
}
/* Added by Ce.Gao. */
#ifdef BOOTTIME_OPTIMIZATION //添加
void CommandListener::setupNetworkRulesOnBoot(void){
ALOGI("CommandListener constructor calls setupNetworkRulesOnBoot when system is booting!");
/*
* This is the only time we touch top-level chains in iptables; controllers
* should only mutate rules inside of their children chains, as created by
* the constants above.
*
* Modules should never ACCEPT packets (except in well-justified cases);
* they should instead defer to any remaining modules using RETURN, or
* otherwise DROP/REJECT.
*/
// Create chains for children modules
createChildChainsOnBoot(V4V6, "filter", "INPUT", FILTER_INPUT);
createChildChainsOnBoot(V4V6, "filter", "FORWARD", FILTER_FORWARD);
createChildChainsOnBoot(V4V6, "filter", "OUTPUT", FILTER_OUTPUT);
createChildChainsOnBoot(V4V6, "raw", "PREROUTING", RAW_PREROUTING);
createChildChainsOnBoot(V4V6, "mangle", "POSTROUTING", MANGLE_POSTROUTING);
createChildChainsOnBoot(V4, "mangle", "FORWARD", MANGLE_FORWARD);
createChildChainsOnBoot(V4, "nat", "PREROUTING", NAT_PREROUTING);
createChildChainsOnBoot(V4, "nat", "POSTROUTING", NAT_POSTROUTING);
// Let each module setup their child chains
setupOemIptablesHook();
/* When enabled, DROPs all packets except those matching rules. */
sFirewallCtrl->setupIptablesHooksOnBoot();
/* Does DROPs in FORWARD by default */
sNatCtrl->setupIptablesHooksOnBoot();
/*
* Does REJECT in INPUT, OUTPUT. Does counting also.
* No DROP/REJECT allowed later in netfilter-flow hook order.
*/
sBandwidthCtrl->setupIptablesHooksOnBoot();
/*
* Counts in nat: PREROUTING, POSTROUTING.
* No DROP/REJECT allowed later in netfilter-flow hook order.
*/
sIdletimerCtrl->setupIptablesHooks();
if (int ret = RouteController::Init(NetworkController::LOCAL_NET_ID)) {
ALOGE("failed to initialize RouteController (%s)", strerror(-ret));
}
}
#endif
/* End of addtions by Ce.Gao. */
修改:system\netd\server\BandwidthController.h
class BandwidthController {
public:
class TetherStats {
public:
TetherStats(void)
: rxBytes(-1), rxPackets(-1),
txBytes(-1), txPackets(-1) {};
TetherStats(std::string intIfn, std::string extIfn,
int64_t rxB, int64_t rxP,
int64_t txB, int64_t txP)
: intIface(intIfn), extIface(extIfn),
rxBytes(rxB), rxPackets(rxP),
txBytes(txB), txPackets(txP) {};
/* Internal interface. Same as NatController's notion. */
std::string intIface;
/* External interface. Same as NatController's notion. */
std::string extIface;
int64_t rxBytes, rxPackets;
int64_t txBytes, txPackets;
/*
* Allocates a new string representing this:
* intIface extIface rx_bytes rx_packets tx_bytes tx_packets
* The caller is responsible for free()'ing the returned ptr.
*/
char *getStatsLine(void) const;
};
BandwidthController();
int setupIptablesHooks(void);
/* Added by Ce.Gao. */
#ifdef BOOTTIME_OPTIMIZATION //添加接口定义
int setupIptablesHooksOnBoot(void);
#endif
/* End of addtions by Ce.Gao. */
int enableBandwidthControl(bool force);
int disableBandwidthControl(void);
...................................
......................................
修改:system\netd\server\BandwidthController.cpp 添加接口实现
/**
* Added by Ce.Gao.
* This function is used on boot to accelerate netd starting speed.
*/
#ifdef BOOTTIME_OPTIMIZATION
int BandwidthController::setupIptablesHooksOnBoot(void) {
runCommands(sizeof(IPT_SETUP_COMMANDS) / sizeof(char*),
IPT_SETUP_COMMANDS, RunCmdFailureBad);
return 0;
}
#endif
/**
* End of addtions by Ce.Gao.
*/
7)对应的进行预编译
在device\atc\evb3561sv_w_no2\BoardConfig.mk 该文件中添加
### add by zhaojr for odex
# Enable dex-preoptimization to speed up first boot sequence
ifeq ($(HOST_OS),linux)
#ifeq (user, $(TARGET_BUILD_VARIANT))
ifeq ($(WITH_DEXPREOPT),)
WITH_DEXPREOPT := true
endif
#endif
endif
注意:添加WITH_DEXPREOPT := true之后,系统启动可能会有APP和库没法加载成功,可以使用以下方式进行修改,不进行odex预编译,如之前优化时遇到的问题
packages\apps\Launcher2\Android.mk
LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
#LOCAL_SDK_VERSION := current
LOCAL_DEX_PREOPT := false //编译时不进行odex预编译
LOCAL_PACKAGE_NAME := Launcher2
LOCAL_CERTIFICATE := shared
LOCAL_PRIVILEGED_MODULE := true
8、裁剪掉系统不用的部分APK
PackageManagerService
scanDirTracedLI
(1)减少预置APP的数量(对开机速度会有较为明显的提升);
(2)删除没有必要的apk包;
(3)单线程scan分区里面的apk并不一定能充分使用IO资源,尝试改为多线程异步scan;
(4)精简系统,把系统中用不到的apk包、有重复功能的apk移除,这样既可以使系统有更大的剩余存储空间又可以减少scan的时间,加快开机;
(5)其中一部分根系统主界面主要功能之外的APK,可以将其打包到特殊的目的结构中,在进行包扫描的时候先扫描system/app、vendor/app、data/app目录,之后在收到系统发的boot完成广播之后再进行扫描安装。
9、bootanimation 时间
1. 最好不要超过 system_server 启动时间 (11s) ( 63385.657304 : Android:SysServerInit_START 到 android:SysServerInit_END)
2. 不要播放 mp3
3. bootanimation.zip 图片越少越好
4、或者使用两张图片,前面的图片镂空,后面的图片实体,仍后后面的图片从亮到暗,直接修改动画显示的原理,让后面的图片一直在循环转动,直到boot完成广播发出在退出即可,这样将大幅加快启动速度。
按照以上优化之前,之前系统启动速度大概在50多秒,优化之后大概缩短在14秒左右就可以启动到主界面了。
最后参考文章:
https://blog.csdn.net/dearsq/article/details/81537655