diff --git a/.obsidian/workspace.json b/.obsidian/workspace.json index 4bda4c1..e8e243e 100644 --- a/.obsidian/workspace.json +++ b/.obsidian/workspace.json @@ -200,6 +200,9 @@ }, "active": "25c9f7051aac05b3", "lastOpenFiles": [ + "docs/android面试/系统原理/DPMS常见面试题.md", + "docs/android面试/系统原理/DPMS常见面试题", + "docs/DPMS常见面试题", "docs/android面试/系统原理/AMS面试.md", "ams常见面试题.txt", "docs/android面试/系统原理/WMS面试.md", @@ -227,14 +230,11 @@ "docs/Google开发文档体系/核心主题/Material_Design.md", "docs/Google开发文档体系/核心主题/Jetpack组件.md", "docs/Google开发文档体系/示例代码/架构示例.md", - "docs/Google开发文档体系/示例代码/官方示例项目.md", "docs/Google开发文档体系/视频和教程", "docs/Google开发文档体系/核心主题", "docs/Google开发文档体系/示例代码", "docs/Google开发文档体系/最佳实践", "docs/Google开发文档体系/工具和资源", - "docs/Google开发文档体系/入门指南", - "docs/Google开发文档体系/API参考", - "docs/Google开发文档体系" + "docs/Google开发文档体系/入门指南" ] } \ No newline at end of file diff --git a/docs/android面试/系统原理/AMS面试.md b/docs/android面试/系统原理/AMS面试.md index e7935c4..70d7ef8 100644 --- a/docs/android面试/系统原理/AMS面试.md +++ b/docs/android面试/系统原理/AMS面试.md @@ -1,288 +1,305 @@ -AMS常见面试题 +# AMS常见面试题 -================================================================================ -一、AMS基础概念 -================================================================================ +--- -Q1: 什么是AMS?它的作用是什么? +## 一、AMS基础概念 -A: AMS(ActivityManagerService)是Android系统的核心服务之一,运行在system_server进程中。 +### Q1: 什么是AMS?它的作用是什么? -主要作用: -1. Activity生命周期管理:管理Activity的创建、启动、暂停、停止、销毁等生命周期 -2. Service生命周期管理:管理Service的启动、绑定、停止等 -3. BroadcastReceiver管理:管理广播的注册、发送、接收 -4. 进程管理:管理应用进程的创建、销毁、优先级调整 -5. 任务栈管理:管理Activity任务栈(Task Stack),处理启动模式、Intent Flag等 -6. 内存管理:监控应用内存使用,进行进程回收和内存优化 +**A:** AMS(ActivityManagerService)是Android系统的核心服务之一,运行在system_server进程中。 -Q2: AMS在系统启动流程中的位置? +**主要作用:** -A: AMS在系统启动流程中的位置: -1. Bootloader阶段:加载Linux内核 -2. Kernel启动:初始化硬件,启动init进程 -3. Init进程:解析init.rc,启动Zygote和ServiceManager -4. Zygote进程:预加载类和资源,fork出SystemServer进程 -5. SystemServer进程:启动各类系统服务 +1. **Activity生命周期管理**:管理Activity的创建、启动、暂停、停止、销毁等生命周期 +2. **Service生命周期管理**:管理Service的启动、绑定、停止等 +3. **BroadcastReceiver管理**:管理广播的注册、发送、接收 +4. **进程管理**:管理应用进程的创建、销毁、优先级调整 +5. **任务栈管理**:管理Activity任务栈(Task Stack),处理启动模式、Intent Flag等 +6. **内存管理**:监控应用内存使用,进行进程回收和内存优化 + +### Q2: AMS在系统启动流程中的位置? + +**A:** AMS在系统启动流程中的位置: + +1. **Bootloader阶段**:加载Linux内核 +2. **Kernel启动**:初始化硬件,启动init进程 +3. **Init进程**:解析init.rc,启动Zygote和ServiceManager +4. **Zygote进程**:预加载类和资源,fork出SystemServer进程 +5. **SystemServer进程**:启动各类系统服务 - 启动AMS(ActivityManagerService) - 启动WMS(WindowManagerService) - 启动PMS(PackageManagerService) - 启动其他系统服务 -6. AMS启动Launcher:系统服务就绪后,AMS启动Launcher应用 +6. **AMS启动Launcher**:系统服务就绪后,AMS启动Launcher应用 -Q3: AMS与其他系统服务的关系? +### Q3: AMS与其他系统服务的关系? -A: AMS与其他系统服务的关系: -1. AMS与WMS:AMS负责Activity的生命周期,WMS负责窗口的显示和布局 -2. AMS与PMS:AMS需要PMS提供包信息来启动Activity -3. AMS与Zygote:AMS通过Zygote创建新进程 -4. AMS与Binder:AMS通过Binder机制与应用进程通信 +**A:** AMS与其他系统服务的关系: -================================================================================ -二、Activity启动流程 -================================================================================ +1. **AMS与WMS**:AMS负责Activity的生命周期,WMS负责窗口的显示和布局 +2. **AMS与PMS**:AMS需要PMS提供包信息来启动Activity +3. **AMS与Zygote**:AMS通过Zygote创建新进程 +4. **AMS与Binder**:AMS通过Binder机制与应用进程通信 -Q4: 请详细描述Activity的启动流程? +--- -A: Activity启动流程(以跨进程启动为例): +## 二、Activity启动流程 -客户端进程(应用A): -1. Activity.startActivity(Intent intent) -2. Instrumentation.execStartActivity() -3. ActivityManager.getService().startActivity() +### Q4: 请详细描述Activity的启动流程? + +**A:** Activity启动流程(以跨进程启动为例): + +**客户端进程(应用A):** + +1. `Activity.startActivity(Intent intent)` +2. `Instrumentation.execStartActivity()` +3. `ActivityManager.getService().startActivity()` - 通过Binder调用AMS的startActivity方法 -服务端进程(system_server): -4. ActivityManagerService.startActivity() -5. ActivityManagerService.startActivityAsUser() -6. ActivityStarter.startActivity() +**服务端进程(system_server):** + +4. `ActivityManagerService.startActivity()` +5. `ActivityManagerService.startActivityAsUser()` +6. `ActivityStarter.startActivity()` - 检查权限和Intent - 解析目标Activity信息 -7. ActivityStarter.startActivityUnchecked() +7. `ActivityStarter.startActivityUnchecked()` - 处理启动模式(standard、singleTop、singleTask、singleInstance) - 处理Intent Flag -8. ActivityStackSupervisor.startActivityLocked() +8. `ActivityStackSupervisor.startActivityLocked()` - 创建或查找ActivityRecord - 查找或创建任务栈(Task) -9. ActivityStack.startActivityLocked() +9. `ActivityStack.startActivityLocked()` - 将ActivityRecord添加到任务栈 -10. ActivityStack.resumeTopActivityLocked() +10. `ActivityStack.resumeTopActivityLocked()` - 暂停当前Activity - 准备启动目标Activity -11. ActivityStackSupervisor.realStartActivityLocked() +11. `ActivityStackSupervisor.realStartActivityLocked()` - 检查目标进程是否存在 - 如果不存在,通过Zygote创建新进程 - 通过ApplicationThread发送启动消息 -目标进程(应用B): -12. ApplicationThread.scheduleLaunchActivity() +**目标进程(应用B):** + +12. `ApplicationThread.scheduleLaunchActivity()` - 接收AMS的启动消息 -13. ActivityThread.handleLaunchActivity() +13. `ActivityThread.handleLaunchActivity()` - 创建Activity实例 - 调用Activity.attach() - 调用Activity.onCreate() -14. ActivityThread.performResumeActivity() +14. `ActivityThread.performResumeActivity()` - 调用Activity.onStart() - 调用Activity.onResume() 15. 通过Binder通知AMS:Activity启动完成 -Q5: Activity启动过程中,AMS如何检查权限? +### Q5: Activity启动过程中,AMS如何检查权限? -A: AMS在启动Activity时会进行以下权限检查: +**A:** AMS在启动Activity时会进行以下权限检查: -1. 目标Activity的exported属性检查 +1. **目标Activity的exported属性检查** - 如果exported=false,只有同应用可以启动 - 如果exported=true,其他应用可以启动 -2. 权限检查 +2. **权限检查** - 检查调用方是否有启动目标Activity的权限 - 检查目标Activity声明的权限要求 -3. Intent Filter匹配 +3. **Intent Filter匹配** - 如果是隐式Intent,检查Intent Filter是否匹配 -4. 签名权限检查 +4. **签名权限检查** - 如果目标Activity声明了签名权限,检查调用方签名 -关键代码位置: -- ActivityStarter.checkStartActivityPermission() -- ActivityStarter.resolveActivity() +**关键代码位置:** +- `ActivityStarter.checkStartActivityPermission()` +- `ActivityStarter.resolveActivity()` -Q6: Activity的启动模式是如何在AMS中实现的? +### Q6: Activity的启动模式是如何在AMS中实现的? -A: AMS通过ActivityStack和ActivityRecord管理启动模式: +**A:** AMS通过ActivityStack和ActivityRecord管理启动模式: -1. standard模式(标准模式) +1. **standard模式(标准模式)** - 每次启动都创建新的ActivityRecord - 添加到当前任务栈顶部 -2. singleTop模式(栈顶复用) +2. **singleTop模式(栈顶复用)** - 检查栈顶Activity是否为目标Activity - 如果是,复用并调用onNewIntent() - 如果不是,创建新实例 -3. singleTask模式(栈内复用) +3. **singleTask模式(栈内复用)** - 检查任务栈中是否存在目标Activity - 如果存在,复用并清理其上方的Activity - 如果不存在,创建新实例 -4. singleInstance模式(单实例) +4. **singleInstance模式(单实例)** - 创建独立的任务栈 - 该栈中只有这一个Activity -关键代码位置: -- ActivityStarter.startActivityUnchecked() -- ActivityStack.findActivityLocked() -- ActivityStack.startActivityLocked() +**关键代码位置:** +- `ActivityStarter.startActivityUnchecked()` +- `ActivityStack.findActivityLocked()` +- `ActivityStack.startActivityLocked()` -Q7: Intent Flag是如何影响Activity启动的? +### Q7: Intent Flag是如何影响Activity启动的? -A: 常见的Intent Flag及其在AMS中的处理: +**A:** 常见的Intent Flag及其在AMS中的处理: -1. FLAG_ACTIVITY_NEW_TASK +1. **FLAG_ACTIVITY_NEW_TASK** - 创建新的任务栈 - 如果任务栈已存在,则复用 -2. FLAG_ACTIVITY_CLEAR_TOP +2. **FLAG_ACTIVITY_CLEAR_TOP** - 如果目标Activity在栈中,清理其上方的Activity - 复用目标Activity并调用onNewIntent() -3. FLAG_ACTIVITY_SINGLE_TOP +3. **FLAG_ACTIVITY_SINGLE_TOP** - 效果类似singleTop启动模式 - 如果栈顶是目标Activity,复用 -4. FLAG_ACTIVITY_CLEAR_TASK +4. **FLAG_ACTIVITY_CLEAR_TASK** - 清除任务栈中所有Activity - 然后启动目标Activity -5. FLAG_ACTIVITY_REORDER_TO_FRONT +5. **FLAG_ACTIVITY_REORDER_TO_FRONT** - 如果目标Activity在栈中,将其移到栈顶 - 不创建新实例 -关键代码位置: -- ActivityStarter.computeLaunchingTaskFlags() -- ActivityStack.startActivityLocked() +**关键代码位置:** +- `ActivityStarter.computeLaunchingTaskFlags()` +- `ActivityStack.startActivityLocked()` -================================================================================ -三、Service启动流程 -================================================================================ +--- -Q8: Service的启动流程是怎样的? +## 三、Service启动流程 -A: Service启动流程: +### Q8: Service的启动流程是怎样的? -客户端进程: -1. Context.startService(Intent intent) -2. ContextImpl.startService() -3. ActivityManager.getService().startService() +**A:** Service启动流程: + +**客户端进程:** + +1. `Context.startService(Intent intent)` +2. `ContextImpl.startService()` +3. `ActivityManager.getService().startService()` - 通过Binder调用AMS -服务端进程(system_server): -4. ActivityManagerService.startService() -5. ActiveServices.startServiceLocked() +**服务端进程(system_server):** + +4. `ActivityManagerService.startService()` +5. `ActiveServices.startServiceLocked()` - 检查Service是否已启动 - 创建ServiceRecord -6. ActiveServices.bringUpServiceLocked() +6. `ActiveServices.bringUpServiceLocked()` - 检查目标进程是否存在 - 如果不存在,通过Zygote创建进程 -7. ActiveServices.realStartServiceLocked() +7. `ActiveServices.realStartServiceLocked()` - 通过ApplicationThread发送创建消息 -目标进程: -8. ApplicationThread.scheduleCreateService() -9. ActivityThread.handleCreateService() +**目标进程:** + +8. `ApplicationThread.scheduleCreateService()` +9. `ActivityThread.handleCreateService()` - 创建Service实例 - 调用Service.onCreate() 10. 通过Binder通知AMS:Service创建完成 -Q9: Service的绑定流程是怎样的? +### Q9: Service的绑定流程是怎样的? -A: Service绑定流程: +**A:** Service绑定流程: -客户端进程: -1. Context.bindService(Intent intent, ServiceConnection conn, int flags) -2. ContextImpl.bindService() -3. ActivityManager.getService().bindService() +**客户端进程:** + +1. `Context.bindService(Intent intent, ServiceConnection conn, int flags)` +2. `ContextImpl.bindService()` +3. `ActivityManager.getService().bindService()` - 通过Binder调用AMS -服务端进程: -4. ActivityManagerService.bindService() -5. ActiveServices.bindServiceLocked() +**服务端进程:** + +4. `ActivityManagerService.bindService()` +5. `ActiveServices.bindServiceLocked()` - 检查Service是否已启动 - 如果未启动,先启动Service -6. ActiveServices.requestServiceBindingLocked() +6. `ActiveServices.requestServiceBindingLocked()` - 创建ConnectionRecord - 通过ApplicationThread发送绑定消息 -目标进程: -7. ApplicationThread.scheduleBindService() -8. ActivityThread.handleBindService() +**目标进程:** + +7. `ApplicationThread.scheduleBindService()` +8. `ActivityThread.handleBindService()` - 调用Service.onBind() - 返回IBinder对象 9. 通过Binder将IBinder传递给客户端 10. 客户端ServiceConnection.onServiceConnected()被调用 -Q10: Service的启动和绑定有什么区别? +### Q10: Service的启动和绑定有什么区别? -A: 启动和绑定的区别: +**A:** 启动和绑定的区别: -启动(startService): +**启动(startService):** - 生命周期:onCreate() -> onStartCommand() -> onDestroy() - 独立运行:Service独立于启动它的组件运行 - 停止方式:调用stopService()或Service.stopSelf() - 适用场景:后台任务、音乐播放等 -绑定(bindService): +**绑定(bindService):** - 生命周期:onCreate() -> onBind() -> onUnbind() -> onDestroy() - 依赖关系:Service与绑定它的组件生命周期关联 - 停止方式:所有组件解绑后自动停止 - 适用场景:需要与Activity交互、提供接口给其他组件 -混合模式: +**混合模式:** - 可以同时启动和绑定 - 需要同时调用stopService()和解绑才会销毁 -================================================================================ -四、BroadcastReceiver流程 -================================================================================ +--- -Q11: BroadcastReceiver的注册流程是怎样的? +## 四、BroadcastReceiver流程 -A: BroadcastReceiver注册流程: +### Q11: BroadcastReceiver的注册流程是怎样的? + +**A:** BroadcastReceiver注册流程: + +**静态注册(AndroidManifest.xml):** -静态注册(AndroidManifest.xml): 1. 系统启动时,PMS解析AndroidManifest.xml -2. 发现标签,创建Receiver信息 +2. 发现``标签,创建Receiver信息 3. 注册到AMS的ReceiverList中 -动态注册(代码中): -1. Context.registerReceiver(BroadcastReceiver receiver, IntentFilter filter) -2. ContextImpl.registerReceiver() -3. ActivityManager.getService().registerReceiver() +**动态注册(代码中):** + +1. `Context.registerReceiver(BroadcastReceiver receiver, IntentFilter filter)` +2. `ContextImpl.registerReceiver()` +3. `ActivityManager.getService().registerReceiver()` - 通过Binder调用AMS -4. ActivityManagerService.registerReceiver() +4. `ActivityManagerService.registerReceiver()` - 创建ReceiverList - 保存到AMS的mRegisteredReceivers中 -Q12: 广播的发送和接收流程是怎样的? +### Q12: 广播的发送和接收流程是怎样的? -A: 广播发送和接收流程: +**A:** 广播发送和接收流程: -发送广播: -1. Context.sendBroadcast(Intent intent) -2. ContextImpl.sendBroadcast() -3. ActivityManager.getService().broadcastIntent() +**发送广播:** + +1. `Context.sendBroadcast(Intent intent)` +2. `ContextImpl.sendBroadcast()` +3. `ActivityManager.getService().broadcastIntent()` - 通过Binder调用AMS -AMS处理: -4. ActivityManagerService.broadcastIntent() -5. BroadcastQueue.enqueueBroadcast() +**AMS处理:** + +4. `ActivityManagerService.broadcastIntent()` +5. `BroadcastQueue.enqueueBroadcast()` - 将广播加入队列 -6. BroadcastQueue.scheduleBroadcastsLocked() +6. `BroadcastQueue.scheduleBroadcastsLocked()` - 调度广播分发 -接收广播: -7. BroadcastQueue.processNextBroadcast() +**接收广播:** + +7. `BroadcastQueue.processNextBroadcast()` - 查找匹配的Receiver - 按优先级排序 8. 对于动态注册的Receiver: @@ -291,426 +308,429 @@ AMS处理: 9. 对于静态注册的Receiver: - 如果进程不存在,先启动进程 - 然后发送广播 -10. ActivityThread.handleReceiver() +10. `ActivityThread.handleReceiver()` - 创建Receiver实例 - 调用Receiver.onReceive() 11. 如果是有序广播,等待当前Receiver处理完成后再发送下一个 -Q13: 有序广播和普通广播的区别? +### Q13: 有序广播和普通广播的区别? -A: 有序广播(Ordered Broadcast)和普通广播的区别: +**A:** 有序广播(Ordered Broadcast)和普通广播的区别: -普通广播(sendBroadcast): +**普通广播(sendBroadcast):** - 所有Receiver同时接收 - 无法中断传播 - 无法传递结果 - 效率较高 -有序广播(sendOrderedBroadcast): +**有序广播(sendOrderedBroadcast):** - Receiver按优先级顺序接收 - 可以中断传播(abortBroadcast()) - 可以传递结果(setResult()) - 效率较低 -优先级设置: -- 静态注册:在中设置android:priority +**优先级设置:** +- 静态注册:在``中设置android:priority - 动态注册:在IntentFilter中设置setPriority() -================================================================================ -五、进程管理 -================================================================================ +--- -Q14: AMS如何管理应用进程? +## 五、进程管理 -A: AMS的进程管理机制: +### Q14: AMS如何管理应用进程? -1. 进程创建 +**A:** AMS的进程管理机制: + +1. **进程创建** - 当需要启动Activity/Service时,检查目标进程是否存在 - 如果不存在,通过Zygote创建新进程 - 创建ProcessRecord记录进程信息 -2. 进程优先级 +2. **进程优先级** - FOREGROUND_APP:前台应用,优先级最高 - VISIBLE_APP:可见应用 - SERVICE:后台服务 - BACKGROUND_APP:后台应用 - EMPTY_APP:空进程,优先级最低 -3. 进程回收(Low Memory Killer) +3. **进程回收(Low Memory Killer)** - 当系统内存不足时,按优先级回收进程 - 优先回收EMPTY_APP、BACKGROUND_APP - 最后回收FOREGROUND_APP -4. 进程通信 +4. **进程通信** - 通过Binder机制与应用进程通信 - ApplicationThread是应用进程的Binder服务端 -Q15: AMS如何判断进程是否需要回收? +### Q15: AMS如何判断进程是否需要回收? -A: AMS判断进程是否需要回收的因素: +**A:** AMS判断进程是否需要回收的因素: -1. 进程优先级 +1. **进程优先级** - 优先级越低,越容易被回收 -2. 内存使用情况 +2. **内存使用情况** - 进程占用的内存越大,越容易被回收 -3. 进程状态 +3. **进程状态** - 空进程(没有Activity、Service、Receiver)优先回收 - 后台进程次之 - 前台进程最后回收 -4. 用户交互 +4. **用户交互** - 最近使用的进程不容易被回收 - 长时间未使用的进程容易被回收 -5. 进程重要性 +5. **进程重要性** - 系统进程不会被回收 - 关键服务进程不容易被回收 -关键代码位置: -- ActivityManagerService.updateOomAdjLocked() -- ProcessList.computeOomAdjLocked() +**关键代码位置:** +- `ActivityManagerService.updateOomAdjLocked()` +- `ProcessList.computeOomAdjLocked()` -================================================================================ -六、任务栈管理 -================================================================================ +--- -Q16: 什么是任务栈(Task Stack)? +## 六、任务栈管理 -A: 任务栈(Task Stack)是AMS用来管理Activity的栈结构: +### Q16: 什么是任务栈(Task Stack)? -1. 任务(Task)定义 +**A:** 任务栈(Task Stack)是AMS用来管理Activity的栈结构: + +1. **任务(Task)定义** - 用户为了完成某项工作而交互的Activity集合 - 一个任务栈包含多个ActivityRecord -2. 任务栈特点 +2. **任务栈特点** - 后进先出(LIFO):最后启动的Activity在栈顶 - 返回键导航:按返回键会依次关闭栈顶Activity - 独立管理:不同应用的Activity可以在不同任务栈中 -3. 任务栈标识 +3. **任务栈标识** - taskId:任务栈的唯一标识 - taskAffinity:任务栈的亲和性,相同affinity的Activity在同一栈 -4. 任务栈管理 +4. **任务栈管理** - ActivityStack:管理单个任务栈 - ActivityStackSupervisor:管理所有任务栈 -Q17: Activity的启动模式如何影响任务栈? +### Q17: Activity的启动模式如何影响任务栈? -A: 启动模式对任务栈的影响: +**A:** 启动模式对任务栈的影响: -1. standard模式 +1. **standard模式** - 每次启动创建新ActivityRecord - 添加到调用方所在的任务栈 -2. singleTop模式 +2. **singleTop模式** - 如果栈顶是目标Activity,复用 - 否则创建新实例,添加到当前栈 -3. singleTask模式 +3. **singleTask模式** - 查找或创建具有相同taskAffinity的任务栈 - 如果栈中存在目标Activity,复用并清理上方Activity - 如果不存在,创建新实例 -4. singleInstance模式 +4. **singleInstance模式** - 创建独立的任务栈 - 该栈中只有这一个Activity - 其他Activity不能进入该栈 -关键代码位置: -- ActivityStarter.computeLaunchingTaskFlags() -- ActivityStack.findActivityLocked() +**关键代码位置:** +- `ActivityStarter.computeLaunchingTaskFlags()` +- `ActivityStack.findActivityLocked()` -================================================================================ -七、AMS源码分析 -================================================================================ +--- -Q18: AMS的关键类有哪些? +## 七、AMS源码分析 -A: AMS的关键类: +### Q18: AMS的关键类有哪些? -1. ActivityManagerService +**A:** AMS的关键类: + +1. **ActivityManagerService** - AMS的主类,系统服务的实现 - 管理所有Activity、Service、Receiver -2. ActivityStack +2. **ActivityStack** - 管理单个任务栈 - 处理Activity的入栈、出栈、生命周期 -3. ActivityStackSupervisor +3. **ActivityStackSupervisor** - 管理所有任务栈 - 协调多个ActivityStack -4. ActivityStarter +4. **ActivityStarter** - 处理Activity启动逻辑 - 检查权限、处理启动模式、Intent Flag -5. ActivityRecord +5. **ActivityRecord** - 表示一个Activity实例 - 存储Activity的状态、配置等信息 -6. ProcessRecord +6. **ProcessRecord** - 表示一个应用进程 - 存储进程信息、进程中的Activity/Service -7. ServiceRecord +7. **ServiceRecord** - 表示一个Service实例 - 存储Service的状态、绑定信息 -8. ReceiverList +8. **ReceiverList** - 表示BroadcastReceiver列表 - 管理动态注册的Receiver -Q19: AMS的关键方法有哪些? +### Q19: AMS的关键方法有哪些? -A: AMS的关键方法: +**A:** AMS的关键方法: -Activity相关: -- startActivity():启动Activity -- startActivityAsUser():以指定用户身份启动Activity -- finishActivity():结束Activity -- resumeTopActivityLocked():恢复栈顶Activity +**Activity相关:** +- `startActivity()`:启动Activity +- `startActivityAsUser()`:以指定用户身份启动Activity +- `finishActivity()`:结束Activity +- `resumeTopActivityLocked()`:恢复栈顶Activity -Service相关: -- startService():启动Service -- bindService():绑定Service -- stopService():停止Service -- unbindService():解绑Service +**Service相关:** +- `startService()`:启动Service +- `bindService()`:绑定Service +- `stopService()`:停止Service +- `unbindService()`:解绑Service -Broadcast相关: -- registerReceiver():注册Receiver -- unregisterReceiver():注销Receiver -- broadcastIntent():发送广播 +**Broadcast相关:** +- `registerReceiver()`:注册Receiver +- `unregisterReceiver()`:注销Receiver +- `broadcastIntent()`:发送广播 -进程管理: -- startProcessLocked():启动进程 -- killProcessLocked():杀死进程 -- updateOomAdjLocked():更新进程优先级 +**进程管理:** +- `startProcessLocked()`:启动进程 +- `killProcessLocked()`:杀死进程 +- `updateOomAdjLocked()`:更新进程优先级 -Q20: AMS如何与应用进程通信? +### Q20: AMS如何与应用进程通信? -A: AMS与应用进程的通信机制: +**A:** AMS与应用进程的通信机制: -1. Binder机制 +1. **Binder机制** - AMS作为Binder服务端,运行在system_server进程 - 应用进程通过ActivityManager.getService()获取AMS代理 - 通过Binder调用AMS的方法 -2. ApplicationThread +2. **ApplicationThread** - ApplicationThread是应用进程的Binder服务端 - AMS通过ApplicationThread向应用进程发送消息 - 应用进程通过ApplicationThread接收AMS的指令 -3. 通信流程 +3. **通信流程** + ``` 应用进程 -> Binder -> AMS(启动Activity) AMS -> ApplicationThread -> 应用进程(创建Activity) + ``` -4. 关键接口 +4. **关键接口** - IActivityManager:AMS的Binder接口 - IApplicationThread:ApplicationThread的Binder接口 -================================================================================ -八、性能优化与问题排查 -================================================================================ +--- -Q21: 如何优化Activity启动速度? +## 八、性能优化与问题排查 -A: Activity启动速度优化: +### Q21: 如何优化Activity启动速度? -1. Application优化 +**A:** Activity启动速度优化: + +1. **Application优化** - 减少Application.onCreate()中的初始化 - 延迟初始化非关键组件 - 使用App Startup统一管理初始化 -2. Activity优化 +2. **Activity优化** - 减少onCreate()中的耗时操作 - 使用异步加载数据 - 优化布局层级 -3. 进程优化 +3. **进程优化** - 避免不必要的进程创建 - 使用进程保活策略(谨慎使用) -4. 系统优化 +4. **系统优化** - 减少AMS处理时间 - 优化Binder通信 - 减少跨进程调用 -Q22: 如何排查AMS相关的问题? +### Q22: 如何排查AMS相关的问题? -A: AMS问题排查方法: +**A:** AMS问题排查方法: -1. 日志分析 +1. **日志分析** - 查看logcat中的AMS相关日志 - 关注ActivityManager、ActivityTaskManager标签 - - 使用adb logcat | grep -i "activitymanager" + - 使用`adb logcat | grep -i "activitymanager"` -2. 使用工具 +2. **使用工具** - Systrace:分析Activity启动时间线 - Perfetto:分析系统整体性能 - dumpsys activity:查看Activity栈信息 -3. 常见问题 +3. **常见问题** - ANR:检查AMS响应时间 - 启动慢:分析启动流程各阶段耗时 - 内存泄漏:检查ActivityRecord是否正确释放 -4. 调试命令 - - adb shell dumpsys activity activities:查看Activity栈 - - adb shell dumpsys activity services:查看Service信息 - - adb shell dumpsys activity broadcasts:查看广播信息 +4. **调试命令** + - `adb shell dumpsys activity activities`:查看Activity栈 + - `adb shell dumpsys activity services`:查看Service信息 + - `adb shell dumpsys activity broadcasts`:查看广播信息 -Q23: 如何分析Activity启动性能? +### Q23: 如何分析Activity启动性能? -A: Activity启动性能分析: +**A:** Activity启动性能分析: -1. 使用Systrace +1. **使用Systrace** - 抓取启动过程的trace - 分析各阶段耗时 - 重点关注AMS处理时间 -2. 使用Perfetto +2. **使用Perfetto** - 更详细的性能分析 - 可以查看Binder调用 - 分析进程创建时间 -3. 代码埋点 +3. **代码埋点** - 在关键位置添加时间戳 - 记录各阶段耗时 - 分析瓶颈 -4. 关键指标 +4. **关键指标** - 冷启动时间:从点击到首帧显示 - 热启动时间:从点击到Activity可见 - AMS处理时间:AMS处理启动请求的时间 -================================================================================ -九、高级问题 -================================================================================ +--- -Q24: AMS如何处理多窗口模式? +## 九、高级问题 -A: AMS在多窗口模式下的处理: +### Q24: AMS如何处理多窗口模式? -1. 多窗口类型 +**A:** AMS在多窗口模式下的处理: + +1. **多窗口类型** - 分屏模式(Split Screen) - 画中画模式(Picture-in-Picture) - 自由窗口模式(Freeform) -2. 任务栈管理 +2. **任务栈管理** - 每个窗口有独立的任务栈 - 不同窗口的Activity可以同时运行 - 需要协调多个ActivityStack -3. 生命周期管理 +3. **生命周期管理** - 非焦点窗口的Activity进入onPause() - 焦点窗口的Activity保持onResume() - 窗口切换时触发生命周期变化 -4. 关键类 +4. **关键类** - ActivityStack:管理单个任务栈 - DisplayContent:管理显示内容 - TaskStack:任务栈管理 -Q25: AMS如何与WMS协作? +### Q25: AMS如何与WMS协作? -A: AMS与WMS的协作: +**A:** AMS与WMS的协作: -1. 职责分工 +1. **职责分工** - AMS:管理Activity生命周期、任务栈 - WMS:管理窗口显示、布局、输入事件 -2. 协作流程 +2. **协作流程** - AMS启动Activity后,通知WMS创建窗口 - WMS创建窗口后,通知AMS窗口已就绪 - AMS管理Activity生命周期,WMS管理窗口显示 -3. 关键交互 +3. **关键交互** - Activity创建窗口:通过WindowManager.addView() - 窗口状态同步:AMS和WMS同步窗口状态 - 输入事件:WMS将输入事件分发给AMS管理的Activity -4. 通信机制 +4. **通信机制** - 通过Binder机制通信 - 通过回调机制同步状态 -================================================================================ -十、实战问题 -================================================================================ +--- -Q26: 如何实现Activity的保活? +## 十、实战问题 -A: Activity保活方法(不推荐,仅作了解): +### Q26: 如何实现Activity的保活? -1. 前台服务 +**A:** Activity保活方法(不推荐,仅作了解): + +1. **前台服务** - 启动前台Service - 显示通知 - 提高进程优先级 -2. 1像素Activity +2. **1像素Activity** - 在锁屏时启动1像素透明Activity - 提高进程优先级 - 解锁时关闭 -3. 双进程守护 +3. **双进程守护** - 两个进程互相守护 - 一个进程被杀,另一个进程重启它 -注意:这些方法会影响用户体验和系统性能,不推荐使用。 +> **注意:** 这些方法会影响用户体验和系统性能,不推荐使用。 -Q27: 如何实现Activity的预加载? +### Q27: 如何实现Activity的预加载? -A: Activity预加载方法: +**A:** Activity预加载方法: -1. 提前创建进程 +1. **提前创建进程** - 在Application中提前启动目标进程 - 预热进程,减少启动时间 -2. 预加载数据 +2. **预加载数据** - 提前加载Activity需要的数据 - 使用缓存机制 -3. 使用启动器 +3. **使用启动器** - 使用App Startup管理初始化 - 控制初始化顺序 -4. 优化布局 +4. **优化布局** - 减少布局复杂度 - 使用ViewStub延迟加载 -Q28: 如何监控AMS的性能? +### Q28: 如何监控AMS的性能? -A: AMS性能监控方法: +**A:** AMS性能监控方法: -1. 系统指标 +1. **系统指标** - 使用dumpsys activity获取性能数据 - 监控进程创建时间 - 监控Activity启动时间 -2. 日志分析 +2. **日志分析** - 分析AMS相关日志 - 统计各操作耗时 - 找出性能瓶颈 -3. 工具使用 +3. **工具使用** - Systrace:分析启动流程 - Perfetto:详细性能分析 - Android Profiler:实时监控 -4. 自定义监控 +4. **自定义监控** - 在关键位置添加埋点 - 统计各阶段耗时 - 上报性能数据 -================================================================================ -总结 -================================================================================ +--- + +## 总结 AMS是Android系统的核心服务,负责管理Activity、Service、BroadcastReceiver等组件的生命周期。 -关键知识点: +### 关键知识点: + 1. AMS的职责和架构 2. Activity启动流程(跨进程) 3. Service启动和绑定流程 @@ -719,7 +739,8 @@ AMS是Android系统的核心服务,负责管理Activity、Service、BroadcastR 6. AMS源码关键类和方法 7. 性能优化和问题排查 -面试重点: +### 面试重点: + - 深入理解Activity启动流程 - 掌握AMS与其他系统服务的协作 - 了解进程管理和内存回收机制 diff --git a/docs/android面试/系统原理/DPMS常见面试题.md b/docs/android面试/系统原理/DPMS常见面试题.md new file mode 100644 index 0000000..0167f7a --- /dev/null +++ b/docs/android面试/系统原理/DPMS常见面试题.md @@ -0,0 +1,684 @@ +# DPM常见面试题 + +## 一、DPM基础概念 + +### Q1: 什么是DPM?它的作用是什么? + +**A:** DPM(Device Policy Manager,设备策略管理器)是Android系统提供的企业设备管理框架。 + +**主要作用:** + +1. 设备策略管理:管理企业设备的安全策略、合规策略 +2. 设备控制:远程控制设备功能,如锁屏、擦除数据、禁用功能等 +3. 应用管理:管理企业应用的安装、卸载、权限控制 +4. 安全策略:强制密码策略、加密策略、网络策略等 +5. 合规检查:检查设备是否符合企业安全策略 +6. 远程管理:支持远程设备管理和监控 + +**应用场景:** + +- 企业移动设备管理(MDM - Mobile Device Management) +- 企业移动应用管理(MAM - Mobile Application Management) +- 企业移动安全(EMM - Enterprise Mobility Management) +- BYOD(Bring Your Own Device)场景 + +### Q2: DPM在Android系统架构中的位置? + +**A:** DPM在系统架构中的位置: + +1. **系统服务层** + - DevicePolicyManagerService:DPM的核心服务 + - 运行在system_server进程中 + - 通过Binder机制与应用通信 + +2. **Framework层** + - DevicePolicyManager:应用层使用的API + - DeviceAdminReceiver:设备管理员接收器 + - 通过`Context.DEVICE_POLICY_SERVICE`获取 + +3. **应用层** + - 设备管理应用:实现DeviceAdminReceiver + - 企业应用:使用DevicePolicyManager API + +**架构关系:** + +``` +应用层 -> DevicePolicyManager -> Binder -> DevicePolicyManagerService -> 系统服务 +``` + +### Q3: DPM与其他系统服务的关系? + +**A:** DPM与其他系统服务的关系: + +1. **DPM与AMS(ActivityManagerService)** + - DPM可以控制应用的启动和运行 + - 可以禁用某些应用 + - 可以限制应用的使用时间 + +2. **DPM与PMS(PackageManagerService)** + - DPM可以控制应用的安装和卸载 + - 可以管理应用权限 + - 可以限制应用安装来源 + +3. **DPM与UserManagerService** + - DPM可以管理多用户策略 + - 可以限制用户切换 + - 可以控制用户创建和删除 + +4. **DPM与Security服务** + - DPM可以设置密码策略 + - 可以强制设备加密 + - 可以管理证书 + +--- + +## 二、DeviceAdminReceiver + +### Q4: 什么是DeviceAdminReceiver?如何实现? + +**A:** DeviceAdminReceiver是设备管理员的接收器,用于接收系统发送的设备管理事件。 + +**实现步骤:** + +1. **创建DeviceAdminReceiver子类** + +```java +public class MyDeviceAdminReceiver extends DeviceAdminReceiver { + + @Override + public void onEnabled(Context context, Intent intent) { + // 设备管理员被启用 + super.onEnabled(context, intent); + } + + @Override + public void onDisabled(Context context, Intent intent) { + // 设备管理员被禁用 + super.onDisabled(context, intent); + } + + @Override + public CharSequence onDisableRequested(Context context, Intent intent) { + // 用户请求禁用设备管理员时调用 + // 返回提示信息 + return "禁用设备管理员将导致设备无法管理"; + } + + @Override + public void onPasswordChanged(Context context, Intent intent, UserHandle user) { + // 密码被修改 + super.onPasswordChanged(context, intent, user); + } + + @Override + public void onPasswordFailed(Context context, Intent intent, UserHandle user) { + // 密码输入错误 + super.onPasswordFailed(context, intent, user); + } + + @Override + public void onPasswordSucceeded(Context context, Intent intent, UserHandle user) { + // 密码输入正确 + super.onPasswordSucceeded(context, intent, user); + } +} +``` + +2. **在AndroidManifest.xml中注册** + +```xml + + + + + + +``` + +3. **创建设备管理员策略文件(res/xml/device_admin.xml)** + +```xml + + + + + + + + + + + + + + +``` + +### Q5: DeviceAdminReceiver的主要回调方法有哪些? + +**A:** DeviceAdminReceiver的主要回调方法: + +1. **生命周期回调** + - `onEnabled()`:设备管理员被启用 + - `onDisabled()`:设备管理员被禁用 + - `onDisableRequested()`:用户请求禁用时的提示 + +2. **密码相关回调** + - `onPasswordChanged()`:密码被修改 + - `onPasswordFailed()`:密码输入错误 + - `onPasswordSucceeded()`:密码输入正确 + - `onPasswordExpiring()`:密码即将过期 + +3. **安全事件回调** + - `onLockTaskModeEntering()`:进入锁定任务模式 + - `onLockTaskModeExiting()`:退出锁定任务模式 + - `onUserAdded()`:用户被添加 + - `onUserRemoved()`:用户被删除 + - `onUserStarted()`:用户启动 + - `onUserStopped()`:用户停止 + +4. **系统更新回调** + - `onSystemUpdatePending()`:系统更新待处理 + - `onBugreportShared()`:Bug报告被共享 + - `onBugreportFailed()`:Bug报告失败 + - `onBugreportSharingTimedOut()`:Bug报告超时 + +5. **网络事件回调** + - `onChoosePrivateKeyAlias()`:选择私钥别名 + - `onSecurityLogsAvailable()`:安全日志可用 + +--- + +## 三、DevicePolicyManager API + +### Q6: DevicePolicyManager的主要功能有哪些? + +**A:** DevicePolicyManager的主要功能: + +1. **密码策略管理** + - 设置密码最小长度 + - 设置密码复杂度要求 + - 设置密码过期时间 + - 强制密码策略 + +2. **设备锁定控制** + - 锁定设备 + - 设置锁屏超时时间 + - 禁用锁屏功能 + - 清除锁屏密码 + +3. **数据擦除** + - 擦除设备数据 + - 擦除应用数据 + - 恢复出厂设置 + +4. **应用管理** + - 安装应用 + - 卸载应用 + - 隐藏应用 + - 禁用应用 + +5. **功能控制** + - 禁用相机 + - 禁用截屏 + - 禁用USB调试 + - 禁用安装未知来源应用 + +6. **网络策略** + - 设置VPN配置 + - 管理WiFi配置 + - 控制网络访问 + +### Q7: 如何使用DevicePolicyManager设置密码策略? + +**A:** 设置密码策略的步骤: + +1. **获取DevicePolicyManager实例** + +```java +DevicePolicyManager dpm = (DevicePolicyManager) + getSystemService(Context.DEVICE_POLICY_SERVICE); +ComponentName admin = new ComponentName(this, MyDeviceAdminReceiver.class); +``` + +2. **检查设备管理员是否激活** + +```java +if (!dpm.isAdminActive(admin)) { + // 激活设备管理员 + Intent intent = new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN); + intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, admin); + intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION, + "需要设备管理员权限来设置密码策略"); + startActivityForResult(intent, REQUEST_CODE_ENABLE_ADMIN); + return; +} +``` + +3. **设置密码策略** + +```java +// 设置密码最小长度 +dpm.setPasswordMinimumLength(admin, 8); + +// 设置密码质量要求 +dpm.setPasswordQuality(admin, + DevicePolicyManager.PASSWORD_QUALITY_NUMERIC); // 数字密码 +// 或 +dpm.setPasswordQuality(admin, + DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC); // 字母数字密码 + +// 设置密码最小字母数 +dpm.setPasswordMinimumLetters(admin, 1); + +// 设置密码最小数字数 +dpm.setPasswordMinimumNumeric(admin, 1); + +// 设置密码最小符号数 +dpm.setPasswordMinimumSymbols(admin, 1); + +// 设置密码最小大写字母数 +dpm.setPasswordMinimumUpperCase(admin, 1); + +// 设置密码最小小写字母数 +dpm.setPasswordMinimumLowerCase(admin, 1); + +// 设置密码过期时间(毫秒) +dpm.setPasswordExpirationTimeout(admin, 30 * 24 * 60 * 60 * 1000L); // 30天 + +// 设置密码历史长度(不能重复使用最近N个密码) +dpm.setPasswordHistoryLength(admin, 5); + +// 强制设置密码 +dpm.setPasswordQuality(admin, DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC); +dpm.lockNow(); // 立即锁定设备,要求用户设置密码 +``` + +### Q8: 如何使用DevicePolicyManager控制设备功能? + +**A:** 控制设备功能的常用方法: + +1. **锁定设备** + +```java +// 立即锁定设备 +dpm.lockNow(); + +// 设置锁屏超时时间(毫秒) +dpm.setMaximumTimeToLock(admin, 5 * 60 * 1000L); // 5分钟 +``` + +2. **禁用功能** + +```java +// 禁用相机 +dpm.setCameraDisabled(admin, true); + +// 禁用截屏 +dpm.setScreenCaptureDisabled(admin, true); + +// 禁用USB调试(需要系统权限) +// 通过系统属性设置 +SystemProperties.set("persist.sys.usb.config", "none"); +``` + +3. **控制应用安装** + +```java +// 设置允许安装的应用包名列表 +dpm.setPermittedAccessibilityServices(admin, permittedPackages); + +// 设置允许使用的输入法列表 +dpm.setPermittedInputMethods(admin, permittedInputMethods); +``` + +4. **擦除数据** + +```java +// 擦除设备数据(恢复出厂设置) +dpm.wipeData(0); + +// 擦除应用数据(需要系统权限) +// 通过PackageManager删除应用数据 +``` + +5. **管理证书** + +```java +// 安装证书 +dpm.installCaCert(admin, certificateBytes); + +// 卸载证书 +dpm.uninstallCaCert(admin, certificate); +``` + +### Q9: 如何使用DevicePolicyManager管理应用? + +**A:** 应用管理功能: + +1. **安装应用** + +```java +// 静默安装应用(需要系统权限) +// 通过PackageManager安装 +PackageInstaller.Session session = packageInstaller.openSession(sessionId); +session.write("app.apk", 0, -1, inputStream); +session.commit(createIntentSender()); +``` + +2. **卸载应用** + +```java +// 通过PackageManager卸载 +packageManager.deletePackage(packageName, + new PackageDeleteObserver(), PackageManager.DELETE_ALL_USERS); +``` + +3. **隐藏应用** + +```java +// 隐藏应用(需要系统权限) +// 通过PackageManager设置应用隐藏 +packageManager.setApplicationEnabledSetting(packageName, + PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER, + PackageManager.DONT_KILL_APP); +``` + +4. **禁用应用** + +```java +// 禁用应用 +packageManager.setApplicationEnabledSetting(packageName, + PackageManager.COMPONENT_ENABLED_STATE_DISABLED, + PackageManager.DONT_KILL_APP); +``` + +--- + +## 四、设备管理员激活 + +### Q10: 如何激活设备管理员? + +**A:** 激活设备管理员的步骤: + +1. **创建激活Intent** + +```java +ComponentName admin = new ComponentName(this, MyDeviceAdminReceiver.class); +DevicePolicyManager dpm = (DevicePolicyManager) + getSystemService(Context.DEVICE_POLICY_SERVICE); + +if (!dpm.isAdminActive(admin)) { + Intent intent = new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN); + intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, admin); + intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION, + "需要激活设备管理员以管理设备安全策略"); + startActivityForResult(intent, REQUEST_CODE_ENABLE_ADMIN); +} +``` + +2. **处理激活结果** + +```java +@Override +protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + + if (requestCode == REQUEST_CODE_ENABLE_ADMIN) { + if (resultCode == RESULT_OK) { + // 设备管理员已激活 + Toast.makeText(this, "设备管理员已激活", Toast.LENGTH_SHORT).show(); + } else { + // 用户取消了激活 + Toast.makeText(this, "需要激活设备管理员", Toast.LENGTH_SHORT).show(); + } + } +} +``` + +3. **检查激活状态** + +```java +boolean isActive = dpm.isAdminActive(admin); +if (isActive) { + // 设备管理员已激活,可以使用DPM功能 +} else { + // 需要激活设备管理员 +} +``` + +### Q11: 如何取消设备管理员? + +**A:** 取消设备管理员的方法: + +1. **应用主动取消** + +```java +ComponentName admin = new ComponentName(this, MyDeviceAdminReceiver.class); +DevicePolicyManager dpm = (DevicePolicyManager) + getSystemService(Context.DEVICE_POLICY_SERVICE); + +if (dpm.isAdminActive(admin)) { + dpm.removeActiveAdmin(admin); + // 设备管理员已被取消 +} +``` + +2. **用户在设置中取消** + - 用户可以在"设置 -> 安全 -> 设备管理器"中取消设备管理员 + - 取消时会触发`DeviceAdminReceiver.onDisableRequested()` + - 可以返回提示信息,但不能阻止取消 + +3. **处理取消请求** + +```java +@Override +public CharSequence onDisableRequested(Context context, Intent intent) { + // 返回提示信息 + return "取消设备管理员将导致设备无法管理,是否确定取消?"; +} +``` + +--- + +## 五、密码策略 + +### Q12: DPM支持哪些密码策略? + +**A:** DPM支持的密码策略: + +1. **密码质量要求** + - `PASSWORD_QUALITY_UNSPECIFIED`:无要求 + - `PASSWORD_QUALITY_BIOMETRIC_WEAK`:生物识别(弱) + - `PASSWORD_QUALITY_SOMETHING`:任意密码 + - `PASSWORD_QUALITY_NUMERIC`:数字密码 + - `PASSWORD_QUALITY_NUMERIC_COMPLEX`:复杂数字密码 + - `PASSWORD_QUALITY_ALPHABETIC`:字母密码 + - `PASSWORD_QUALITY_ALPHANUMERIC`:字母数字密码 + - `PASSWORD_QUALITY_COMPLEX`:复杂密码(包含字母、数字、符号) + +2. **密码长度要求** + - `setPasswordMinimumLength()`:最小长度 + - 默认最小长度为4 + +3. **密码复杂度要求** + - `setPasswordMinimumLetters()`:最小字母数 + - `setPasswordMinimumNumeric()`:最小数字数 + - `setPasswordMinimumSymbols()`:最小符号数 + - `setPasswordMinimumUpperCase()`:最小大写字母数 + - `setPasswordMinimumLowerCase()`:最小小写字母数 + - `setPasswordMinimumNonLetter()`:最小非字母字符数 + +4. **密码历史** + - `setPasswordHistoryLength()`:密码历史长度 + - 防止用户重复使用最近N个密码 + +5. **密码过期** + - `setPasswordExpirationTimeout()`:密码过期时间 + - 密码过期后强制用户修改密码 + +### Q13: 如何实现密码策略的强制执行? + +**A:** 强制执行密码策略的方法: + +1. **设置密码质量要求** + +```java +// 设置密码质量要求 +dpm.setPasswordQuality(admin, + DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC); + +// 设置密码最小长度 +dpm.setPasswordMinimumLength(admin, 8); + +// 设置密码复杂度 +dpm.setPasswordMinimumLetters(admin, 1); +dpm.setPasswordMinimumNumeric(admin, 1); +dpm.setPasswordMinimumSymbols(admin, 1); +``` + +2. **强制锁定设备** + +```java +// 立即锁定设备,要求用户设置符合策略的密码 +dpm.lockNow(); +``` + +3. **检查密码是否符合策略** + +```java +// 检查当前密码是否符合策略 +boolean isPasswordSufficient = dpm.isActivePasswordSufficient(); + +if (!isPasswordSufficient) { + // 密码不符合策略,强制用户修改 + dpm.lockNow(); +} +``` + +4. **监听密码变化** + +```java +// 在DeviceAdminReceiver中监听密码变化 +@Override +public void onPasswordChanged(Context context, Intent intent, UserHandle user) { + // 密码被修改,检查是否符合策略 + DevicePolicyManager dpm = (DevicePolicyManager) + context.getSystemService(Context.DEVICE_POLICY_SERVICE); + + if (!dpm.isActivePasswordSufficient()) { + // 密码不符合策略,可以采取进一步措施 + } +} +``` + +--- + +## 六、设备锁定和擦除 + +### Q14: 如何使用DPM锁定设备? + +**A:** 锁定设备的方法: + +1. **立即锁定** + +```java +// 立即锁定设备 +dpm.lockNow(); +``` + +2. **设置锁屏超时** + +```java +// 设置锁屏超时时间(毫秒) +dpm.setMaximumTimeToLock(admin, 5 * 60 * 1000L); // 5分钟 +``` + +3. **清除锁屏密码** + +```java +// 清除锁屏密码(需要系统权限) +dpm.resetPassword("", DevicePolicyManager.RESET_PASSWORD_REQUIRE_ENTRY); +``` + +4. **设置锁屏消息** + +```java +// 设置锁屏时显示的消息 +dpm.setLockTaskPackages(admin, new String[]{"com.example.app"}); +``` + +### Q15: 如何使用DPM擦除设备数据? + +**A:** 擦除设备数据的方法: + +1. **擦除所有数据(恢复出厂设置)** + +```java +// 擦除设备所有数据 +dpm.wipeData(0); + +// 擦除设备数据并保留外部存储 +dpm.wipeData(DevicePolicyManager.WIPE_EXTERNAL_STORAGE); +``` + +2. **擦除应用数据(需要系统权限)** + +```java +// 通过PackageManager删除应用数据 +packageManager.deleteApplicationDataFiles(packageName, + new IPackageDataObserver.Stub() { + @Override + public void onRemoveCompleted(String packageName, boolean succeeded) { + // 删除完成 + } + }); +``` + +3. **擦除前的准备** + +```java +// 在擦除前可以保存重要数据 +// 发送通知给用户 +// 记录擦除操作日志 +``` + +**注意:** + +- `wipeData()`会立即擦除设备,无法撤销 +- 需要谨慎使用,建议在擦除前进行确认 +- 某些设备可能不支持擦除功能 + +--- + +## 七、应用管理 + +### Q16: DPM如何管理企业应用? + +**A:** DPM管理企业应用的方法: + +1. **应用安装管理** + +```java +// 设置允许安装的应用包名列表 +List permittedPackages = new ArrayList<>(); +permittedPackages.add("com.example.app1"); +permittedPackages.add("com.example.app2"); + +dpm.setPermittedAccessibilityServices(admin, permittedPackages); +``` + +2. **应用隐藏和显示** + +```java +// 隐藏应用(需要系统权限) +packageManager.setApplicationEnabledSetting(packageName, + PackageManager.COMPONENT_ENABLED_STATE_HIDDEN, + PackageManager.DONT_KILL_APP); + +// 显示应用 +packageManager.setApplicationEnabledSet \ No newline at end of file diff --git a/docs/技术面试问题回答.md b/docs/技术面试问题回答.md index addbe38..49a7aca 100644 --- a/docs/技术面试问题回答.md +++ b/docs/技术面试问题回答.md @@ -356,1449 +356,3 @@ --- - - - -## 基础概念类 - - - -### Q1: 什么是WMS?它的主要职责是什么? - - - -**答案:** - - - -WMS(Window Manager Service)是Android窗口系统的核心服务,运行在system_server进程中。 - - - -**主要职责:** - - - -1. **窗口管理**:管理所有窗口的创建、显示、销毁等生命周期 - -2. **窗口层级管理**:维护窗口的Z-Order顺序,决定窗口的显示优先级 - -3. **布局计算**:计算窗口的位置、大小和可见区域 - -4. **输入事件分发**:将触摸、按键等输入事件分发给正确的窗口 - -5. **窗口动画**:管理窗口的显示、隐藏、切换等动画效果 - -6. **屏幕旋转**:处理屏幕方向变化时的窗口布局调整 - -7. **多显示支持**:支持多个显示设备的窗口管理 - - - -```java - -// WMS是系统服务,在SystemServer中启动 - -public class SystemServer { - -    private void startOtherServices(...) { - -        WindowManagerService wm = WindowManagerService.main(...); - -        ServiceManager.addService(Context.WINDOW_SERVICE, wm); - -    } - -} - -``` - - - -### Q2: WMS与WindowManager、WindowManagerGlobal的关系是什么? - - - -**答案:** - - - -这三者的关系如下: - - - -1. **WindowManager**:应用层接口,开发者使用的API - -2. **WindowManagerGlobal**:应用层实现,管理ViewRootImpl和窗口会话 - -3. **WindowManagerService**:系统服务,实际管理窗口的服务端 - - - -**调用流程:** - - - -``` - -应用层:WindowManager.addView() - -    ↓ - -WindowManagerGlobal.addView() - -    ↓ - -ViewRootImpl.setView() - -    ↓ - -IWindowSession.addToDisplay() (Binder调用) - -    ↓ - -WMS.addWindow() (服务端) - -``` - - - -```java - -// WindowManager接口 - -public interface WindowManager extends ViewManager { - -    void addView(View view, ViewGroup.LayoutParams params); - -    void removeView(View view); - -    void updateViewLayout(View view, ViewGroup.LayoutParams params); - -} - - - -// WindowManagerGlobal实现 - -public final class WindowManagerGlobal { - -    public void addView(View view, ViewGroup.LayoutParams params, ...) { - -        ViewRootImpl root = new ViewRootImpl(view.getContext(), display); - -        root.setView(view, wparams, panelParentView); - -    } - -} - - - -// WMS服务端 - -public class WindowManagerService { - -    public int addWindow(Session session, IWindow client, ...) { - -        // 实际窗口管理逻辑 - -    } - -} - -``` - - - -### Q3: 窗口类型有哪些?它们的层级关系是什么? - - - -**答案:** - - - -**窗口类型:** - - - -1. **应用窗口(APPLICATION)** - -   - `TYPE_APPLICATION`:普通Activity窗口 - -   - `TYPE_APPLICATION_STARTING`:启动窗口 - -   - `TYPE_BASE_APPLICATION`:应用基础窗口 - - - -2. **子窗口(SUB_WINDOW)** - -   - `TYPE_APPLICATION_PANEL`:应用面板 - -   - `TYPE_APPLICATION_SUB_PANEL`:应用子面板 - -   - `TYPE_APPLICATION_ATTACHED_DIALOG`:附加对话框 - - - -3. **系统窗口(SYSTEM_WINDOW)** - -   - `TYPE_STATUS_BAR`:状态栏 - -   - `TYPE_NAVIGATION_BAR`:导航栏 - -   - `TYPE_SYSTEM_ALERT`:系统警告窗口 - -   - `TYPE_TOAST`:Toast窗口 - -   - `TYPE_APPLICATION_OVERLAY`:悬浮窗(需要权限) - - - -**层级关系(Z-Order):** - - - -``` - -系统窗口(最高) - -    ↓ - -应用窗口(中等) - -    ↓ - -子窗口(最低) - -``` - - - -```java - -// 窗口类型定义 - -public static class LayoutParams { - -    // 应用窗口:1000-1999 - -    public static final int TYPE_APPLICATION = 2; - -    public static final int TYPE_APPLICATION_STARTING = 3; - -    // 子窗口:1000-1999 - -    public static final int TYPE_APPLICATION_PANEL = 1000; - -    // 系统窗口:2000-2999 - -    public static final int TYPE_STATUS_BAR = 2000; - -    public static final int TYPE_SYSTEM_ALERT = 2003; - -    public static final int TYPE_TOAST = 2005; - -    public static final int TYPE_APPLICATION_OVERLAY = 2038; - -} - -``` - - - ---- - - - -## 架构原理类 - - - -### Q4: WMS的架构是怎样的?包含哪些核心组件? - - - -**答案:** - - - -**WMS架构分层:** - - - -``` - -┌─────────────────────────────────┐ - -│  应用层(客户端)                  │ - -│  Activity/WindowManager          │ - -└──────────────┬──────────────────┘ - -               │ Binder IPC - -┌──────────────▼──────────────────┐ - -│  系统服务层(服务端)              │ - -│  WindowManagerService            │ - -│  ├── WindowState                 │ - -│  ├── DisplayContent              │ - -│  ├── WindowToken                 │ - -│  └── WindowAnimator              │ - -└──────────────┬──────────────────┘ - -               │ - -┌──────────────▼──────────────────┐ - -│  显示层                          │ - -│  SurfaceFlinger                 │ - -└─────────────────────────────────┘ - -``` - - - -**核心组件:** - - - -1. **WindowManagerService**:WMS主类,管理所有窗口 - -2. **WindowState**:窗口状态,表示一个窗口的所有信息 - -3. **DisplayContent**:显示内容,管理一个显示设备上的所有窗口 - -4. **WindowToken**:窗口令牌,用于窗口分组和权限控制 - -5. **WindowAnimator**:窗口动画控制器 - -6. **WindowStateAnimator**:单个窗口的动画状态 - - - -```java - -// WindowState:窗口状态 - -class WindowState { - -    final WindowManagerService mService; - -    final WindowToken mToken; - -    final WindowManager.LayoutParams mAttrs; - -    final DisplayContent mDisplayContent; - -    SurfaceControl mSurfaceControl; - -    // 窗口属性 - -    int mLayer;  // 层级 - -    Rect mFrame; // 位置和大小 - -    boolean mVisible; // 是否可见 - -} - -``` - - - -### Q5: 窗口添加的完整流程是什么? - - - -**答案:** - - - -**窗口添加流程:** - - - -``` - -1. Activity.attach() - -   └──> 创建PhoneWindow - -2. Activity.onCreate() - -   └──> setContentView() - -       └──> PhoneWindow.setContentView() - -           └──> 创建DecorView - -3. Activity.onResume() - -   └──> Activity.makeVisible() - -       └──> WindowManager.addView() - -           └──> WindowManagerGlobal.addView() - -               └──> 创建ViewRootImpl - -                   └──> ViewRootImpl.setView() - -                       └──> IWindowSession.addToDisplay() - -                           └──> WMS.addWindow() - -                               ├──> 创建WindowState - -                               ├──> 创建Surface - -                               └──> 更新布局 - -``` - - - -**关键代码:** - - - -```java - -// 1. Activity创建窗口 - -public final void attach(...) { - -    mWindow = new PhoneWindow(this, window, activityConfigCallback); - -    mWindow.setWindowManager( - -        (WindowManager)context.getSystemService(Context.WINDOW_SERVICE), - -        mToken, mComponent.flattenToString(), - -        (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0); - -} - - - -// 2. WMS添加窗口 - -public int addWindow(Session session, IWindow client, ...) { - -    // 权限检查 - -    if (!checkCallingPermission(...)) { - -        return WindowManagerGlobal.ADD_PERMISSION_DENIED; - -    } - -    // 创建WindowState - -    WindowState win = new WindowState(this, session, client, ...); - -    // 添加到DisplayContent - -    DisplayContent displayContent = getDisplayContent(displayId); - -    displayContent.addWindow(win); - -    // 创建Surface - -    win.createSurfaceControl(); - -    // 更新布局 - -    performLayoutAndPlaceSurfacesLocked(); - -    return WindowManagerGlobal.ADD_OKAY; - -} - -``` - - - -### Q6: WMS如何管理窗口的Z-Order(层级)? - - - -**答案:** - - - -**Z-Order管理机制:** - - - -1. **基础层级**:由窗口类型决定(TYPE值) - -2. **层级调整**:通过`WindowState.mLayer`动态计算 - -3. **层级排序**:DisplayContent维护窗口列表,按层级排序 - - - -**层级计算:** - - - -```java - -// WMS计算窗口层级 - -void assignWindowLayers(DisplayContent displayContent) { - -    int baseLayer = 0; - -    // 1. 系统窗口:最高层级 - -    for (WindowState win : systemWindows) { - -        win.mLayer = baseLayer + win.mAttrs.type; - -    } - -    // 2. 应用窗口:中等层级 - -    for (WindowState win : applicationWindows) { - -        win.mLayer = baseLayer + win.mAttrs.type; - -    } - -    // 3. 子窗口:最低层级(相对于父窗口) - -    for (WindowState win : childWindows) { - -        win.mLayer = win.mParentWindow.mLayer + win.mAttrs.type; - -    } - -    // 4. 按层级排序 - -    displayContent.sortWindowsByLayer(); - -} - -``` - - - -**影响层级的因素:** - - - -- 窗口类型(TYPE) - -- 窗口标志(FLAG) - -- 窗口动画状态 - -- 窗口可见性 - - - ---- - - - -## 窗口管理类 - - - -### Q7: WindowState的作用是什么?它包含哪些关键信息? - - - -**答案:** - - - -**WindowState的作用:** - - - -WindowState是WMS中表示一个窗口状态的核心类,包含了窗口的所有信息。 - - - -**关键信息:** - - - -1. **窗口属性**:LayoutParams、类型、标志等 - -2. **窗口状态**:可见性、焦点状态、动画状态等 - -3. **窗口位置**:Frame、可见区域、裁剪区域等 - -4. **Surface信息**:SurfaceControl、Surface等 - -5. **窗口关系**:父窗口、子窗口、Token等 - - - -```java - -class WindowState { - -    // 窗口属性 - -    final WindowManager.LayoutParams mAttrs; - -    final WindowToken mToken; - -    final DisplayContent mDisplayContent; - -    // 窗口状态 - -    boolean mVisible; - -    boolean mHasSurface; - -    boolean mIsAnimating; - -    // 窗口位置 - -    Rect mFrame;           // 窗口位置和大小 - -    Rect mVisibleFrame;     // 可见区域 - -    Rect mContentFrame;    // 内容区域 - -    // Surface - -    SurfaceControl mSurfaceControl; - -    Surface mSurface; - -    // 窗口关系 - -    WindowState mParentWindow; - -    ArrayList mChildWindows; - -    // 层级 - -    int mLayer; - -} - -``` - - - -### Q8: DisplayContent的作用是什么?它如何管理窗口? - - - -**答案:** - - - -**DisplayContent的作用:** - - - -DisplayContent表示一个显示设备上的所有窗口内容,管理该显示设备上的窗口栈、布局和显示。 - - - -**主要功能:** - - - -1. **窗口管理**:维护该显示设备上的所有窗口 - -2. **窗口栈管理**:维护窗口的Z-Order顺序 - -3. **布局计算**:计算窗口的位置和大小 - -4. **显示配置**:管理显示设备的分辨率、方向等 - - - -```java - -class DisplayContent { - -    final int mDisplayId; - -    final Display mDisplay; - -    // 窗口列表 - -    final WindowList mWindows = new WindowList(); - -    // 窗口栈 - -    final ArrayList mStacks = new ArrayList<>(); - -    // 显示配置 - -    Configuration mDisplayConfiguration; - -    // 添加窗口 - -    void addWindow(WindowState win) { - -        mWindows.add(win); - -        assignWindowLayers(); - -    } - -    // 布局计算 - -    void performLayout() { - -        for (WindowState win : mWindows) { - -            computeWindowFrame(win); - -        } - -    } - -} - -``` - - - -### Q9: WindowToken的作用是什么?为什么需要WindowToken? - - - -**答案:** - - - -**WindowToken的作用:** - - - -WindowToken是窗口的令牌,用于: - -1. **窗口分组**:将属于同一应用的窗口分组 - -2. **权限控制**:控制哪些窗口可以添加到Token - -3. **窗口关联**:关联Activity、Service等组件 - - - -**为什么需要WindowToken:** - - - -1. **安全性**:防止其他应用随意添加窗口到你的应用 - -2. **窗口管理**:统一管理同一组件的所有窗口 - -3. **生命周期**:Token销毁时,所有关联窗口都会被移除 - - - -```java - -class WindowToken { - -    final IBinder token;  // Token标识 - -    final int windowType; // 窗口类型 - -    final String name;    // Token名称 - -    // 关联的窗口列表 - -    final ArrayList windows = new ArrayList<>(); - -    // 添加窗口 - -    void addWindow(WindowState win) { - -        windows.add(win); - -    } - -    // 移除窗口 - -    void removeWindow(WindowState win) { - -        windows.remove(win); - -        if (windows.isEmpty()) { - -            // Token可以销毁 - -        } - -    } - -} - -``` - - - ---- - - - -## 源码分析类 - - - -### Q10: WMS的addWindow方法做了哪些事情? - - - -**答案:** - - - -**addWindow方法流程:** - - - -```java - -public int addWindow(Session session, IWindow client, ...) { - -    // 1. 权限检查 - -    if (!checkCallingPermission(...)) { - -        return WindowManagerGlobal.ADD_PERMISSION_DENIED; - -    } - -    // 2. 参数验证 - -    if (attrs.type < FIRST_APPLICATION_WINDOW || - -        attrs.type > LAST_APPLICATION_WINDOW) { - -        // 系统窗口需要特殊权限 - -    } - -    // 3. 获取或创建WindowToken - -    WindowToken token = getWindowToken(attrs.token); - -    if (token == null) { - -        // 创建新Token - -        token = new WindowToken(...); - -    } - -    // 4. 创建WindowState - -    WindowState win = new WindowState(this, session, client, token, ...); - -    // 5. 添加到DisplayContent - -    DisplayContent displayContent = getDisplayContent(displayId); - -    displayContent.addWindow(win); - -    // 6. 创建Surface - -    win.createSurfaceControl(); - -    // 7. 更新布局 - -    performLayoutAndPlaceSurfacesLocked(); - -    return WindowManagerGlobal.ADD_OKAY; - -} - -``` - - - -**关键步骤:** - - - -1. **权限检查**:检查是否有权限添加该类型窗口 - -2. **Token管理**:获取或创建WindowToken - -3. **创建WindowState**:创建窗口状态对象 - -4. **添加到DisplayContent**:将窗口添加到对应的显示设备 - -5. **创建Surface**:创建窗口的Surface用于绘制 - -6. **更新布局**:重新计算所有窗口的布局 - - - -### Q11: performLayoutAndPlaceSurfacesLocked方法的作用是什么? - - - -**答案:** - - - -**方法作用:** - - - -`performLayoutAndPlaceSurfacesLocked`是WMS的核心布局方法,负责: - -1. 计算所有窗口的位置和大小 - -2. 分配窗口的层级 - -3. 更新Surface的位置和大小 - -4. 处理窗口动画 - - - -**执行流程:** - - - -```java - -void performLayoutAndPlaceSurfacesLocked() { - -    // 1. 遍历所有显示设备 - -    for (DisplayContent displayContent : mDisplayContents) { - -        // 2. 计算显示配置 - -        displayContent.computeScreenConfiguration(); - -        // 3. 应用窗口策略 - -        applyWindowPolicy(displayContent); - -        // 4. 计算窗口位置和大小 - -        for (WindowState win : displayContent.mWindows) { - -            computeWindowFrame(win); - -        } - -        // 5. 分配窗口层级 - -        assignWindowLayers(displayContent); - -        // 6. 更新Surface - -        for (WindowState win : displayContent.mWindows) { - -            if (win.mHasSurface) { - -                updateSurface(win); - -            } - -        } - -        // 7. 处理窗口动画 - -        displayContent.mAnimator.updateWindowsLocked(); - -    } - -} - -``` - - - -### Q12: WMS如何与SurfaceFlinger交互? - - - -**答案:** - - - -**交互流程:** - - - -``` - -WMS - -  ├──> 创建SurfaceControl - -  ├──> 设置Surface属性(位置、大小、层级) - -  └──> 通过SurfaceControl与SurfaceFlinger通信 - -       └──> SurfaceFlinger合成Surface并显示 - -``` - - - -**关键代码:** - - - -```java - -// WMS创建Surface - -class WindowState { - -    void createSurfaceControl() { - -        mSurfaceControl = new SurfaceControl.Builder() - -            .setName(mWindowTag) - -            .setBufferSize(mFrame.width(), mFrame.height()) - -            .setFormat(PixelFormat.TRANSLUCENT) - -            .build(); - -        mSurface = new Surface(mSurfaceControl); - -    } - -    void updateSurface() { - -        // 设置Surface位置和大小 - -        mSurfaceControl.setPosition(mFrame.left, mFrame.top); - -        mSurfaceControl.setSize(mFrame.width(), mFrame.height()); - -        // 设置Surface层级 - -        SurfaceControl.Transaction t = new SurfaceControl.Transaction(); - -        t.setLayer(mSurfaceControl, mLayer); - -        t.apply(); - -    } - -} - -``` - - - ---- - - - -## 性能优化类 - - - -### Q13: 如何优化窗口的创建和显示性能? - - - -**答案:** - - - -**优化策略:** - - - -1. **减少窗口数量**:避免创建过多窗口 - -2. **延迟创建**:非关键窗口延迟创建 - -3. **复用窗口**:复用已有的窗口 - -4. **优化布局**:减少布局层级和复杂度 - -5. **使用硬件加速**:启用硬件加速提升绘制性能 - - - -```java - -// 1. 延迟创建窗口 - -Handler.postDelayed(() -> { - -    createWindow(); - -}, 100); - - - -// 2. 复用窗口 - -if (mWindow == null) { - -    mWindow = createWindow(); - -} else { - -    updateWindow(mWindow); - -} - - - -// 3. 启用硬件加速 - - - -``` - - - -### Q14: 窗口动画对性能有什么影响?如何优化? - - - -**答案:** - - - -**影响:** - - - -1. **CPU占用**:动画计算消耗CPU - -2. **GPU占用**:动画渲染消耗GPU - -3. **帧率下降**:复杂动画可能导致掉帧 - - - -**优化方法:** - - - -1. **简化动画**:使用简单的动画效果 - -2. **使用硬件加速**:利用GPU加速动画 - -3. **减少动画时长**:缩短动画时间 - -4. **避免同时多个动画**:减少并发动画数量 - - - -```java - -// 使用硬件加速动画 - -ObjectAnimator animator = ObjectAnimator.ofFloat(view, "alpha", 0f, 1f); - -animator.setDuration(300); - -animator.setInterpolator(new AccelerateDecelerateInterpolator()); - -animator.start(); - -``` - - - ---- - - - -## 问题排查类 - - - -### Q15: 如何排查窗口显示异常的问题? - - - -**答案:** - - - -**排查步骤:** - - - -1. **检查窗口状态**:使用`adb shell dumpsys window` - -2. **检查Surface状态**:查看Surface是否创建成功 - -3. **检查布局**:查看窗口的Frame是否正确 - -4. **检查层级**:查看窗口的Layer是否正确 - -5. **使用Systrace**:分析窗口创建和布局流程 - - - -```bash - -# 1. 查看窗口信息 - -adb shell dumpsys window windows - - - -# 2. 查看窗口层级 - -adb shell dumpsys window displays - - - -# 3. 使用Systrace分析 - -python systrace.py -t 10 -o trace.html wm - -``` - - - -### Q16: 窗口泄漏如何排查和解决? - - - -**答案:** - - - -**排查方法:** - - - -1. **检查WindowManager引用**:确保及时移除窗口 - -2. **检查生命周期**:确保在onDestroy中移除窗口 - -3. **使用LeakCanary**:检测窗口泄漏 - -4. **检查WindowToken**:确保Token正确管理 - - - -```java - -// 正确的窗口管理 - -class MyActivity extends Activity { - -    private View floatingView; - -    @Override - -    protected void onCreate(Bundle savedInstanceState) { - -        super.onCreate(savedInstanceState); - -        // 创建悬浮窗 - -        createFloatingWindow(); - -    } - -    @Override - -    protected void onDestroy() { - -        super.onDestroy(); - -        // 必须移除窗口 - -        if (floatingView != null) { - -            WindowManager wm = getWindowManager(); - -            wm.removeView(floatingView); - -            floatingView = null; - -        } - -    } - -} - -``` - - - ---- - - - -## 多窗口相关 - - - -### Q17: 分屏模式是如何实现的? - - - -**答案:** - - - -**分屏实现原理:** - - - -1. **任务栈管理**:每个分屏窗口对应一个TaskStack - -2. **窗口布局**:WMS计算每个窗口的位置和大小 - -3. **输入事件分发**:根据触摸位置分发到对应窗口 - -4. **焦点管理**:管理两个窗口的焦点切换 - - - -```java - -// 分屏窗口布局 - -void layoutSplitScreenWindows(DisplayContent displayContent) { - -    // 计算分屏窗口大小 - -    Rect primaryFrame = new Rect(0, 0, screenWidth / 2, screenHeight); - -    Rect secondaryFrame = new Rect(screenWidth / 2, 0, screenWidth, screenHeight); - -    // 设置主窗口位置 - -    primaryWindow.mFrame = primaryFrame; - -    // 设置次窗口位置 - -    secondaryWindow.mFrame = secondaryFrame; - -} - -``` - - - -### Q18: 悬浮窗(Overlay Window)如何实现? - - - -**答案:** - - - -**实现步骤:** - - - -1. **申请权限**:`SYSTEM_ALERT_WINDOW`权限 - -2. **设置窗口类型**:`TYPE_APPLICATION_OVERLAY` - -3. **创建窗口**:使用WindowManager添加窗口 - -4. **管理生命周期**:及时移除窗口 - - - -```java - -// 创建悬浮窗 - -private void createOverlayWindow() { - -    // 1. 检查权限 - -    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - -        if (!Settings.canDrawOverlays(this)) { - -            // 请求权限 - -            requestOverlayPermission(); - -            return; - -        } - -    } - -    // 2. 创建窗口参数 - -    WindowManager.LayoutParams params = new WindowManager.LayoutParams( - -        WindowManager.LayoutParams.WRAP_CONTENT, - -        WindowManager.LayoutParams.WRAP_CONTENT, - -        WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY, - -        WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, - -        PixelFormat.TRANSLUCENT - -    ); - -    // 3. 创建视图 - -    View overlayView = LayoutInflater.from(this) - -        .inflate(R.layout.overlay_window, null); - -    // 4. 添加窗口 - -    WindowManager wm = getSystemService(Context.WINDOW_SERVICE); - -    wm.addView(overlayView, params); - -} - -``` - - - ---- - - - -## 总结 - - - -WMS窗口面试题主要涵盖: - - - -1. **基础概念**:WMS作用、窗口类型、层级关系 - -2. **架构原理**:WMS架构、窗口添加流程、Z-Order管理 - -3. **窗口管理**:WindowState、D \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml index 319d57f..c3f23b0 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -209,6 +209,7 @@ nav: - git/git设置用户名和邮箱.md - android面试: - android面试/技术面试问题回答.md + - android面试/系统原理/AMS面试.md - android面试/系统原理/WMS面试.md - android面试/README.md - android面试/基础知识/Android基础.md @@ -289,7 +290,7 @@ nav: - android面试/项目经验/技术选型.md - android面试/项目经验/问题排查经验.md - android面试/项目经验/项目架构设计.md - - android面试/系统原理/AMS面试.md + - android面试/系统原理/DPMS常见面试题.md - Google开发文档体系: - Google开发文档体系/API参考/Android_API概览.md - Google开发文档体系/API参考/Jetpack_API.md