车载 RemoteCarTaskView详解

概述

RemoteCarTaskView 是 Car SDK 类(android.car.app 包),是一个 跨进程 SurfaceView。它在 CarLauncher 进程中作为普通 View 嵌入,但编排在 SystemUI 进程,而渲染在实际Activity所属的进程(如map应用)

流程图

SurfaceFlingerShellTaskOrganizer (SystemWM)TaskViewTaskController (SystemUI/SWM)TaskViewTransitions (SystemUI/SWM)RemoteCarTaskViewServerImpl (SystemUI)SystemUI (CarSystemUIProxyImpl)CarSystemUIProxyAidlWrapper (CarLib)ControlledRemoteCarTaskView (App)CarTaskViewController (CarLib)App (CarLauncher)SurfaceFlingerShellTaskOrganizer (SystemWM)TaskViewTaskController (SystemUI/SWM)TaskViewTransitions (SystemUI/SWM)RemoteCarTaskViewServerImpl (SystemUI)SystemUI (CarSystemUIProxyImpl)CarSystemUIProxyAidlWrapper (CarLib)ControlledRemoteCarTaskView (App)CarTaskViewController (CarLib)App (CarLauncher)第一步:创建客户端与 Binder 通道存储 ICarTaskViewHost第二步:SurfaceFlinger 分配 Surface第三步:跨进程通知 SystemUI第四步:TaskViewTaskController 处理 surfaceCreatedalt[surfaceControl != null]alt[mTaskToken == null (Task 尚未出现)][isUsingShellTransitions == true][(传统路径)]第五步:startActivity 流程 — 客户端发起启动请求第六步:SystemUI 端处理 startActivity第七步:TaskViewTransitions 启动 ActivityActivity 启动后由 AMS 创建 TaskShellTaskOrganizer 检测到 Task 出现触发 onTaskAppeared 回调第八步:Task 出现回调链第九步:将 Task 内容合成到 TaskView Surfacealt[isUsingShellTransitions == true][(传统路径)]完成!Activity 内容合成到 App 布局中createControlledRemoteCarTaskView(config)new ControlledRemoteCarTaskView()创建 mICarTaskViewClient (ICarTaskViewClient.Stub)mService.createCarTaskView(mICarTaskViewClient)new CarTaskViewClient(client)linkToDeath(clientDeathRecipient)createCarTaskView(carTaskViewClient) (AIDL)new RemoteCarTaskViewServerImpl(...)mRemoteCarTaskViewServerSet.add(server)return carTaskViewHostreturn ICarTaskViewHostsetRemoteHost(host)完成布局,添加 RemoteCarTaskView 到窗口分配 Surface 缓冲区完成surfaceCreated(holder) ← 回调触发点if (mICarTaskViewHost != null && !mInitialized)onInitialized() → startActivity()mSurfaceCreated = truemICarTaskViewHost.notifySurfaceCreated(SurfaceControlHelper.copy(getSurfaceControl())) (AIDL)notifySurfaceCreated(control)mTaskViewTaskController.surfaceCreated(control)mSurfaceCreated = truemIsInitialized = truemSurfaceControl = surfaceControlsetTrustedOverlay(surfaceControl, DISABLED)- 安全措施:即使 TaskView 在受信任窗口中- 内部应用也不能拥有 TrustedOverlay 权限notifyInitialized()→ 回调外部监听器 onInitialized()mShellExecutor.execute { ... }切换到 Shell 线程异步处理return 等待 onTaskAppeared 后续处理mTaskViewController.setTaskViewVisible(this, true)委托转场动画统一管理可见性mTransaction.reparent(mTaskLeash, mSurfaceControl)- 将 Task 内容 reparent 到 TaskView Surface- show(mTaskLeash) 显示 Task 内容mTransaction.apply() 提交事务updateTaskVisibility()→ 同步可见性到 WindowContainerTransaction→ 通知监听器 onTaskVisibilityChanged(taskId, visible)onInitialized() 回调触发mContext.getMainExecutor().execute { startActivity() }startActivity() → startActivityInternal()检查前置条件:- isUserUnlocked() 用户是否解锁- display != null 显示器是否可用- display.getState() == STATE_ON 显示器是否亮屏构建 ActivityOptions:- makeCustomAnimation(enterResId=0, exitResId=0) 无动画- setPendingIntentBackgroundActivityStartMode(ALLOWED) BAL 豁免获取 launchBounds:ViewHelper.getBoundsOnScreen(this, launchBounds)构建 PendingIntent:PendingIntent.getActivity(mContext, 0,mConfig.mActivityIntent,FLAG_IMMUTABLE | FLAG_UPDATE_CURRENT)处理 fillInIntent:if (FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS)→ fillInIntent = new Intent().addFlags(EXCLUDE_FROM_RECENTS)mICarTaskViewHost.startActivity(pendingIntent, fillInIntent,options.toBundle(), launchBounds) (AIDL oneway)CarTaskViewHost.startActivity()ensureManageSystemUIPermission(mContext) 权限校验ActivityOptions.fromBundle(options)opt.setPendingIntentBackgroundActivityStartMode(MODE_BACKGROUND_ACTIVITY_START_ALLOW_ALWAYS)BAL 硬化豁免:允许 PendingIntent 在后台启动 ActivitymTaskViewTransitions.startActivity(mTaskViewTaskController,pendingIntent, fillInIntent,opt, launchBounds)startActivity(taskViewTaskController,pendingIntent, fillInIntent, options, launchBounds)设置 launchBounds 到 ActivityOptionsoptions.setLaunchBounds(launchBounds)pendingIntent.send(mContext, 0,fillInIntent, null, null, null, options.toBundle())通过 PendingIntent 启动目标 ActivityonTaskAppeared(taskInfo, leash)onTaskAppeared(taskInfo, leash)applyAllInsets() 应用所有 InsetsmCarTaskViewClient.onTaskAppeared(taskInfo, leash) (AIDL)mICarTaskViewClient.onTaskAppeared()mTaskInfo = taskInfoupdateWindowBounds()stopTheStartActivityBackoffIfExists()Task 已出现,停止重试退避mCallback.onTaskAppeared(taskInfo)通知应用层回调处理 onTaskAppeared 后续:mTaskToken = taskInfo.tokenmTaskLeash = leashsetTaskViewVisible(mTaskViewTaskController, true)通过 Shell Transitions 管理 reparentmTransaction.reparent(mTaskLeash, mSurfaceControl)将 Task Surface reparent 到 TaskView SurfacemTransaction.show(mTaskLeash)mTransaction.apply()updateTaskVisibility()

