2024年Framework底层服务,AMS PMS WMS原理分析_ams pms wms(1),HarmonyOS鸿蒙面试题的答案

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!


img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上鸿蒙开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

需要这份系统化的资料的朋友,可以戳这里获取

PackageHandler -> doHandleMessage(INIT_COPY)
-> connectToService()
{
连接成功
mBound = true;
}
-> bindServiceAsUser()
-> DefaultContainerConnection
-> onServiceConnected()
-> sendMessage(MCS_BOUND)

3、发送 MCS_BOUND 消息时,根据发送的 Message 是否带 Object 分为两种,如下所示:

void doHandleMessage(Message msg) {
switch (msg.what) {
case INIT_COPY: {

//mBound用于标识是否绑定了服务,默认值为false
if (!mBound) {

if (!connectToService()) {
// 绑定 DefaultContainerConnection 成功之后会发送
// mHandler.sendMessage(mHandler.obtainMessage(MCS_BOUND, Object));

//绑定服务失败则return
return;
} else {
//绑定服务成功,将请求添加到ArrayList类型的mPendingInstalls中,等待处理
mPendingInstalls.add(idx, params);
}
} else {
//已经绑定服务
mHandler.sendEmptyMessage(MCS_BOUND);
}
break;
}

}
}
}

4、 MCS_BOUND 消息的处理:

case MCS_BOUND: {
if (DEBUG_INSTALL) Slog.i(TAG, “mcs_bound”);
if (msg.obj != null) {

}
if (mContainerService == null) {//1

} elseif (mPendingInstalls.size() > 0) {//2
HandlerParams params = mPendingInstalls.get(0);//3
if (params != null) {
Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, “queueInstall”,
System.identityHashCode(params));
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, “startCopy”);
if (params.startCopy()) {//4
if (DEBUG_SD_INSTALL) Log.i(TAG,
“Checking for more work or unbind…”);
//如果APK安装成功,删除本次安装请求
if (mPendingInstalls.size() > 0) {
mPendingInstalls.remove(0);
}
if (mPendingInstalls.size() == 0) {
if (mBound) {
//如果没有安装请求了,发送解绑服务的请求
if (DEBUG_SD_INSTALL) Log.i(TAG,
“Posting delayed MCS_UNBIND”);
removeMessages(MCS_UNBIND);
Message ubmsg = obtainMessage(MCS_UNBIND);
sendMessageDelayed(ubmsg, 10000);
}
} else {
if (DEBUG_SD_INSTALL) Log.i(TAG,
“Posting MCS_BOUND for next work”);
//如果还有其他的安装请求,接着发送MCS_BOUND消息继续处理剩余的安装请求
mHandler.sendEmptyMessage(MCS_BOUND);
}
}
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}else {
Slog.w(TAG, “Empty queue”);
}
break;
}

2.复制APK

2.1 复制过程时序图
HandlerParams 是 PMS 中的抽象类,它的实现类为 PMS 的内部类 InstallParams。HandlerParams 的 startCopy 方法如下所示:

2.2 复制过程的源码分析
PackageManagerService.java#HandlerParams

final boolean startCopy() {
boolean res;
try {
if (DEBUG_INSTALL) Slog.i(TAG, "startCopy " + mUser + ": " + this);
//startCopy方法尝试的次数,超过了4次,就放弃这个安装请求
if (++mRetries > MAX_RETRIES) {
Slog.w(TAG, “Failed to invoke remote methods on default container service. Giving up”);
//MCS_GIVE_UP类型消息,将本次安装请求从安装请求队列mPendingInstalls中移除掉
mHandler.sendEmptyMessage(MCS_GIVE_UP);
handleServiceError();
returnfalse;
} else {
handleStartCopy(); // 注释①
res = true;
}
} catch (RemoteException e) {
if (DEBUG_INSTALL) Slog.i(TAG, “Posting install MCS_RECONNECT”);
mHandler.sendEmptyMessage(MCS_RECONNECT);
res = false;
}
handleReturnCode();
return res;
}

