Android Launcher和SystemUI的启动

Android 12系统源码_SystemUI(六)发送消息给Launcher3显示最近应用列表 通过Android12源码梳理SystemUI模块如何发送消息给Launcher3,最终显示最近应用列表的。 阅读详情
AI摘要

本文详细解析了Android系统启动时Launcher的初始化过程,涉及SystemServer的run(),SystemUI的启动,以及关键组件如AMS、ATMS的介入,展示了从SystemServer到启动LauncherActivity的完整流程。

一、前提提要

        Launcher即桌面程序是在系统服务等启动后打开的第一个应用程序进程,主要管理手机内部的各个用户App的展示与打开等功能,在开启Launcher的过程中SystemUI 如导航栏等布局也相继加载到屏幕中。

        Launcher的启动在各种系统服务初始化完成后进行的,即SystemServer的startOtherService()方法最后

二、启动流程

        1、SystemServer.run()

//com.android.server.SystemServer
private void run() {
    try{
        ......
        //1、创建系统Context
        createSystemContext();
        ......
    }catch(..){..}
    ......
    try{
        ......
        //2、启动其他服务
        startOtherServices(); 
        ...... 
    }catch(..){..}
    //......         
}

        系统服务如:AMS\ATMS、PMS、WMS等都是在SystemServer的run()方法中启动初始化,关于系统服务的启动不做过多介绍,这里主要有是创建了系统Context为后续启动做准备,然后进入到startOtherServices方法中

        2、startOhterServices()

//com.android.server.SystemServer
private void startOtherServices() {
    final Context context = mSystemContext;
    ......
    //wms、ims等各种服务初始化
    ......
    //通过AMS做启动前的准备
    mActivityManagerService.systemReady(() -> {
        ......
        try {
            //2、启动系统UI
            startSystemUi(context, windowManagerF);
        } catch (Throwable e) {
            reportWtf("starting System UI", e);
        }
        ......
    },BOOT_TIMINGS_TRACE_LOG);
}

        在startOtherServices方法中先是完成必要的系统服务后,通过AMS开始对Launcher的启动进行准备工作,调用AMS的systemReady方法传入了一个Callback,并且在Callback中又对系统UI进行启动

        3、启动SystemUI

//com.android.server.SystemServer
private static void startSystemUi(Context context, WindowManagerService windowManager) {
    //启动系统UI Service
    Intent intent = new Intent();
    intent.setComponent(new ComponentName("com.android.systemui",
            "com.android.systemui.SystemUIService"));
    intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
    //Slog.d(TAG, "Starting service: " + intent);
    context.startServiceAsUser(intent, UserHandle.SYSTEM);
    windowManager.onSystemUiStarted();
}

        通过启动Service的方式初始化UI

//com.android.systemui.SystemUIService
public class SystemUIService extends Service {
    @Override
    public void onCreate() {
        super.onCreate();
        //执行SystemUIApplication中的创建方法
        ((SystemUIApplication) getApplication()).startServicesIfNeeded();
        ......
    }
    ......
}

          在Service的onCreate()方法中又调用了当前Application的startServicesIfNeeded方法继续初始化

        在前面的createSystemContext()方法中创建了Context的同时也创建的Application对象,Application的具体实例类型是通过解析对应的AndroidManifest.xml获取,此处创建的Application所解析的xml在 /frameworks/base/packages/SystemUI 包下

//frameworks/base/packages/SystemUI/AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
     package="com.android.systemui"
     android:sharedUserId="android.uid.systemui"       
     coreApp="true">
     ......
      <application
          //Application类
          android:name=".SystemUIApplication"       
          android:persistent="true"    
          android:allowClearUserData="false"
          android:allowBackup="false"
          .....
      </application>
</manifest>
          

        SystemUIApplication中继续执行

//com.android.systemui.SystemUIApplication
public void startServicesIfNeeded() {
    //获取需要初始化系统UI的名字
    String[] names = getResources().getStringArray(R.array.config_systemUIServiceComponents);
    startServicesIfNeeded(names);
}

