在工作中,对于系统开发确实有些难度,特别是在开机阶段遇到的问题,比如开机动画播放完毕进入锁屏界面黑屏几秒然后进入 锁屏界面,这就需要根据开机日志来分析问题所在,在工作中遇到的几种黑屏情况做下记录
首次开机进入Launcher3前黑屏几秒的几种情况问题的总结
2.1 开机向导引起的进入Launcher桌面短暂黑屏
在系统中默认是有开机向导的,首次开机会首选进入开机向导,然后进入锁屏桌面,如果某些原因 引起开机向导卡顿,会造成短暂黑屏然后进入Launcher界面 去掉开机向导的相关修改为: frameworks/base/packages/SettingsProvider/res/values/defaults.xml
可以修改如下:
frameworks/base/packages/SettingsProvider/res/values/defaults.xml
true
true
再在产品mk中去掉这两个app:
packages/apps/OneTimeInitializer
packages/apps/Provision
在build的handheld_product.mk中参与编译这两个apk
$(call inherit-product, $(SRC_TARGET_DIR)/product/media_product.mk)# /product packages
PRODUCT_PACKAGES += \Camera2 \DeskClock \LatinIME \Launcher3QuickStep \OneTimeInitializer \Provision \Music \Settings \SettingsIntelligence \StorageManager \SystemUI \WallpaperCropper \frameworks-base-overlaysPRODUCT_PACKAGES_DEBUG += \frameworks-base-overlays-debug修改如下:
build\make\target\product\handheld_product.mk
$(call inherit-product, $(SRC_TARGET_DIR)/product/media_product.mk)# /product packages
PRODUCT_PACKAGES += \Camera2 \DeskClock \LatinIME \Launcher3QuickStep \
- OneTimeInitializer \
- Provision \Music \Settings \SettingsIntelligence \StorageManager \SystemUI \WallpaperCropper \frameworks-base-overlaysPRODUCT_PACKAGES_DEBUG += \frameworks-base-overlays-debug
让系统直接启动桌面,不用启动Provision。Provision干的事情和SetupWizard、 OneTimeInitializer类似。都是设置DEVICE_PROVISIONED和USER_SETUP_COMPLETE。
2.2 开机动画引起的进入launcher前的黑屏情况
在系统进入首次开机的时候,由于需要加载相当多的系统数据和服务,首次开机耗时会长一点,如果 开机动画过少,在播放完开机动画以后,还没等到AMS执行完停止播放动画的相关通知,就会陷入 黑屏状态等得到AMS停止播放动画以后就会进入桌面
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.javafinal void finishBooting() {Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "FinishBooting");synchronized (this) {if (!mBootAnimationComplete) {mCallFinishBooting = true;return;}mCallFinishBooting = false;}ArraySet completedIsas = new ArraySet();for (String abi : Build.SUPPORTED_ABIS) {ZYGOTE_PROCESS.establishZygoteConnectionForAbi(abi);final String instructionSet = VMRuntime.getInstructionSet(abi);if (!completedIsas.contains(instructionSet)) {try {mInstaller.markBootComplete(VMRuntime.getInstructionSet(abi));} catch (InstallerException e) {if (!VMRuntime.didPruneDalvikCache()) {// This is technically not the right filter, as different zygotes may// have made different pruning decisions. But the log is best effort,// anyways.Slog.w(TAG, "Unable to mark boot complete for abi: " + abi + " (" +e.getMessage() +")");}}completedIsas.add(instructionSet);}}IntentFilter pkgFilter = new IntentFilter();pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);pkgFilter.addDataScheme("package");mContext.registerReceiver(new BroadcastReceiver() {@Overridepublic void onReceive(Context context, Intent intent) {String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);if (pkgs != null) {for (String pkg : pkgs) {synchronized (ActivityManagerService.this) {if (forceStopPackageLocked(pkg, -1, false, false, false, false, false,0, "query restart")) {setResultCode(Activity.RESULT_OK);return;}}}}}}, pkgFilter);IntentFilter dumpheapFilter = new IntentFilter();dumpheapFilter.addAction(DumpHeapActivity.ACTION_DELETE_DUMPHEAP);mContext.registerReceiver(new BroadcastReceiver() {@Overridepublic void onReceive(Context context, Intent intent) {final long delay = intent.getBooleanExtra(DumpHeapActivity.EXTRA_DELAY_DELETE, false) ? 5 * 60 * 1000 : 0;mHandler.sendEmptyMessageDelayed(DELETE_DUMPHEAP_MSG, delay);}}, dumpheapFilter);// Inform checkpointing systems of successtry {// This line is needed to CTS test for the correct exception handling// See b/138952436#comment36 for contextSlog.i(TAG, "About to commit checkpoint");IStorageManager storageManager = PackageHelper.getStorageManager();storageManager.commitChanges();} catch (Exception e) {PowerManager pm = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE);pm.reboot("Checkpoint commit failed");}// Let system services know.mSystemServiceManager.startBootPhase(SystemService.PHASE_BOOT_COMPLETED);synchronized (this) {// Ensure that any processes we had put on hold are now started// up.final int NP = mProcessesOnHold.size();if (NP > 0) {ArrayList procs =new ArrayList(mProcessesOnHold);for (int ip=0; ipjoin() != NO_ERROR) {ALOGE("Join StartPropertySetThread failed!");}const nsecs_t now = systemTime();const nsecs_t duration = now - mBootTime;ALOGI("Boot is finished (%ld ms)", long(ns2ms(duration)) );mFrameTracer->initialize();mTimeStats->onBootFinished();// wait patiently for the window manager deathconst String16 name("window");mWindowManager = defaultServiceManager()->getService(name);if (mWindowManager != 0) {mWindowManager->linkToDeath(static_cast(this));}sp input(defaultServiceManager()->getService(String16("inputflinger")));if (input == nullptr) {ALOGE("Failed to link to input service");} else {mInputFlinger = interface_cast(input);}if (mVrFlinger) {mVrFlinger->OnBootFinished();}// stop boot animation// formerly we would just kill the process, but we now ask it to exit so it// can choose where to stop the animation.property_set("service.bootanim.exit", "1");const int LOGTAG_SF_STOP_BOOTANIM = 60110;LOG_EVENT_LONG(LOGTAG_SF_STOP_BOOTANIM,ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));static_cast(schedule([this] {readPersistentProperties();mPowerAdvisor.onBootFinished();mBootStage = BootStage::FINISHED;if (property_get_bool("sf.debug.show_refresh_rate_overlay", false)) {enableRefreshRateOverlay(true);}}));}
在BootAnimation.cpp退出动画的相关方法
frameworks/base/cmds/bootanimation/BootAnimation.cppvoid BootAnimation::checkExit() {// Allow surface flinger to gracefully request shutdownchar value[PROPERTY_VALUE_MAX];property_get(EXIT_PROP_NAME, value, "0");int exitnow = atoi(value);if (exitnow) {requestExit();mCallbacks->shutdown();}}
在项目中遇到开机动画只有几张的项目 在首次开机的时候会出现黑屏 把开机动画增加到30张左右的就解决了这个问题
2.3 FallbackHome导致的黑屏问题
在无锁屏的情况下 会在开机动画播放完毕后进入系统设置的FallbackHome,等收到解锁通知后 然后进入默认桌面,这时可以在onCreate设置开机动画最后一张作为背景
public class FallbackHome extends Activity {private static final String TAG = "FallbackHome";private static final int PROGRESS_TIMEOUT = 2000;private boolean mProvisioned;private WallpaperManager mWallManager;private final Runnable mProgressTimeoutRunnable = () -> {View v = getLayoutInflater().inflate(R.layout.fallback_home_finishing_boot, null /* root */);setContentView(v);v.setAlpha(0f);v.animate().alpha(1f).setDuration(500).setInterpolator(AnimationUtils.loadInterpolator(this, android.R.interpolator.fast_out_slow_in)).start();getWindow().addFlags(LayoutParams.FLAG_KEEP_SCREEN_ON);};private final OnColorsChangedListener mColorsChangedListener = new OnColorsChangedListener() {@Overridepublic void onColorsChanged(WallpaperColors colors, int which) {if (colors != null) {final View decorView = getWindow().getDecorView();decorView.setSystemUiVisibility(updateVisibilityFlagsFromColors(colors, decorView.getSystemUiVisibility()));mWallManager.removeOnColorsChangedListener(this);}}};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);// Set ourselves totally black before the device is provisioned so that// we don't flash the wallpaper before SUWmProvisioned = Settings.Global.getInt(getContentResolver(),Settings.Global.DEVICE_PROVISIONED, 0) != 0;final int flags;if (!mProvisioned) {setTheme(R.style.FallbackHome_SetupWizard);flags = View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;} else {flags = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;}mWallManager = getSystemService(WallpaperManager.class);if (mWallManager == null) {Log.w(TAG, "Wallpaper manager isn't ready, can't listen to color changes!");} else {loadWallpaperColors(flags);}getWindow().getDecorView().setSystemUiVisibility(flags);// 增加背景
+ getWindow().setBackgroundDrawableResource(R.drawable.background);registerReceiver(mReceiver, new IntentFilter(Intent.ACTION_USER_UNLOCKED));maybeFinish();}@Overrideprotected void onResume() {super.onResume();if (mProvisioned) {mHandler.postDelayed(mProgressTimeoutRunnable, PROGRESS_TIMEOUT);}}
}
第二种改法
总结:这三种情况目前是开发中,遇到常见的情况,具体情况可以根据开机日子分析来解决相关的问题