在 注释① 处调用抽象方法 handleStartCopy ,具体实现在 InstallParams 中,如下所示:
PackageManagerService.java#InstallParams

public void handleStartCopy() throws RemoteException {

//确定APK的安装位置。onSd:安装到SD卡, onInt:内部存储即Data分区,ephemeral:安装到临时存储(Instant Apps安装)
finalboolean onSd = (installFlags & PackageManager.INSTALL_EXTERNAL) != 0;
finalboolean onInt = (installFlags & PackageManager.INSTALL_INTERNAL) != 0;
finalboolean ephemeral = (installFlags & PackageManager.INSTALL_INSTANT_APP) != 0;
PackageInfoLite pkgLite = null;
if (onInt && onSd) {
// APK不能同时安装在SD卡和Data分区
Slog.w(TAG, “Conflicting flags specified for installing on both internal and external”);
ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
//安装标志冲突,Instant Apps不能安装到SD卡中
} elseif (onSd && ephemeral) {
Slog.w(TAG, “Conflicting flags specified for installing ephemeral on external”);
ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
} else {
//获取APK的少量的信息
pkgLite = mContainerService.getMinimalPackageInfo(origin.resolvedPath, installFlags,
packageAbiOverride);
if (DEBUG_EPHEMERAL && ephemeral) {
Slog.v(TAG, "pkgLite for install: " + pkgLite);
}

if (ret == PackageManager.INSTALL_SUCCEEDED) {
//判断安装的位置
int loc = pkgLite.recommendedInstallLocation;
if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_LOCATION) {
ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
} elseif (loc == PackageHelper.RECOMMEND_FAILED_ALREADY_EXISTS) {
ret = PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
}

}else{
loc = installLocationPolicy(pkgLite); // 注释①

}
}
//根据InstallParams创建InstallArgs对象
final InstallArgs args = createInstallArgs(this); // 注释②
mArgs = args;
if (ret == PackageManager.INSTALL_SUCCEEDED) {

if (!origin.existing && requiredUid != -1
&& isVerificationEnabled(
verifierUser.getIdentifier(), installFlags, installerUid)) {

} else{
ret = args.copyApk(mContainerService, true); // 注释③
}
}
mRet = ret;
}

  • 注释① 处确定了 APK 的安装位置。
  • 注释②处创建 InstallArgs 对象,此对象是一个抽象类,定义了 APK 的复制和重命名APK等安装逻辑,在 Android 8.x 及之前的版本中有三个子类:FileInstallArgs、AsecInstallArgs、MoveInstallArgs。其中 FileInstallArgs 用于处理安装到非ASEC的存储空间的APK,即内部存储空间(Data分区);AsecInstallArgs 用于处理安装到ASEC(mnt/asec)即SD卡中的APK;MoveInstallArgs 用于处理已安装APK的移动的逻辑;但在 Android 9.x 之后已经去掉了 AsecInstallArgs ,
  • 注释③ 处调用 InstallArgs 的 copyApk 方法,这里以 FileInstallArgs 的实现为例,内部会调用 FileInstallArgs 的 doCopyApk 方法:

private int doCopyApk(IMediaContainerService imcs, boolean temp) throws RemoteException {

try {
finalboolean isEphemeral = (installFlags & PackageManager.INSTALL_INSTANT_APP) != 0;
//创建临时文件存储目录
final File tempDir =
mInstallerService.allocateStageDirLegacy(volumeUuid, isEphemeral); // 注释①
codeFile = tempDir;
resourceFile = tempDir;
} catch (IOException e) {
Slog.w(TAG, "Failed to create copy file: " + e);
return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
}

int ret = PackageManager.INSTALL_SUCCEEDED;
ret = imcs.copyPackage(origin.file.getAbsolutePath(), target); // 注释②

return ret;
}

  • 注释① 处用于创建临时存储目录,比如 /data/app/vmdl18300388.tmp,其中 18300388 是安装的 sessionId;
  • 注释②处通过 IMediaContainerService 跨进程调用 DefaultContainerService 的 copyPackage 方法,这个方法会在 DefaultContainerService 所在的进程中将 APK 复制到临时存储目录,比如 /data/app/vmdl18300388.tmp/base.apk ,至此 APK 的复制工作结束。