private void startServicesIfNeeded(String[] services) {
    if (mServicesStarted) {
        return;
    }
    //SystemUI集合,系统UI都继承自SystemUI
    mServices = new SystemUI[services.length];
    ......
    final int N = services.length;
    for (int i = 0; i < N; i++) {
        String clsName = services[i];
        ......
        Class cls;
        try {
            //通过反射实例化各个系统UI
            cls = Class.forName(clsName);
            Object o = cls.newInstance();
            if (o instanceof SystemUI.Injector) {
                o = ((SystemUI.Injector) o).apply(this);
            }
            mServices[i] = (SystemUI) o;
        } ......

        mServices[i].mContext = this;
        mServices[i].mComponents = mComponents;
        if (DEBUG) Log.d(TAG, "running: " + mServices[i]);
        //初始化系统UI (4-1)
        mServices[i].start();
        ......
        if (mBootCompleted) {
            mServices[i].onBootCompleted();
        }
    }
    .......
}

        从config.xml获取需要初始化的各个SystemUI类名,然后创建SystemUI数组并遍历集合通过反射的方式创建实例,最后调用SystemUI.start()方法对每个SystemUI初始化和渲染

        config_systemUIServiceComponents定义在在/frameworks/base/packages/SystemUI/res/values/config.xml 文件下,其中包括了 如 顶部状态栏、通知、键盘等一些列UI

<!-- SystemUI Services: The classes of the stuff to start. -->    
<string-array name="config_systemUIServiceComponents" translatable="false">       
    <item>com.android.systemui.Dependency</item>
    <item>com.android.systemui.util.NotificationChannels</item>
    <item>com.android.systemui.statusbar.CommandQueue$CommandQueueStart</item>        
    <item>com.android.systemui.keyguard.KeyguardViewMediator</item>
    <item>com.android.systemui.recents.Recents</item>
    <item>com.android.systemui.volume.VolumeUI</item>
    <item>com.android.systemui.stackdivider.Divider</item>
    <item>com.android.systemui.SystemBars</item> 
    <item>com.android.systemui.usb.StorageNotification</item>
    <item>com.android.systemui.power.PowerUI</item>
    <item>com.android.systemui.media.RingtonePlayer</item>
    <item>com.android.systemui.keyboard.KeyboardUI</item>
    <item>com.android.systemui.pip.PipUI</item> 
    <item>com.android.systemui.shortcut.ShortcutKeyDispatcher</item>
    <item>@string/config_systemUIVendorServiceComponent</item>
    <item>com.android.systemui.util.leak.GarbageMonitor$Service</item>
    <item>com.android.systemui.LatencyTester</item>
    <item>com.android.systemui.globalactions.GlobalActionsComponent</item> 
    <item>com.android.systemui.ScreenDecorations</item>
    <item>com.android.systemui.fingerprint.FingerprintDialogImpl</item>
    <item>com.android.systemui.SliceBroadcastRelayHandler</item>
</string-array>

        

        以SystemBars为例:

//继承自SystemUI
public class SystemBars extends SystemUI {
    ......
    //执行的start()方法
    @Override
    public void start() {
        if (DEBUG) Log.d(TAG, "start");
        //创建StatusBar
        createStatusBarFromConfig();
    }
    ......
    private void createStatusBarFromConfig() {
        if (DEBUG) Log.d(TAG, "createStatusBarFromConfig");
        //获取StatusBar类名
        //com.android.systemui.statusbar.phone.StatusBar
        final String clsName = mContext.getString(R.string.config_statusBarComponent);
        if (clsName == null || clsName.length() == 0) {
            throw andLog("No status bar component configured", null);
        }
        Class<?> cls = null;
        try {
            cls = mContext.getClassLoader().loadClass(clsName);
        } catch (Throwable t) {
            throw andLog("Error loading status bar component: " + clsName, t);
        }
        try {
            //通过反射创建StatusBar对象
            mStatusBar = (SystemUI) cls.newInstance();
        } catch (Throwable t) {
            throw andLog("Error creating status bar component: " + clsName, t);
        }
        mStatusBar.mContext = mContext;
        mStatusBar.mComponents = mComponents;
        if (mStatusBar instanceof StatusBar) {
            SystemUIFactory.getInstance().getRootComponent()
                .getStatusBarInjector()
                .createStatusBar((StatusBar) mStatusBar);
        }
        //StatusBar也是继承SystemUI继续执行start方法
        mStatusBar.start();
        if (DEBUG) Log.d(TAG, "started " + mStatusBar.getClass().getSimpleName());
    }
    ......
}

        SystemBar的start()中创建了StatusBar对象,StatusBar也是继承自SystemUI,再次执行start()方法