怎么做到的
startActivity只是将intent传递到systemui,真正执行start操作的是在systemui,systemui将task的surfaceleash reparent到创建RemoteCarTaskView的进程传递过来的SurfaceControl(由RemoteCarTaskView【继承自SurfaceView】 创建)

手势事件

SystemUI地图 ActivityControlledRemoteCarTaskView (App)CarLauncher主窗口mSpyWindow(App - CarTaskViewInputInterceptor)InputDispatcher(系统)用户手指SystemUI地图 ActivityControlledRemoteCarTaskView (App)CarLauncher主窗口mSpyWindow(App - CarTaskViewInputInterceptor)InputDispatcher(系统)用户手指alt[shouldCaptureGestures == false][shouldCaptureGestures == true]alt[是需要拦截的手势 (下滑)][不是需要拦截的手势 (点击)]alt[点在 TaskView 内 + shouldCaptureGestures][点不在 TaskView 内]触摸屏幕 (DOWN + MOVE)dispatchTouchEvent(event)判断点是否在 TaskView 内?检测是否是手势injectInputEvent 到 Launcher 窗口Launcher 处理打开通知return true ← 事件结束return false ← 继续往下分发继续分发dispatchTouchEvent(event)shouldCaptureGestures?return false ← Android 继续往下层分发到 SystemUI 的地图窗口onTouchEvent 处理,地图滚动/缩放return true ← App 消费,不传给地图return false ← 继续往下分发到其他 View

┌─────────────────────────────────────────────────────┐
│ 屏幕分层:从 top 到底部 │
│ │
│ 1. mSpyWindow (CarTaskViewInputInterceptor) ← 最顶层│
│ (悬浮透明,拦截所有触摸事件) │
│ │
│ 2. CarLauncher UI ← 原有的 Launcher UI │
│ │
│ 3. 地图 Surface (ControlledRemoteCarTaskView) │
│ ← 地图内容由 SystemUI 合成到此 │
└─────────────────────────────────────────────────────┘

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值