3.APK的安装

3.1 APK安装时序图
在上述 APK 的赋值调用链的过程中,在 HandlerParams 的 startCopy 方法中,会调用 handleReturnCode 方法,时序图如下:

3.2 安装源码分析
PackageManagerService#handleReturnCode:

void handleReturnCode() {
if (mArgs != null) {
processPendingInstall(mArgs, mRet);
}
}

private void processPendingInstall(final InstallArgs args, final int currentStatus) {
mHandler.post(new Runnable() {
public void run() {
mHandler.removeCallbacks(this);
PackageInstalledInfo res = new PackageInstalledInfo();
res.setReturnCode(currentStatus);
res.uid = -1;
res.pkg = null;
res.removedInfo = null;
if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
//安装前处理
args.doPreInstall(res.returnCode); //注释①
synchronized (mInstallLock) {
installPackageTracedLI(args, res); //注释②
}
//安装后收尾
args.doPostInstall(res.returnCode, res.uid); //注释③
}

// 安装结束发送消息
Message msg = mHandler.obtainMessage(POST_INSTALL, token, 0); // 注释⑤
mHandler.sendMessage(msg);
}
});
}

  • 注释① 处检查APK的状态,在安装前确保安装环境的可靠,如果不可靠会清除复制的APK文件,注释③ 处会检测是否安装成功,失败则删除安装相关的目录和文件。安装完成之后在 注释⑤ 处会发送 POST_INSALL 消息通知已安装完成,此处稍后会说明。
  • 注释② 处的 installPackageTracedLI 会调用 PMS 的 installPackageLI 方法:
    PackageManagerService.java#installPackageLI:

private void installPackageLI(InstallArgs args, PackageInstalledInfo res) {

PackageParser pp = new PackageParser();
pp.setSeparateProcesses(mSeparateProcesses);
pp.setDisplayMetrics(mMetrics);
pp.setCallback(mPackageParserCallback);
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, “parsePackage”);
final PackageParser.Package pkg;
try {
//解析APK
pkg = pp.parsePackage(tmpPackageFile, parseFlags); //注释①
} catch (PackageParserException e) {
res.setError(“Failed parse during installPackageLI”, e);
return;
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}

pp = null;
String oldCodePath = null;
boolean systemApp = false;
synchronized (mPackages) {
// 检查APK是否存在
if ((installFlags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
String oldName = mSettings.getRenamedPackageLPr(pkgName);//获取没被改名前的包名
if (pkg.mOriginalPackages != null
&& pkg.mOriginalPackages.contains(oldName)
&& mPackages.containsKey(oldName)) {
pkg.setPackageName(oldName); //注释②
pkgName = pkg.packageName;
replace = true;//设置标志位表示是替换安装
if (DEBUG_INSTALL) Slog.d(TAG, “Replacing existing renamed package: oldName=”

  • oldName + " pkgName=" + pkgName);
    }

    }
    PackageSetting ps = mSettings.mPackages.get(pkgName);
    //查看Settings中是否存有要安装的APK的信息,如果有就获取签名信息
    if (ps != null) { //注释③
    if (DEBUG_INSTALL) Slog.d(TAG, "Existing package: " + ps);
    PackageSetting signatureCheckPs = ps;
    if (pkg.applicationInfo.isStaticSharedLibrary()) {
    SharedLibraryEntry libraryEntry = getLatestSharedLibraVersionLPr(pkg);
    if (libraryEntry != null) {
    signatureCheckPs = mSettings.getPackageLPr(libraryEntry.apk);
    }
    }
    //检查签名的正确性
    if (ksms.shouldCheckUpgradeKeySetLocked(signatureCheckPs, scanFlags)) {
    if (!ksms.checkUpgradeKeySetLocked(signatureCheckPs, pkg)) {
    res.setError(INSTALL_FAILED_UPDATE_INCOMPATIBLE, "Package "
  • pkg.packageName + " upgrade keys do not match the "
  • “previously installed version”);
    return;
    }
    }

    }

int N = pkg.permissions.size();
for (int i = N-1; i >= 0; i–) {
//遍历每个权限,对权限进行处理
PackageParser.Permission perm = pkg.permissions.get(i);
BasePermission bp = mSettings.mPermissions.get(perm.info.name);

}
}
}
if (systemApp) {
if (onExternal) {
//系统APP不能在SD卡上替换安装
res.setError(INSTALL_FAILED_INVALID_INSTALL_LOCATION,
“Cannot install updates to system apps on sdcard”);
return;
} elseif (instantApp) {
//系统APP不能被Instant App替换
res.setError(INSTALL_FAILED_INSTANT_APP_INVALID,
“Cannot update a system app with an instant app”);
return;
}
}