//com.android.systemui.statusbar.phone.StatusBar

//继承SystemUI
public class StatusBar extends SystemUI implements ...{
    ......
    @Override
    public void start() {
        ......
        //获取WMS
        mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
        ......  
        mWindowManagerService = WindowManagerGlobal.getWindowManagerService();
        ......
        //创建并将view添加到屏幕
        createAndAddWindows(result);
        ......
    }
    ......
    
    public void createAndAddWindows(@Nullable RegisterStatusBarResult result) {
        //创建StatusView
        makeStatusBarView(result);
        mStatusBarWindowController = Dependency.get(StatusBarWindowController.class);
        //添加到Window 涉及到WMS绘制
        mStatusBarWindowController.add(mStatusBarWindow, getStatusBarHeight());
    }
 }

        可以看到StatusBar中实际创建了View,并通过WMS绘制到屏幕中

        4、启动Launcher

        继续回到SystemServer代码

//com.android.server.SystemServer
private void startOtherServices() {
    ......
    //通过AMS做启动前的准备
    mActivityManagerService.systemReady(() -> {
        ......
        try {
            //2、启动系统UI
            startSystemUi(context, windowManagerF);
        } catch (Throwable e) {
            reportWtf("starting System UI", e);
        }
        ......
    },BOOT_TIMINGS_TRACE_LOG);
}

        进入到AMS.systemReady()方法

//com.android.server.am.ActivityManagerService.java
public void systemReady(final Runnable goingCallback, TimingsTraceLog traceLog) {
    synchronized(this) {
        if (mSystemReady) {
            // 如果初始化过一次 那就直接执行callback
            if (goingCallback != null) {
                goingCallback.run();
            }
            return;
        }

        mLocalDeviceIdleController
            = LocalServices.getService(DeviceIdleController.LocalService.class);
        //准备完成配置信息
        mActivityTaskManager.onSystemReady();
        mUserController.onSystemReady();
        mAppOpsService.systemReady();
        mSystemReady = true;
    }
    ......
    //执行callback 初始化系统UI等操作
    if (goingCallback != null) goingCallback.run();
    ......
    synchronized (this) {
        ......
        //启动Launcher
        mAtmInternal.startHomeOnAllDisplays(currentUserId, "systemReady"); 
        ......  
    }
}

        在内部做了防止多次初始化启动的操作,配置完各项信息调用ActivityTaskManagerInternal的startHomeOnAllDisplays启动Launcher

        这里简单了解一下mAtmInternal的创建过程

        1、mAtmInternal是ActivityTaskManagerInternal类型,管理AtivityTaskManager

功能的接口。它的获取是在ActivityManagerService构造方法中

public ActivityManagerService(Context systemContext, 
        ActivityTaskManagerService atm) {
    ......
    //通过ATMI.class获取具体实现类
    mAtmInternal = LocalServices.getService(ActivityTaskManagerInternal.class);
    ......
}

        LocalServices内部维护一个Map,主要用来存取本地的一些接口服务此处获取ActivityTaskManagerInternal的实现类

        2、ActivityTaskManagerInternal是一个接口具体实现类是ActivityTaskManagerService

内部的LocalService

public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
    ......
    final class LocalService extends ActivityTaskManagerInternal {
        ......
    }
    ......
}

        

        3、LocalService的创建是在ATMS的构造函数中,而添加到LocalServices是在ATMS

服务启动的时候

