針對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 [email protected]{
/// 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