//重命名临时文件
if (!args.doRename(res.returnCode, pkg, oldCodePath)) { //注释④
res.setError(INSTALL_FAILED_INSUFFICIENT_STORAGE, “Failed rename”);
return;
}

startIntentFilterVerifications(args.user.getIdentifier(), replace, pkg);

try (PackageFreezer freezer = freezePackageForInstall(pkgName, installFlags,
“installPackageLI”)) {

if (replace) { //注释⑤
//替换安装

replacePackageLIF(pkg, parseFlags, scanFlags | SCAN_REPLACING, args.user,
installerPackageName, res, args.installReason);
} else {
//安装新的APK
installNewPackageLIF(pkg, parseFlags, scanFlags | SCAN_DELETE_DATA_ON_FAILURES,
args.user, installerPackageName, volumeUuid, res, args.installReason);
}
}

synchronized (mPackages) {
final PackageSetting ps = mSettings.mPackages.get(pkgName);
if (ps != null) {
//更新应用程序所属的用户
res.newUsers = ps.queryInstalledUsers(sUserManager.getUserIds(), true);
ps.setUpdateAvailable(false/updateAvailable/);
}

}
}

这里需要说明几点:

1、注释③处,会先检测 Settings 中保存有要安装的 APK 信息,则说明安装该 APK ,因此需要检验APK 的签名信息,确保安全的进行替换。
2、注释④处,会对临时文件重新命名,例如 /data/app/vmdl18300388.tmp/base.apk,重命名为 /data/app/包名-oONlnRRPYyleU63AveqbYA==/base.apk。新的包名后面带上的一串字母和数字的混合字符串,是使用MD5的方式对随机生成的16个字符进行加密之后的产物。
3、注释⑤处,根据 replace 来做区分,如果是替换安装就会调用replacePackageLIF方法,其方法内部还会对系统APP和非系统APP进行区分处理,如果是新安装APK会调用installNewPackageLIF方法
PackageManagerService.java#installNewPackageLIF:

private void installNewPackageLIF(PackageParser.Package pkg, final int policyFlags,
int scanFlags, UserHandle user, String installerPackageName, String volumeUuid,
PackageInstalledInfo res, int installReason) {

try {
//扫描APK
PackageParser.Package newPackage = scanPackageTracedLI(pkg, policyFlags, scanFlags,
System.currentTimeMillis(), user);
//更新Settings信息
updateSettingsLI(newPackage, installerPackageName, null, res, user, installReason);
if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
//安装成功后,为新安装的应用程序准备数据
prepareAppDataAfterInstallLIF(newPackage);

} else {
//安装失败则删除APK
deletePackageLIF(pkgName, UserHandle.ALL, false, null,
PackageManager.DELETE_KEEP_DATA, res.removedInfo, true, null);
}
} catch (PackageManagerException e) {
res.setError("Package couldn’t be installed in " + pkg.codePath, e);
}
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}

4.发送消息

在上面 processPendingInstall 方法的源码分析中,在 注释⑤ 处会发送 POST_INSTALL 消息通知安装完成,那么接下来就来具体看一看在 PackageHandler 中是怎么处理这个消息的。

class PackageHandler extends Handler {
void doHandleMessage(Message msg) {
switch (msg.what) {
… …

case POST_INSTALL: {
… …
handlePackagePostInstall();
… …
break;
}
}
}
}