public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
    ......
    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
    public ActivityTaskManagerService(Context context) {
        ......   
        mInternal = new LocalService();
        ......
    }
    ......
    //ATMS启动
    private void start() {
        //添加到LocalServices,key为ATMI.class
        LocalServices.addService(ActivityTaskManagerInternal.class, mInternal);
    }
}

        ATMS的启动则是在SystemServer中进行的,这里就不多做赘述

        继续回到mAtmInternal.startHomeOnAllDisplays方法

final class LocalService extends ActivityTaskManagerInternal {
    ......
    @Override
    public boolean startHomeOnAllDisplays(int userId, String reason) {
        synchronized (mGlobalLock) {
            //继续执行RootWindowContainer的方法
            return mRootWindowContainer.startHomeOnAllDisplays(userId, reason);
        }
    }
    ......
}

        RootWindowContainer.startHomeOnAllDisplays

class RootActivityContainer extends ConfigurationContainer
        implements DisplayManager.DisplayListener {
    ......
    boolean startHomeOnAllDisplays(int userId, String reason) {
        boolean homeStarted = false;
        for (int i = mActivityDisplays.size() - 1; i >= 0; i--) {
            final int displayId = mActivityDisplays.get(i).mDisplayId;
            //1、获取并继续调用启动方法
            homeStarted |= startHomeOnDisplay(userId, reason, displayId);
        }
        return homeStarted;
    }
    ......
    
    boolean startHomeOnDisplay(int userId, String reason, int displayId) {
        //2、
        return startHomeOnDisplay(userId, reason, displayId, false /* allowInstrumenting */,
            false /* fromHomeKey */);
    }
    
    boolean startHomeOnDisplay(int userId, String reason, int displayId, boolean allowInstrumenting,
        boolean fromHomeKey) {
        // Fallback to top focused display or default display if the displayId is invalid.
        if (displayId == INVALID_DISPLAY) {
            final ActivityStack stack = getTopDisplayFocusedStack();
            displayId = stack != null ? stack.getDisplayId() : DEFAULT_DISPLAY;
        }

        final DisplayContent display = getDisplayContent(displayId);
        boolean result = false;
        for (int tcNdx = display.getTaskDisplayAreaCount() - 1; tcNdx >= 0; --tcNdx) {
            final TaskDisplayArea taskDisplayArea = display.getTaskDisplayAreaAt(tcNdx);
            result |= startHomeOnTaskDisplayArea(userId, reason, taskDisplayArea,
                allowInstrumenting, fromHomeKey);
        }
        return result;
    }
    
    boolean startHomeOnTaskDisplayArea(int userId, String reason, int displayId, boolean allowInstrumenting,
        boolean fromHomeKey) {
        ......
        //Launcher的Intent
        Intent homeIntent = null;
        ActivityInfo aInfo = null;
        //3、获取Launcher的Activity信息
        if (taskDisplayArea == getDefaultTaskDisplayArea()) {
            homeIntent = mService.getHomeIntent();
            aInfo = resolveHomeActivity(userId, homeIntent);
        } else if (shouldPlaceSecondaryHomeOnDisplayArea(taskDisplayArea)) {
            Pair<ActivityInfo, Intent> info = resolveSecondaryHomeActivity(userId, taskDisplayArea);
            aInfo = info.first;
            homeIntent = info.second;
        }
        ......
        //检测是否允许启动
        //内部有对系统运行模式和TopAction以及分屏的判断
        if (!canStartHomeOnDisplayArea(aInfo, displayId, allowInstrumenting)) {
            return false;
        }

        //更新Launcher的启动信息
        homeIntent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name));
        homeIntent.setFlags(homeIntent.getFlags() | FLAG_ACTIVITY_NEW_TASK);
        // Updates the extra information of the intent.
        if (fromHomeKey) {
            homeIntent.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, true);
        }
        // Update the reason for ANR debugging to verify if the user activity is the one that
        // actually launched.
        final String myReason = reason + ":" + userId + ":" + UserHandle.getUserId(
            aInfo.applicationInfo.uid) + ":" + displayId;
        //4、启动Launcher Activity
        mService.getActivityStartController().startHomeActivity(homeIntent, aInfo, myReason,
            displayId);
        return true;
    }
}

       最后通过ATMS获取ActivityStartController对象,并调用startHomeActivity启动了Launcher。

