Android 12系统源码_屏幕设备(一)DisplayManagerService的启动
前言
DisplayManagerService是Android Framework中管理显示屏幕相关的模块,各种Display的连接、配置等,都是通过DMS和来管理控制。
在DMS模块中,对显示屏幕的描述分为物理显示屏(physical display)和逻辑显示屏(logical display),物理屏主要从SurfaceFlinger中读取参数创建,代表实实在在的物理屏,描述其物理特性,不同物理屏有不同的属性。逻辑屏则是相对于对物理屏,侧重于同一个物理屏的不同逻辑设置,受应用和WMS模块影响,如显示区域、显示位置坐标、显示方向等。每一个物理屏幕都对应一个逻辑屏幕,可以修改逻辑屏幕参数,做到同一个物理屏的不同显示方式。
由于不同的物理显示屏有不同的属性和处理方式,因此DMS中通过一系列的屏幕适配器(DisplayAdapter)来和分别各种物理显示屏进行连接。
一、DMS模块常见类
1.1 全局管理类
- IDisplayManager: IBinder接口,负责DMS和其他组建的IPC工作;
- DisplayManagerService:继承于SystemService的系统服务,负责整个系统display的控制和管理;
- DisplayManagerService.LocalService: 继承于DisplayManagerInternal,负责system_server内部其他模块和DMS的交互;
- DisplayManagerService.BindService: 继承于IDisplayManager,是IDisplayManager的具体实现类;
- DisplayManagerService.CallbackRecord: DMS内部类,内部持有IDisplayManagerCallback对象,负责执行IDisplayManagerCallback的回调;
- DisplayManager: 暴露给App层的接口,内部持有DisplayManagerGlobal对象引用,利用DisplayManagerGlobal和DMS进行交互;
- IDisplayManagerCallback:一个IBinder接口,DMS中发生display相关动作后,会通过该接口回调通知给DisplayManagerGlobal;
- DisplayManagerGlobal:内部持有IDisplayManager对象引用,App层通过该对象和DMS进行跨IPC交互;
- DisplayManagerGlobal.DisplayManagerCallback: 继承于IDisplayManagerCallback接口,负责接收来自DMS中display事件的回调;
1.2 数据封装类
- DisplayDevice: 屏幕设备对象。
- DisplayDeviceRepository:屏幕设备管理者,内部持有DisplayDevice集合,负责管理屏幕设备对象。
- WifiDisplayDevice:DisplayDevice的子类,代表通过Wifi连接显示的物理屏幕;
- OverlayDisplayDevice:DisplayDevice的子类,开发者选项->模拟辅助显示开启后,创建的就是该类对象;
- VirtualDisplayDevice:DisplayDevice的子类,表示虚拟显示屏幕,用于屏幕录制等;
- LocalDisplayDevice:DisplayDevice的子类,代表内置物理屏幕,DMS启动后会通过SurfaceControl去读取内置屏幕数据,并创建该类对象;
- LogicalDisplay:代表逻辑显示屏,每一个physical display都会对应一个logical display;
- LogicalDisplayMapper:逻辑屏幕设备管理者,内部持有LogicalDisplay对象集合
- DisplayDeviceInfo: DisplayDevice信息封装类,在创建DisplayDevice时会进行创建,与之对应的是Logical display 的DisplayInfo;
- DisplayInfo:LogicalDisplay信息的封装类,基本数据由DisplayDeviceInfo中获得,app可以通过WMS来修改自己的参数;
- DisplayAdapter: 各物理屏和DMS进行连接的适配器;
- LocalDisplayAdapter: 继承于DisplayAdapter, 用于LocalDisplayDevice和DMS的连接;
- WifiDisplayAdapter: 继承于DisplayAdapter,用于WifiDisplayDevice的和DMS的连接;
- OverlayDisplayAdapter:继承于DisplayAdapter,用于OverlayDisplayDevice和DMS的连接;
- VirtualDisplayAdapter:继承于DisplayAdapter,用于VirtualDisplayDevice和DMS的连接;
- DisplayAdapter.Listener:用于通知DisplayDevice发生变化的接口,DMS中对其进行了实现,会接收以下三个事件并根据事件作出全局反应:a.添加了新的DisplayDevice ;b.DisplayDevice状态发生变化; c.移除DisplayDevice。
- DisplayViewport:携带有physical display参数,用于通知IMS display信息。
1.3 基本类结构的对应关系图
1.4 源码位置
包名 | 目录 | 描述 | 例子 |
---|---|---|---|
android.hardware.display | frameworks/base/core/java/android/hardware/display | DMS模块管理 | DisplayManager, DisplayMangaerGlobal, … |
android.view | frameworks/base/core/java/android/view | 逻辑屏配置项相关 | DisplayInfo, DisplayViewport, … |
com.android.server.display | frameworks/base/services/core/java/com/android/server/display | DMS核心 | DMS,DisplayDevice, … |
二、DisplayManagerService的启动流程
系统启动后会启动JVM虚拟机,SystemServer 是虚拟机的第一个进程,由init 进程fork 产生,主要用来启动frameworks层中的服务,DMS服务也是在这里被启动的,下面我们简单列出SystemServer中和DMS启动相关的源码。
frameworks/base/service/java/com/android/server/SystemServer.java
public final class SystemServer {private DisplayManagerService mDisplayManagerService;public static void main(String[] args) {new SystemServer().run();}private void run() {...代码省略...try {t.traceBegin("StartServices");startBootstrapServices(t);//引导服务startCoreServices(t);//核心服务startOtherServices(t);//其他服务} catch (Throwable ex) {Slog.e("System", "******************************************");Slog.e("System", "************ Failure starting system services", ex);throw ex;} finally {t.traceEnd(); // StartServices}...代码省略...}private void startBootstrapServices(@NonNull TimingsTraceAndSlog t) {...代码省略...// Display manager is needed to provide display metrics before package manager// starts up.t.traceBegin("StartDisplayManager");mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class);//通过反射构建对象实例t.traceEnd();// We need the default display before we can initialize the package manager.t.traceBegin("WaitForDisplay");mSystemServiceManager.startBootPhase(t, SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);//调用DMS的onBootPhase方法t.traceEnd();...代码省略...// DisplayManagerService needs to setup android.display scheduling related policies// since setSystemProcess() would have overridden policies due to setProcessGroupmDisplayManagerService.setupSchedulerPolicies();//调用DMS的setupSchedulerPolicies方法...代码省略...}private void startOtherServices(@NonNull TimingsTraceAndSlog t) {...代码省略...t.traceBegin("DisplayManagerWindowManagerAndInputReady");mDisplayManagerService.windowManagerAndInputReady();//调用DMS的windowManagerAndInputReady方法t.traceEnd();...代码省略...t.traceBegin("MakeDisplayManagerServiceReady");try {mDisplayManagerService.systemReady(safeMode, mOnlyCore);//调用DMS的systemReady方法} catch (Throwable e) {reportWtf("making Display Manager Service ready", e);}t.traceEnd();}
}
2.1 构造方法
DisplayManagerService实例对象是通过SystemServiceManager的startService方法获得的,该方法内部先是通过反射构建DisplayManagerService对象实例的,然后还会调用该对象的onStart方法,先来看下构造方法。
frameworks/base/services/core/java/com/android/server/display/DisplayManagerService.java
public final class DisplayManagerService extends SystemService {private final Context mContext;//android.display线程的Handlerprivate final DisplayManagerHandler mHandler;//android.ui线程Handlerprivate final Handler mUiHandler;//主要负责管理和协调设备的显示模式,包括分辨率、刷新率等。//它优化了系统的显示设置,以平衡性能和电池使用,并确保在多显示器配置下的显示效果一致。private final DisplayModeDirector mDisplayModeDirector;//屏幕设备管理者, 此类内容维护了一个 DisplayDevice 对象的集合,这些对象代表了系统中所有的显示设备。//可以通过这个类跟踪各个显示设备的状态、属性和配置。private final DisplayDeviceRepository mDisplayDeviceRepo;//主要负责逻辑显示设备的映射和管理,确保物理显示设备的状态和配置能够正确映射到逻辑显示设备上。//这个类对于支持多显示器和虚拟显示设备的系统功能至关重要。private final LogicalDisplayMapper mLogicalDisplayMapper;private final Injector mInjector;//负责同步和管理屏幕亮度设置,以确保多个显示设备或显示区域的亮度一致,同时优化用户体验和系统协调。private final BrightnessSynchronizer mBrightnessSynchronizer;public DisplayManagerService(Context context) {this(context, new Injector());}@VisibleForTestingDisplayManagerService(Context context, Injector injector) {super(context);mInjector = injector;mContext = context;//android.display线程handlermHandler = new DisplayManagerHandler(DisplayThread.get().getLooper());//android.ui线程HandlermUiHandler = UiThread.getHandler();//管理所有的屏幕设备mDisplayDeviceRepo = new DisplayDeviceRepository(mSyncRoot, mPersistentDataStore);//负责逻辑显示设备的映射和管理mLogicalDisplayMapper = new LogicalDisplayMapper(mContext, mDisplayDeviceRepo,new LogicalDisplayListener(), mSyncRoot, mHandler);//负责管理和协调设备的显示模式mDisplayModeDirector = new DisplayModeDirector(context, mHandler);//负责同步和管理屏幕亮度设置mBrightnessSynchronizer = new BrightnessSynchronizer(mContext);Resources resources = mContext.getResources();mDefaultDisplayDefaultColorMode = mContext.getResources().getInteger(com.android.internal.R.integer.config_defaultDisplayDefaultColorMode);mDefaultDisplayTopInset = SystemProperties.getInt(PROP_DEFAULT_DISPLAY_TOP_INSET, -1);float[] lux = getFloatArray(resources.obtainTypedArray(com.android.internal.R.array.config_minimumBrightnessCurveLux));float[] nits = getFloatArray(resources.obtainTypedArray(com.android.internal.R.array.config_minimumBrightnessCurveNits));mMinimumBrightnessCurve = new Curve(lux, nits);mMinimumBrightnessSpline = Spline.createSpline(lux, nits);mCurrentUserId = UserHandle.USER_SYSTEM;ColorSpace[] colorSpaces = SurfaceControl.getCompositionColorSpaces();mWideColorSpace = colorSpaces[1];mAllowNonNativeRefreshRateOverride = mInjector.getAllowNonNativeRefreshRateOverride();mSystemReady = false;}
}
2.2 执行onStart方法
public final class DisplayManagerService extends SystemService {private final PersistentDataStore mPersistentDataStore = new PersistentDataStore();@Overridepublic void onStart() {// 加载数据synchronized (mSyncRoot) {mPersistentDataStore.loadIfNeeded();//加载display中的固定数据loadStableDisplayValuesLocked();}// 在android.display线程中创建默认DisplayAdapter,并进行注册mHandler.sendEmptyMessage(MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS);// If there was a runtime restart then we may have stale caches left around, so we need to// make sure to invalidate them upon every start.DisplayManagerGlobal.invalidateLocalDisplayInfoCaches();//向ServiceManager注册BinderService,以便其他模块可以跨进程调用publishBinderService(Context.DISPLAY_SERVICE, new BinderService(),true /*allowIsolated*/);//注册Local ServicepublishLocalService(DisplayManagerInternal.class, new LocalService());}}
2.2.1 加载display中的固定数据
frameworks/base/services/core/java/com/android/server/display/PersistentDataStore.java
final class PersistentDataStore {private Injector mInjector;public PersistentDataStore() {this(new Injector());}@VisibleForTestingPersistentDataStore(Injector injector) {mInjector = injector;}public void loadIfNeeded() {if (!mLoaded) {load();mLoaded = true;}}private void load() {clearState();final InputStream is;try {is = mInjector.openRead();} catch (FileNotFoundException ex) {return;}TypedXmlPullParser parser;try {parser = Xml.resolvePullParser(is);loadFromXml(parser);} catch (IOException ex) {Slog.w(TAG, "Failed to load display manager persistent store data.", ex);clearState();} catch (XmlPullParserException ex) {Slog.w(TAG, "Failed to load display manager persistent store data.", ex);clearState();} finally {IoUtils.closeQuietly(is);}}static class Injector {private final AtomicFile mAtomicFile;public Injector() {//display配置的文件路径mAtomicFile = new AtomicFile(new File("/data/system/display-manager-state.xml"), "display-state");}public InputStream openRead() throws FileNotFoundException {return mAtomicFile.openRead();}public OutputStream startWrite() throws IOException {return mAtomicFile.startWrite();}public void finishWrite(OutputStream os, boolean success) {if (!(os instanceof FileOutputStream)) {throw new IllegalArgumentException("Unexpected OutputStream as argument: " + os);}FileOutputStream fos = (FileOutputStream) os;if (success) {mAtomicFile.finishWrite(fos);} else {mAtomicFile.failWrite(fos);}}}
}
利用PersistentDataStore加载display中的固定数据,这些数据都是以xml文件的形式,保存在/data/system/display-manager-state.xml中;
2.2.2 注册屏幕适配器
public final class DisplayManagerService extends SystemService {private static final int MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS = 1;private static final int MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS = 2;@Overridepublic void onStart() {...代码省略...// android.display线程中创建默认DisplayAdapter,并进行注册mHandler.sendEmptyMessage(MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS);...代码省略...}private final class DisplayManagerHandler extends Handler {@Overridepublic void handleMessage(Message msg) {switch (msg.what) {case MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS://注册默认的屏幕适配器registerDefaultDisplayAdapters();break;case MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS://注册额外的屏幕设备适配器registerAdditionalDisplayAdapters();break;...代码省略... }}}private void registerDefaultDisplayAdapters() {synchronized (mSyncRoot) {//注册默认的屏幕适配器registerDisplayAdapterLocked(new LocalDisplayAdapter(mSyncRoot, mContext, mHandler, mDisplayDeviceRepo));//注册虚拟的屏幕适配器mVirtualDisplayAdapter = mInjector.getVirtualDisplayAdapter(mSyncRoot, mContext,mHandler, mDisplayDeviceRepo);if (mVirtualDisplayAdapter != null) {registerDisplayAdapterLocked(mVirtualDisplayAdapter);}}}
}
2.3 执行onBootPhase方法
DisplayManagerService的onStart()方法被执行完毕后,onBootPhase()方法将会被执行。
public final class DisplayManagerService extends SystemService {@Overridepublic void onBootPhase(int phase) {if (phase == PHASE_WAIT_FOR_DEFAULT_DISPLAY) {synchronized (mSyncRoot) {//Injector的getDefaultDisplayDelayTimeout默认返回10秒long timeout = SystemClock.uptimeMillis() + mInjector.getDefaultDisplayDelayTimeout();// 超过timeout之后,如果默认屏幕的逻辑显示屏为空,则抛出异常while (mLogicalDisplayMapper.getDisplayLocked(Display.DEFAULT_DISPLAY) == null|| mVirtualDisplayAdapter == null) {long delay = timeout - SystemClock.uptimeMillis();if (delay <= 0) {throw new RuntimeException("Timeout waiting for default display "+ "to be initialized. DefaultDisplay="+ mLogicalDisplayMapper.getDisplayLocked(Display.DEFAULT_DISPLAY)+ ", mVirtualDisplayAdapter=" + mVirtualDisplayAdapter);}if (DEBUG) {Slog.d(TAG, "waitForDefaultDisplay: waiting, timeout=" + delay);}try {mSyncRoot.wait(delay);} catch (InterruptedException ex) {}}}} else if (phase == PHASE_BOOT_COMPLETED) {mDisplayModeDirector.onBootCompleted();}}
}
PHASE_WAIT_FOR_DEFAULT_DISPLAY阶段是最早的一个启动阶段,当一些引导服务启动完毕后,启动后续服务时,检查DMS是否已经创建默认逻辑屏,如果在10s内没有完成默认LogicalDisplay的创建,则抛出异常。
2.4 执行setupSchedulerPolicies方法
public final class DisplayManagerService extends SystemService {public void setupSchedulerPolicies() {// 给android.display、android.anim、android.anim.lf三个线程设置组和CPU集Process.setThreadGroupAndCpuset(DisplayThread.get().getThreadId(),Process.THREAD_GROUP_TOP_APP);Process.setThreadGroupAndCpuset(AnimationThread.get().getThreadId(),Process.THREAD_GROUP_TOP_APP);Process.setThreadGroupAndCpuset(SurfaceAnimationThread.get().getThreadId(),Process.THREAD_GROUP_TOP_APP);}}
给以上三个线程设置线程组和调度集,将线程组设为Process.THREAD_GROUP_TOP_APP,以确保更加高效的执行。
2.5 执行windowManagerAndInputReady方法
当SystemServer中启动WindowManagerService和InputManagerService后,将调用此方法通知DMS。
public final class DisplayManagerService extends SystemService {private static final int MSG_REQUEST_TRAVERSAL = 4;//WMS和输入法启动完毕public void windowManagerAndInputReady() {synchronized (mSyncRoot) {mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);//获取设备状态服务并设置回调对象DeviceStateManager deviceStateManager = mContext.getSystemService(DeviceStateManager.class);deviceStateManager.registerCallback(new HandlerExecutor(mHandler), new DeviceStateListener());//通知WMS进行窗口更新流程scheduleTraversalLocked(false);}}private void scheduleTraversalLocked(boolean inTraversal) {if (!mPendingTraversal && mWindowManagerInternal != null) {mPendingTraversal = true;if (!inTraversal) {mHandler.sendEmptyMessage(MSG_REQUEST_TRAVERSAL);}}}private final class DisplayManagerHandler extends Handler {@Overridepublic void handleMessage(Message msg) {switch (msg.what) {...代码省略... case MSG_REQUEST_TRAVERSAL://通知WMS进行窗口更新流程mWindowManagerInternal.requestTraversalFromDisplayManager();break;...代码省略... }}}}
先是获得WMS和IMS各自的LocalService对象,然后将发起显示内容更新流程,请求WMS模块进行窗口更新。DMS和WMS联系非常紧密,通常当DMS中相关属性发生变化后,会通知WMS进行窗口更新,WMS在更新过程中也会通知DMS,应用来自窗口的Display相关属性。
2.6 执行systemReady方法
此方法DMS在SystemServer中被调用的最后一个方法,通知DMS启动完成:
public final class DisplayManagerService extends SystemService {private static final String PROP_DEFAULT_DISPLAY_TOP_INSET = "persist.sys.displayinset.top";private static final int MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS = 1;//注册物理屏幕适配器、虚拟屏幕适配器private static final int MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS = 2;//注册其他屏幕适配器public void systemReady(boolean safeMode, boolean onlyCore) {synchronized (mSyncRoot) {mSafeMode = safeMode;mOnlyCore = onlyCore;mSystemReady = true;//启动完成//将默认Display的top inset存储到persist.sys.displayinset.top中recordTopInsetLocked(mLogicalDisplayMapper.getDisplayLocked(Display.DEFAULT_DISPLAY));updateSettingsLocked();updateUserDisabledHdrTypesFromSettingsLocked();}mDisplayModeDirector.setDesiredDisplayModeSpecsListener(new DesiredDisplayModeSpecsObserver());mDisplayModeDirector.start(mSensorManager);//注册除了物理屏幕适配器、虚拟屏幕适配器以外的其他屏幕适配器mHandler.sendEmptyMessage(MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS);mSettingsObserver = new SettingsObserver();mBrightnessSynchronizer.startSynchronizing();}private void recordTopInsetLocked(@Nullable LogicalDisplay d) {if (!mSystemReady || d == null) {return;}int topInset = d.getInsets().top;if (topInset == mDefaultDisplayTopInset) {return;}mDefaultDisplayTopInset = topInset;//将默认Display的top inset存储到persist.sys.displayinset.top中SystemProperties.set(PROP_DEFAULT_DISPLAY_TOP_INSET, Integer.toString(topInset));} private final class DisplayManagerHandler extends Handler {@Overridepublic void handleMessage(Message msg) {switch (msg.what) {case MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS://注册默认的屏幕适配器registerDefaultDisplayAdapters();break;case MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS://注册额外的屏幕设备适配器registerAdditionalDisplayAdapters();break;...代码省略... }}}//注册额外的屏幕适配器对象private void registerAdditionalDisplayAdapters() {synchronized (mSyncRoot) {if (shouldRegisterNonEssentialDisplayAdaptersLocked()) {registerOverlayDisplayAdapterLocked();//注册模拟辅助设备屏幕适配器registerWifiDisplayAdapterLocked();//注册WIFI屏幕适配器}}}private void registerOverlayDisplayAdapterLocked() {registerDisplayAdapterLocked(new OverlayDisplayAdapter(mSyncRoot, mContext, mHandler, mDisplayDeviceRepo, mUiHandler));}private void registerWifiDisplayAdapterLocked() {if (mContext.getResources().getBoolean(com.android.internal.R.bool.config_enableWifiDisplay)|| SystemProperties.getInt(FORCE_WIFI_DISPLAY_ENABLE, -1) == 1) {mWifiDisplayAdapter = new WifiDisplayAdapter(mSyncRoot, mContext, mHandler, mDisplayDeviceRepo,mPersistentDataStore);registerDisplayAdapterLocked(mWifiDisplayAdapter);}}private void registerDisplayAdapterLocked(DisplayAdapter adapter) {//将适配器对面添加到适配器集合中mDisplayAdapters.add(adapter);adapter.registerLocked();}
}
此方法该会通过mHandler发起注册其他DeviceAdapter的操作,最终完成四种DisplayAdapter的注册。
三 总结
相关文章:
Android 12系统源码_屏幕设备(一)DisplayManagerService的启动
前言 DisplayManagerService是Android Framework中管理显示屏幕相关的模块,各种Display的连接、配置等,都是通过DMS和来管理控制。 在DMS模块中,对显示屏幕的描述分为物理显示屏(physical display)和逻辑显示屏(logical display),…...
《AI视频类工具之十——D-ID》
一.简介 官网:D-ID | The #1 Choice for AI Generated Video Creation Platform D-ID是一个人工智能生成的视频创建平台,可以轻松快速地从文本输入中创建高质量、高性价比和引人入胜的视频,背后的Al技术是由Stable Difusion和GPT.3提供支持,可以在没有任何技术知识的情况…...
【网络】局域网LAN、广域网WAN、TCP/IP协议、封装和分用
文章目录 局域网 LAN广域网 WAN网络中的重要概念IP 地址端口号 认识协议协议分层是什么OSI 七层网络模型TCP/IP 五层网络模型(或四层)物理层传输层网络层数据链表层应用层网络设备所在分层 封装和分用[站在发送方视角](封装)[站在…...
我司搜索中台的三次演变
本人从入职就开始负责我司的搜索中台了,总共是经历了三个大版本的迭代。 分别是: 基于阿里云智能开放搜索OpenSearch实现的第一代自研,开源canal(数据同步) 底层阿里云elasticsearch 对索引封装 实现的第二代自研&a…...
html+css+js网页设计 电商模版4个页面
htmlcssjs网页设计 电商模版4个页面 带js 网页作品代码简单,可使用任意HTML编辑软件(如:Dreamweaver、HBuilder、Vscode 、Sublime 、Webstorm、Text 、Notepad 等任意html编辑软件进行运行及修改编辑等操作)。 获取源码 1&…...
区块链技术在Facebook中的潜力:未来趋势与挑战
数据安全的新高度 区块链技术以其去中心化和不可篡改的特性,正在成为提升数据安全和隐私保护的重要工具。Facebook作为全球最大的社交媒体平台之一,正积极探索如何将区块链技术应用于其平台,以增强用户数据的安全性和隐私保护。Facebook在应…...
dockerfile自定义镜像
目录 概念 基于dockerfile创建 dockerfile的命令 构建容器 FROM ENTRYPOINT和CMD RUN COPY和ADD 工作目录和环境变量以及容器卷(挂载卷) EXPOSE 实战 概念 dockerfile就是自定义镜像,通过dockerfile创建的都是镜像,而…...
【工作状态】如何保持专注?
好的睡眠计划主题化 1、保持足够的睡眠,才能头脑清晰和有精力,工作不是纯拼体力,要用脑力的。 2、脑力主要工作放在午餐前,在脑力充足的时候使用脑力,下午五点后可以安排脑力活动较低的工作,比如听课读书。…...
欧科云链研究院对话:风浪越大鱼越贵—链上数据洞悉加密市场规律
作者 Hedy 出品 OKG Research “我们从来就不是理性人。但可以用最简单的工具——链上数据做‘最猛’的分析。” 在经历了超级宏观周之后,金融市场产生了巨大的震荡,加密市场的表现也越来越受到宏观经济因素的影响。欧科云链研究院OKG Research 集结多…...
SQLite库笔记:日期和时间函数
1. 函数概述 SQLite支持7个日期和时间函数,如下: 1 date(time-value, modifier, modifier, ...) 返回YYYY-MM-DD格式的日期 2 time(time-value, modifier, modifier, ...) 返回HH:MM:SS格式的时间 3 datetime(time-value, modifier, modifier, ...…...
Linux开发板运行报错/system/bin/sh: can‘t create /dev/leds: Permission denied
Linux开发板运行报错/system/bin/sh: cant create /dev/leds: Permission denied 1.问题解决 1.问题解决 /system/bin/sh: can’t create /dev/leds: Permission denied 在linux开发板下运行驱动报错没有权限,需要运行 su,同时也会停止打印 在运行: ch…...
月薪5W的项目经理是如何面试的?这份面试攻略请收好!
面试是项目经理求职必须经历的一关,但很多经验不够丰富的项目经理不知道面试会问些什么问题,也不知道要怎么回答,无疑会直接影响面试企业的判断,使项目经理求职受阳.所以,项目经理想要顺利求职,还是有必要掌…...
接口隔离原则
接口隔离原则 接口隔离原则就是客户端不应该依赖它不需要的接口,或者说类间的依赖关系应该建立在最小的接口上。 我们以搜索美女为例,设计了如下的类图: 源代码如下。美女及其实现类: 搜索程序及其子类源代码如下: 最…...
【C++ 面试 - 基础题】每日 3 题(十六)
✍个人博客:Pandaconda-CSDN博客 📣专栏地址:http://t.csdnimg.cn/fYaBd 📚专栏简介:在这个专栏中,我将会分享 C 面试中常见的面试题给大家~ ❤️如果有收获的话,欢迎点赞👍收藏&…...
端到端测试自动化:使用JavaScript打造可靠的Web应用
端到端测试(End-to-End Testing,简称E2E测试)是软件测试的一种形式,用于验证整个应用从端到端的流程是否按预期工作。在JavaScript生态系统中,E2E测试通常使用专门的框架来模拟用户交互,验证应用的业务逻辑…...
『大模型笔记』基于LLM生成真实世界数据的合成问答数据!
基于LLM生成真实世界数据的合成问答数据! 文章目录 一. 基于LLM生成真实世界数据的合成问答数据!1. 概述(Overview)2. 场景(Scenario)2.1. 概述2.1.1. 第1阶段:构建种子数据集(Stage 1. Constructing a seed dataset)2.1.2. 第2阶段:数据增强(可选)(Data Augmentation…...
一个使用Python和`scikit-learn`库实现KMeans聚类算法的简单示例
一个使用Python和scikit-learn库实现KMeans聚类算法的简单示例。首先,请确保您已经安装了scikit-learn库。如果没有安装,可以通过pip安装它: pip install scikit-learn下面是一个简单的例子,展示如何使用scikit-learn中的KMeans进…...
记录一下vue2和vue3中如何配置keep-alive及写法上的差异
应用场景 跳转下一个页面后,返回当前页面,或者在多个页面之间切换,保留页面中的所有状态,常见的就是填写到一半的表单。h5的tabbar页面缓存,避免重复加载数据。 主要实现思路 这个东西很常见,动态路由一…...
面试题:Rabbitmq怎么保证消息的可靠性?
1.消费端消息可靠性保证: 消息确认(Acknowledgements):(自动(默认),手动) 消费者在接收到消息后,默认情况下RabbitMQ会自动确认消息(autoAcktrue)。为保证消息可靠性,可以设置auto…...
性能测试工具之JMeter
JMeter Apache JMeter应用程序是开源软件,是一个100%纯Java应用程序,旨在负载测试功能行为和衡量性能。它最初是为测试Web应用程序而设计的,但后来扩展到其他测试功能。 JMeter是一个免费、开源、跨平台的性能测试工具,于20世纪90年代后期面世。这是一个成熟、健全且具有…...
SQL Zoo 9-.Window functions
以下数据均来自SQL Zoo 1.Show the lastName, party and votes for the constituency S14000024 in 2017.(显示2017年选区“S14000024”的姓氏、政党和选票) SELECT lastName, party, votesFROM geWHERE constituency S14000024 AND yr 2017 ORDER BY…...
智能化清理C盘的方法 小白也可以轻松清理C盘了 不再担心误删文件
智能化清理C盘的方法 小白用户也可以轻松清理C盘了 不再担心误删文件。对于电脑小白来说,C盘清理是一个大大的问题,因为大家都不知道C盘里有哪些文件可以删除,哪些不能删除,所以就直接的导致大家不可能去清理c盘垃圾。 就算是C盘…...
在c#中常用的特性
在C#中,特性(Attributes)是一种将元数据应用于程序实体(如类、方法、属性等)的方式。这些元数据可以在编译时和运行时被读取,常用于配置、自定义行为、装饰器模式等场景。以下是一些C#中常用的特性…...
Polars简明基础教程十二:可视化(二)
设置绘图后端 我们可以使用 hv.extension 更改绘图后端。但是,我们不在此处运行此单元格,因为它会导致下面的 Matplotlib/Seaborn 图表无法渲染。 注释: hvPlot 利用 HoloViews 库来构建图表,并且可以使用多个后端进行渲染&…...
python 使用正则表达式判断图片路径是否是超链接
在Python中,判断一个给定的字符串(假设为图片路径)是否是网页链接(URL),你可以通过检查该字符串是否符合URL的基本格式来实现。虽然这个方法不能保证链接一定指向图片,但它能判断该字符串是否是…...
【学习笔记】Day 14
一、进度概述 1、《地震勘探原理》第七章 二、详情 地震波动力学是相对于运动学而言的。运动学主要研究波的传播规律,其主要特征是分析、研究波的传播路径。传播速度。旅行时间等。地震波动力学则主要从能量的角度研究地震波的特征,如波的振幅、波形、频…...
使用SSL认证访问操作手册
完整版,从证书生成到使用 【金山文档 | WPS云文档】 使用SSL认证访问操作手册 https://kdocs.cn/l/cuxGfHD17eEw...
网络协议 十一 ARP,RARP,icmp,websocket,webservice,HTTPDNS,FTP,邮件相关的协议, SMTP,POP,IMAP
ARP 已知IP 求 MAC 的过程 RARP 已知MAC 求 IP 的过程,已被DHCP取代 ICMP websocket 协议,html5中提出的前端使用协议 webservice 技术,已过时 HTTPDNS 之前我们要获得 某一个域名的 IP ,要通过DNS协议 去 运营商的ISP 查询&…...
浏览器插件利器--allWebPluginV2.0.0.16-Stable版发布
allWebPlugin简介 allWebPlugin中间件是一款为用户提供安全、可靠、便捷的浏览器插件服务的中间件产品,致力于将浏览器插件重新应用到所有浏览器。它将现有ActiveX控件直接嵌入浏览器,实现插件加载、界面显示、接口调用、事件回调等。支持Chrome、Firefo…...
设计模式22-迭代器模式
设计模式22-迭代器模式 迭代器模式(Iterator Pattern)动机定义结构定义结构结构图解释注意事项 C代码推导多态属性(虚函数)实现迭代器1. **返回值问题**2. **对象切割问题**3. **内存管理问题**4. **迭代器生命周期问题**5. **接口…...
重庆网站建设零臻靠谱/无经验能做sem专员
目录 〇,最强大脑同款游戏 《第1-4季》 一,盲填数独 二,盲指过天桥 三,盲填折线数独 四,盲填骑士跳 五,七阶幻立方 六,泰森多边形 七,分形 八,数独王中王&…...
程序员做网站美工能过关吗/百度云搜索引擎官网
【Struts2国际化资源文件定义的3种范围方法】1)全局的国际化资源文件,对所有的Action和View都有效定义方式:在struts.xml中增加全局资源文件定路径定义: <constant name"struts.custom.i18n.resources" value…...
网站源码完整/百度前三推广
目录 简介 安装 单独使用 const store createStore(reducer) store.subscribe(fun) store.getState() store.dispatch(obj) 示例 结合react使用 Provider const mapStateToProps state>(obj) const mapDispatchToProps obj connection 示例 index.js sto…...
徐州鸿美网站建设/网站分析案例
说实话,还真有点紧张 毕竟刚毕业一年吗,上一家公司 主要是入门,而且是行业软件。然而这家公司有些不同,电子商务,互联网转载于:https://www.cnblogs.com/haihang/p/3498753.html...
网站建设需要资料/营销方案案例范文
MD5的全称是Message-Digest Algorithm 5,在90年代初由MIT的计算机科学实验室和RSA Data Security Inc发明,经MD2、MD3和MD4发展而来。 MD5将任意长度的“字节串”变换成一个128bit的大整数,并且它是一个不可逆的字符串变换算法࿰…...
免费素材网站哪个最好/百度引擎的搜索方式是什么
写查询语句的时候有时候会突然来这么一句提示,仔细看sql还没什么错误。 报错代码 SQL> select l.awuname,g.aultext,d.aulword2 from aw_usercotrl l,aw_userlog g,aw_userlog_lword d3 where l.awuid g.awuid and g.aulid d.fkaulid4 ;select from whereO…...