private void handlePackagePostInstall(…){
// 如果已经成功的安装了应用,在发送广播之前先授予一些必要的权限
grantRequestedRuntimePermissions(res.pkg, args.user.getIdentifier(),
args.installGrantPermissions);

// 安装完成之后发送"ACTION_PACKAGE_ADDED"广播
sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
packageName, extras, null, null, firstUsers);

// 如果是升级更新安装,还会发送ACTION_PACKAGE_REPLACED和ACTION_MY_PACKAGE_REPLACED广播
// 这两个广播不同之处在于PACKAGE_REPLACE将携带一个extra信息
sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED,
packageName, extras, null, null, updateUsers);
sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED,
null, null, packageName, null, updateUsers);

// 执行gc操作
Runtime.getRuntime().gc();

// 调用FileInstallArgs的doPostDeleteLI进行资源清理
res.removedInfo.args.doPostDeleteLI(true);

// 回调onPackageInstalled方法
installObserver.onPackageInstalled(res.name, res.returnCode,
res.returnMsg, extras);
}

以上为主要的方法摘要,具体可总结为:

1、第一步:这里主要是先将安装信息从安装列列表中移除,这个也是前面在processPendingInstall中添加的
2、第二步:安装成功后,获取运行时权限
3、第三步:获取权限后,发送ACTION_PACKAGE_ADDED广播,告诉Laucher之流,更新icon
4、第四步:如果是升级更新则在发送两条广播

  • ACTION_PACKAGE_REPLACED:一个新版本的应用安装到设备上,替换换之前已经存在的版本
  • ACTION_MY_PACKAGE_REPLACED:应用的新版本替换旧版本被安装,只发给被更新的应用自己

5、第五步:如果安装包中设置了PRIVATE_FLAG_FORWARD_LOCK或者被要求安装在SD卡上,则调用sendResourcesChangedBroadcast方法来发送一个资源更改的广播
6、第六步:如果该应用是一个浏览器,则要清除浏览器设置,重新检查浏览器设置
7、第七步:强制调用gc,出发JVM进行垃圾回收操作
8、第八步:删除旧的安装信息
9、回调回调 IPackageInstallObserver2 的 packageInstalled 方法。告诉 PackageInstaller 安装结果。从而实现了安装回调到UI层

5.安装总结

上述几部分大致说明 PMS 处理 APK 的主要步骤,可总结如下:

1、当 PackageInstaller 将 APK 的信息提交给 PMS 处理,PMS 会通过向 PackageHandler 发送消息来驱动 APK 的复制和安装工作
2、PMS 发送 INIT_COPY 和 MCS_BOUND 类型的消息,控制 PackageHandler 来绑定 DefaultContainerService 来完成 APK 的复制等工作
3、复制 APK 完成之后,则开始进行安装 APK 的流程,包括安装前的检查、安装 APK 和安装后的收尾工作。

WMS篇

WindowManagerService服务(WMS)的实现是相当复杂的,毕竟它要管理的整个系统所有窗口的UI,而在任何一个系统中,窗口管理子系统都是极其复杂的。而WMS就是管理整个系统的窗口的。

WMS功能
  • 窗口管理:负责启动、添加、删除窗口,管理窗口大小、层级,核心成员有:WindowContainer、RootWindowContainer、* DisplayContent、TaskStack、Task、AppWindowToken、WindowState;
  • 窗口动画:由其子系统 WindowAnimator 管理;
  • 输入系统中转站:通过对窗口的触摸从而产生触摸事件,由 InputMethodService(IMS)对触摸事件进行处理,它会寻找一个最合适的窗口处理触摸反馈信息;
  • Surface 管理:为每个窗口分配一块 Surface,用于绘制要显示的内容。

WMS创建过程中线程关系

WMS 创建过程中涉及到的类主要有 SystemServer、WindowManagerService(WMS)、WindowManagerPolicy(WMP),它们都在 system_server 进程中运行,但是会在不同线程中运行,如下所示。

WMS启动流程

(1)main