后续启动流程与点击App应用冷启动过程类似,等整理完成后再出下一篇博客

三、最后

        本文通过自己对Android 10版本源码的理解整理发布,其中很多细节不够详细还需要进一步理解,如果出现错误欢迎指正,如果小伙伴有更好的流程解析欢迎一起探讨

Launcher下拉显示SystemUI qs控制面板 代码流程 【代码】Laucher下拉显示SystemUI qs控制面板 代码流程。 阅读详情

相关推荐

android系统Launcher启动时机

今天有空研究了一下系统启动流程中的Launcher启动时机,有必要给大家分享一下阅读代码的成果; 首先我们知道系统启动先会生成init进程,init进程会去启动各种守护进程类似usbd,adbd等,同时将启动Zygote进程,而之后Zygote进程会去起SystemServer进程,这个SystemServer是启动大部分服务的进程,同时将这些服务注册到ServiceManager中,其实应该能...

liangtianmeng的专栏 1715

systemUI与Launcher和Home的区别

systemUI与Launcher和Home的区别 launcher就是主页,那些图标,启动应用的 和home是同一个东西 systemUI就是通知栏,导航按键栏

YACHL882828的博客 6967

拆解智能座舱:手把手带你认识Android Automotive OS里的SystemUI、Launcher与车控应用

本文深入解析Android Automotive OS中智能座舱的三大核心组件:SystemUI、Launcher与车控应用的协同工作原理。从SystemUI的动态DPI适配到Launcher的3D车模渲染技术,再到车控应用与Vehicle HAL的高效通信机制,全面揭示车载系统开发的关键技术与性能优化策略,为车载应用开发提供实用指导。

weixin_31785177的博客 316

Framework 学习之旅:Android 系统启动流程

init进程(pid=1,init进程是所有进程的鼻祖,第一个启动)启动后,会启动adbd,logd等用户守护进程,并且会启动servicemanager(binder服务管家)等重要服务,同时孵化出zygote进程,这里属于C++Framework,代码为C++程序。zygote同时会启动相关的APP进程,它启动的第一个APP进程为Launcher,然后启动Email,SMS等进程,所有的APP进程都有zygotefork生成。初始化进程管理等操作会启动INIT进程,这些在Native层中。...

xufei5789651的博客 2208

[深入SystemUI]-了解recents的启动流程(二)

本文流程基于Android 9.0 toggleRecentApps介绍 上节中我们讲了preloadRecentApps,而点击了switch可能执行两种不同的方法,另外一种就是toggleRecentApps。 和preloadRecentApps在fwk中的调用过程一样,最终是调用到了SystemUI的Recents.toggleRecentApps()方法。 toggleRecent...

百吉猫的博客 2460

android 16根据白名单屏蔽home键和recent

加日志去看对应的disable值不打印,说明没走systemUi设置NavigationBar这套逻辑,但是手机是有底部导航栏的,我们去systemUI启动初始化去分析。总结:TaskBar在Android 12.1后用于大屏设备,替代传统导航栏,需要修改导航按钮显示隐藏,icon定制,背景定制,点击事件等,需要在Launcher的。判断条件为false没有去创建NavigationBar,这也就验证了开头说的打印不生效,查看代码initializeTaskbarIfNecessary()

weixin_43882863的博客 989

Android 13分屏动画全解析:从Launcher点击到SystemUI启动的完整流程(附调用栈)

本文深入解析Android 13分屏动画的完整流程,从Launcher点击到SystemUI启动的详细调用栈。通过分析RecentsView、SplitSelectStateController等核心组件,揭示分屏动画的协调机制与性能优化技巧,帮助开发者理解多窗口交互的底层实现。

weixin_30634661的博客 360

Android15车载系统开机冷启动流程源码解析

本文主要介绍Android15车机系统开机冷启动的流程,暂不包含bootloader,仅从kernel开始直至Launcher首页展示。

jidapenglin28的专栏 254