public static void main(String[] args) {
new SystemServer().run();
}

(2)run

/frameworks/base/services/java/com/android/server/SystemServer.java

private void run() {
try {

// 创建Looper
Looper.prepareMainLooper();
// 加载libandroid_servers.so
System.loadLibrary(“android_servers”);
// 创建系统的 Context:ContextImpl.createSystemContext(new ActivityThread())
createSystemContext();
// 创建 SystemServiceManager
mSystemServiceManager = new SystemServiceManager(mSystemContext);
LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);

}

try {
//启动引导服务,ActivityManagerService、ActivityTaskManagerService、PackageManagerService、PowerManagerService、DisplayManagerService 等
startBootstrapServices();
//启动核心服务,BatteryService、UsageStatusService 等
startCoreServices();
//启动其他服务,InputManagerService、WindowManagerService、CameraService、AlarmManagerService 等
startOtherServices();

}

// 开启消息循环
Looper.loop();
}

(3)startOtherServices

/frameworks/base/services/java/com/android/server/SystemServer.java

private void startOtherServices() {

WindowManagerService wm = null;

InputManagerService inputManager = null;

try {

inputManager = new InputManagerService(context);

//PhoneWindowManager 是 WMP 的实现类
wm = WindowManagerService.main(context, inputManager, !mFirstBoot, mOnlyCore, new PhoneWindowManager(), mActivityManagerService.mActivityTaskManager);
ServiceManager.addService(Context.WINDOW_SERVICE, wm, false, DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PROTO);
ServiceManager.addService(Context.INPUT_SERVICE, inputManager, false, DUMP_FLAG_PRIORITY_CRITICAL);

mActivityManagerService.setWindowManager(wm);

wm.onInitReady(); //initPolicy

//wm 的 mInputManagerCallback 属性在定义时就被初始化
inputManager.setWindowManagerCallbacks(wm.getInputManagerCallback());
inputManager.start();

}

try {
wm.displayReady(); //初始化屏幕信息
}

try {
wm.systemReady(); //通知 WMS 系统的初始化完成
}

final Configuration config = wm.computeNewConfiguration(DEFAULT_DISPLAY);

}

注意:在 WindowManagerService.main() 中,传入了 InputManagerService、PhoneWindowManager(WindowManagerPolicy 的实现类)、ActivityTaskManagerService(简称 ATMS

通过 ServiceManager.addService() 将 Context.WINDOW_SERVICE 与 WMS 绑定,因此在其他进程中可以通过如下方式获取 WMS。

IBinder b = ServiceManager.getService(Context.WINDOW_SERVICE);
IWindowManager wm = IWindowManager.Stub.asInterface(b);

(3)main

public static WindowManagerService main(final Context context, final InputManagerService im, final boolean showBootMsgs,
final boolean onlyCore, WindowManagerPolicy policy, ActivityTaskManagerService atm) {
return main(context, im, showBootMsgs, onlyCore, policy, atm, SurfaceControl.Transaction::new);
}

public static WindowManagerService main(final Context context, final InputManagerService im, final boolean showBootMsgs,
final boolean onlyCore, WindowManagerPolicy policy, ActivityTaskManagerService atm, TransactionFactory transactionFactory) {
//在 android.display 线程中创建 WMS(此时 system_server 线程阻塞)
DisplayThread.getHandler().runWithScissors(() ->
sInstance = new WindowManagerService(context, im, showBootMsgs, onlyCore, policy, atm, transactionFactory), 0);
return sInstance;
}

WMS 初始化

本节主要研究 WMS 在初始化时做的工作。

(1)构造函数

/frameworks/base/services/java/com/android/server/wm/WindowManagerService.java

private WindowManagerService(Context context, InputManagerService inputManager, boolean showBootMsgs, boolean onlyCore,
WindowManagerPolicy policy, ActivityTaskManagerService atm, TransactionFactory transactionFactory) {

mAtmService = atm;
mContext = context;

mInputManager = inputManager;
mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);

mPolicy = policy;
//动画管理
mAnimator = new WindowAnimator(this);
//根容器,其子容器是 DisplayContent
mRoot = new RootWindowContainer(this);
mWindowPlacerLocked = new WindowSurfacePlacer(this);

//mPolicy 是 PhoneWindowManager 对象,WindowManagerPolicy 的实现类
LocalServices.addService(WindowManagerPolicy.class, mPolicy);

//DM
mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
//PM
mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
//AMS
mActivityManager = ActivityManager.getService();
//ATMS
mActivityTaskManager = ActivityTaskManager.getService();
//ActivityManagerInternal
mAmInternal = LocalServices.getService(ActivityManagerInternal.class);
//ActivityTaskManagerInternal
mAtmInternal = LocalServices.getService(ActivityTaskManagerInternal.class);

//PackageManagerInternal
mPmInternal = LocalServices.getService(PackageManagerInternal.class);
//添加本地服务
LocalServices.addService(WindowManagerInternal.class, new LocalService());
}
LocalService 是 WMS 的内部类,也是 WindowManagerInternal 的实现类。

(2)初始化 WMP

public void onInitReady() {
//初始化 WMP
initPolicy();

//打开 Surface 事务:SurfaceControl.openTransaction()
openSurfaceTransaction();

}
private void initPolicy() {
//在 android.ui 线程中执行
UiThread.getHandler().runWithScissors(new Runnable() {
@Override
public void run() {
WindowManagerPolicyThread.set(Thread.currentThread(), Looper.myLooper());
mPolicy.init(mContext, WindowManagerService.this, WindowManagerService.this);
}
}, 0);
}

(3)初始化 Display

public void displayReady() {
synchronized (mGlobalLock) {
if (mMaxUiWidth > 0) {
mRoot.forAllDisplays(displayContent -> displayContent.setMaxUiWidth(mMaxUiWidth));
}
final boolean changed = applyForcedPropertiesForDefaultDisplay();
mAnimator.ready();

}

updateCircularDisplayMaskIfNeeded();
}

(4)通知系统 WMS 初始化完成

public void systemReady() {
mSystemReady = true;
mPolicy.systemReady();
mRoot.forAllDisplayPolicies(DisplayPolicy::systemReady);
mTaskSnapshotController.systemReady();

UiThread.getHandler().post(mSettingsObserver::updateSystemUiSettings);
UiThread.getHandler().post(mSettingsObserver::updatePointerLocation);

}

总结

服务端
  • AMS 主要用于管理所有应用程序的Activity
  • WMS 管理各个窗口,隐藏,显示等
  • PMS 用来管理跟踪所有应用APK,安装,解析,控制权限等.
  • 还有用来处理触摸消息的两个类KeyInputQueue和InputDispatchThread,一个用来读消息,一个用来分发消息.。
客户端
  • 主要包括ActivityThread,Activity,DecodeView及父类View,PhoneWindow,ViewRootImpl及内部类等
  • ActivityThread主要用来和AMS通讯的客户端,Activity是我们编写应用比较熟悉的类。

这里只是简单的认识和归纳总结一下,非常感谢以上博主的贡献。后期我会深入了解Android系统的源码,然后专开一个专栏来详细介绍PMS、AMS、WMS。
技术资料提供:Frame Work源码解析手册

最后

如果想要成为架构师或想突破20~30K薪资范畴,那就不要局限在编码,业务,要会选型、扩展,提升编程思维。此外,良好的职业规划也很重要,学习的习惯很重要,但是最重要的还是要能持之以恒,任何不能坚持落实的计划都是空谈。

如果你没有方向,这里给大家分享一套由阿里高级架构师编写的《Android八大模块进阶笔记》,帮大家将杂乱、零散、碎片化的知识进行体系化的整理,让大家系统而高效地掌握Android开发的各个知识点。
在这里插入图片描述
相对于我们平时看的碎片化内容,这份笔记的知识点更系统化,更容易理解和记忆,是严格按照知识体系编排的。

一、架构师筑基必备技能

1、深入理解Java泛型
2、注解深入浅出
3、并发编程
4、数据传输与序列化
5、Java虚拟机原理
6、高效IO
……