Android系统启动流程全解析:从Bootloader到Launcher的底层揭秘

操作系统从按下电源键到桌面可交互,背后是一条由引导加载、内核初始化、进程孵化、系统服务注册串联而成的复杂链路。理解Android启动流程,是排查开机慢、自启动失效、系统服务崩溃等问题的关键前提。从Bootloader校验签名,到init进程解析脚本,再到Zygote孵化应用进程、SystemServer承载核心服务,每一个环节都深刻影响着设备稳定性和用户体验。本文以时序与问题双线并行,梳理各阶段的职责与常见故障,并给出bootchart、dmesg、logcat等实用排查工具。掌握这套路径,开发者能更精准地

weixin_34252686的博客 369

NSIDC海冰运动产品-速度矢量场图绘制(数据下载和处理--年、季节平均)【python/basemap】

入门级NSIDC海冰运动产品速度矢量场图绘制(数据下载和处理--年、季节平均)【python/basemap】

Mluoo的博客 2959

Day470&471.Netty概述&Netty高性能架构设计 -netty

Netty概述 一、原生 NIO 存在的问题 NIO 的类库和 API 繁杂,使用麻烦:需要熟练掌握 Selector、ServerSocketChannel、SocketChannel、ByteBuffer等。 需要具备其他的额外技能:要熟悉 Java 多线程编程,因为 NIO 编程涉及到 Reactor 模式,你必须对多线程和网络编程非常熟悉,才能编写出高质量的 NIO 程序。 开发工作量和难度都非常大:例如客户端面临断连重连、网络闪断、半包读写、失败缓存、网络拥塞和异常流的处理等等。 JDK NIO

阿昌爱Java 1572

Android系统应用---SystemUI之一:SystemUI概述和创建启动流程分析

SystemUI概述 自android2.2开始,原本存在与framework-res.apk中的状态栏和下拉通知栏界面控制被分割出一个单独的apk文件,命名为SystemUI.apk,保存在System/priv-app/SystemUI/文件夹中。在SystemUI.apk中,存在着状态栏的图标,XML和控制文件等,这样的划分,使我们可以更方便地去修改UI的显示,也就说在目前的Android

无敌麦子地的博客 3279

Skyworks SKY85331-11的Wi-Fi 6 (802.11ax)标准 2.4G 高功率WLAN前端模块解决方案

SKY85331-11是高度集成的2 GHz前端模块(FEM)包含2 GHz单刀双掷(SPDT)发送/接收(T / R)开关,2 GHz低噪声放大器(LNA)带旁路和一个2 GHz功率放大器(PA),用于大功率802.11ax应用程序和系统LNA和PA禁用功能可确保低漏电流 关闭模式。 包括一个集成的功率检测器以提供系统内的闭环功率控制。该设备提供Small (24-pin, 3 x 5 mm) (LGA)封装。 图1.引脚配置和封装如图所示 图2.信号引脚分配和功能引脚描述 图...

zhangbao19890622的博客 4508

Android 9.0(P) SystemUI之QuickStep探索

引言 QuickStep是Android P中一大新特性,在Android P中 Google将SystemUI中Recents在Launcher又实现了一遍,并且取名为QuickStep,其具有新的界面(如下图)以及交互方式。 quickstep.png QuickStep有两种启动方式,一种为常规启动方式——点击recents键,一种则是通过手势启动(如下图)。 ...

木叶风的博客 1万+

别再搞错了!ERA5-Land小时数据里的辐射值,原来不是你想的那个‘瞬时值’

本文深入解析ERA5-Land小时数据中辐射值的累积特性,揭示其与瞬时值的本质区别。通过详细的数据处理方法和Python代码示例,指导研究者正确转换累积辐射量为实用瞬时值,避免常见误区,提升气候模型验证的准确性。

weixin_28700411的博客 210

暑期实习前端面试笔试总结汇总

腾讯2020暑期实习——前端视频面试(1)回顾 腾讯2020暑期实习——前端视频面试(2)回顾 腾讯2020暑期实习——前端视频面试(3)回顾 腾讯2020暑期实习——前端视频面试(4)回顾 蘑菇街2020暑期实习——前端视频面试回顾 二、笔试 奇安信前端实习笔试总结 vivo笔试(2020年3月8日) ...