在这里插入图片描述

二、Android百大框架源码解析

1.Retrofit 2.0源码解析
2.Okhttp3源码解析
3.ButterKnife源码解析
4.MPAndroidChart 源码解析
5.Glide源码解析
6.Leakcanary 源码解析
7.Universal-lmage-Loader源码解析
8.EventBus 3.0源码解析
9.zxing源码分析
10.Picasso源码解析
11.LottieAndroid使用详解及源码解析
12.Fresco 源码分析——图片加载流程

在这里插入图片描述

三、Android性能优化实战解析
  • 腾讯Bugly:对字符串匹配算法的一点理解
  • 爱奇艺:安卓APP崩溃捕获方案——xCrash
  • 字节跳动:深入理解Gradle框架之一:Plugin, Extension, buildSrc
  • 百度APP技术:Android H5首屏优化实践
  • 支付宝客户端架构解析:Android 客户端启动速度优化之「垃圾回收」
  • 携程:从智行 Android 项目看组件化架构实践
  • 网易新闻构建优化:如何让你的构建速度“势如闪电”?

在这里插入图片描述

四、高级kotlin强化实战

1、Kotlin入门教程
2、Kotlin 实战避坑指南
3、项目实战《Kotlin Jetpack 实战》

  • 从一个膜拜大神的 Demo 开始
  • Kotlin 写 Gradle 脚本是一种什么体验?
  • Kotlin 编程的三重境界
  • Kotlin 高阶函数
  • Kotlin 泛型
  • Kotlin 扩展
  • Kotlin 委托
  • 协程“不为人知”的调试技巧
  • 图解协程:suspend

在这里插入图片描述

五、Android高级UI开源框架进阶解密

1.SmartRefreshLayout的使用
2.Android之PullToRefresh控件源码解析
3.Android-PullToRefresh下拉刷新库基本用法
4.LoadSir-高效易用的加载反馈页管理框架
5.Android通用LoadingView加载框架详解
6.MPAndroidChart实现LineChart(折线图)
7.hellocharts-android使用指南
8.SmartTable使用指南
9.开源项目android-uitableview介绍
10.ExcelPanel 使用指南
11.Android开源项目SlidingMenu深切解析
12.MaterialDrawer使用指南
在这里插入图片描述

六、NDK模块开发

1、NDK 模块开发
2、JNI 模块
3、Native 开发工具
4、Linux 编程
5、底层图片处理
6、音视频开发
7、机器学习

在这里插入图片描述

七、Flutter技术进阶

1、Flutter跨平台开发概述
2、Windows中Flutter开发环境搭建
3、编写你的第一个Flutter APP
4、Flutter开发环境搭建和调试
5、Dart语法篇之基础语法(一)
6、Dart语法篇之集合的使用与源码解析(二)
7、Dart语法篇之集合操作符函数与源码分析(三)

在这里插入图片描述

八、微信小程序开发

1、小程序概述及入门
2、小程序UI开发
3、API操作
4、购物商场项目实战……

在这里插入图片描述

全套视频资料:

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

img.cn/f1905585c6d346a8b0a8fefcfa553bc4.png)

六、NDK模块开发

1、NDK 模块开发
2、JNI 模块
3、Native 开发工具
4、Linux 编程
5、底层图片处理
6、音视频开发
7、机器学习

在这里插入图片描述

七、Flutter技术进阶

1、Flutter跨平台开发概述
2、Windows中Flutter开发环境搭建
3、编写你的第一个Flutter APP
4、Flutter开发环境搭建和调试
5、Dart语法篇之基础语法(一)
6、Dart语法篇之集合的使用与源码解析(二)
7、Dart语法篇之集合操作符函数与源码分析(三)

在这里插入图片描述

八、微信小程序开发

1、小程序概述及入门
2、小程序UI开发
3、API操作
4、购物商场项目实战……

在这里插入图片描述

全套视频资料:

[外链图片转存中…(img-dn66Bg9e-1715608563716)]
[外链图片转存中…(img-PjWr9QhO-1715608563716)]

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 17
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值