明媚 3067

android 进lanucher的广播,Android开机优化之调整Launcher的加载时间

前言如前面两篇文章所描述的,我们对Android系统的开机时间优化有了一个比较全面的了解,以及一些常用的调试手段(bootchart等),在这篇文章中我们先来看看如下这个问题,首先看一张图: 如上图所示,1、在系统启动的时候,为什么像inputmethod、phone、systemUI及settings这些包加载启动的时候要比Launcher早个2秒多的时间呢?2、开机动画结束,到Launcher...

weixin_31786973的博客 1167

Parasoft C++Test软件集成测试(部件测试)_实例讲解

本文以一组功能函数组件作为示例,讲解了如何使用C++Test进行软件集成测试。本文的示例比较简单,但是思路、方法和流程都是通用的,希望对大家有所帮助。

文章主要涉及嵌入式软件开发、测试、项目管理等,欢迎交流,共同进步。 735

Android U 多任务启动分屏——Launcher流程(下分屏)

前文讲了Launcher中上分屏流程,现在我们看看下分屏的流程。

yimelancholy的博客 3069

深入C++学习还必须掌握的一基础知识精讲

施磊C++语言基础提高课程笔记,包括了new/delete;malloc/free;引用和指针;const,指计和引用的结合;函数重载,inline的数,参数带默认值的函数;函数模板等知识点

GeniusAng的博客 1480

[特殊字符] 从零构建携程/飞猪机票价格爬虫:Python异步抓取与反爬对抗实战

在出行决策、竞品分析、价格预测模型训练等场景中,稳定获取携程(Ctrip)和飞猪(Fliggy)的实时机票价格波动数据是刚需。然而,这两大平台均部署了业界顶尖的反爬体系——包括但不限于:动态请求签名(SignToken设备指纹采集(UACanvasWebGL接口参数加密(X-Sign_abtestcookie混淆)频率限制与 IP 封禁(滑动窗口 + 行为检测)目录前言:为什么需要自建机票价格爬虫?一、技术选型与项目架构1.1 核心技术栈1.2 系统架构图(文字描述)1.3 法律与道德声明。

2201_76125261的博客 341

【Android系统启动】 Android14启动流程概览

作为一个Android开发工程师,了解Android系统从上电到全功能启动的流程,是十分有必要的。这个对排查系统疑难问题、定制系统开发都十分有帮助。因此记录以下系列文章笔记。文章编写与2024年,基于AOSP官网主干代码ARM64b部分学习,按年份计算代码处于Android14~Android15中间。笔者水平有限,如存在谬误,欢迎指出纠正。

thirdbro的博客 3129

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

android启动拷贝system,android系统从SystemServer到Launcher的启动过程

android系统从SystemServer到Launcher的启动过程android系统从init进程到SystemServer的启动过程请移驾,本文主要从流程的角度分析SystemServer如何启动的Launcher应用程序,不注重细节。SystemServerpublic static void main(String[] args) {new SystemServer().run();}...

weixin_35340730的博客 274

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

android p关于qickstep launcher anr分析

手机在开机后,有概率出现qickstep anr 通过main log,查找anr 发现; 07-03 14:53:10.395084 1557 1557 D ImsVT Util: onRecevied feature changed phoneId: 1, feature: 1, status: 0 07-03 14:53:10.395459 1557 1599 D ImsVT Uti...

wangjicong_215的博客 2045

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

Android系统启动流程

Android系统启动流程 文章目录Android系统启动流程一、概述三、流程1、init进程启动2、zygote进程---app_main.cpp3、zygote进程---ZygoteInit.java4、RuntimeInit.zygoteInit5、SystemServer.java6、ActivityManagerService 一、概述 android版本:7.1.2 Android系统的启动从最早的BootLoader->启动linux内核->Android_init进程->a

诺~~~ 3001
上一篇: 一份详细的Handler原理解析
Code_dh
博客等级 码龄8年 58粉丝 4原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值