android 10车载CarLauncher的ActivityView源码方案分析

hi粉丝朋友们:
大家好!

1 探索ActivityView背景原因

b站免费视频教程讲解:
https://www.bilibili.com/video/BV1wj411o7A9/
android 10车载CarLauncher的ActivityView源码方案分析_第1张图片

前面的blog都是对于最新的android 13源码进行分析的CarLauncher的实现方案,已经知道CarLauncher使用是TaskView来装载新的地图Task,但是在android 12版本以前其实不是使用的TaskView的方案实现的,而是使用的ActivityView方案。

但是CarLauncher一样实现了CarLauncher的Activity进行内嵌另一个地图Activity,那么下面就有必要来了解一下

2 源码分析

创建ActivityView
package/apps/Car/Launcher/src/com/android/car/carlauncher/CarLauncher.java

  @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
      //省略部分
      //ActivityView直接在xml中已经定义好了,其实它就是个ViewGroup
        mActivityView = findViewById(R.id.maps);
    }

ActivityView的相关构造方法:
base/core/java/android/app/ActivityView.java

 public ActivityView(
            Context context, AttributeSet attrs, int defStyle, boolean singleTaskInstance) {
        super(context, attrs, defStyle);
    //创建对应的SurfaceView
        mSurfaceView = new SurfaceView(context);
      //添加到了ActivityView的容器
        addView(mSurfaceView);

    }

上面可以看出ActivityView就是个ViewGroup,构造方法里面构造了一个SurfaceView

接下来就是SurfaceView的surfaceCreated来触发:

 private class SurfaceCallback implements SurfaceHolder.Callback {
        @Override
        public void surfaceCreated(SurfaceHolder surfaceHolder) {
            if (mVirtualDisplay == null) {
            //初始化虚拟display
                initVirtualDisplay(new SurfaceSession());
                if (mVirtualDisplay != null && mActivityViewCallback != null) {
                //回调onActivityViewReady,主要是触发startActivity
                    mActivityViewCallback.onActivityViewReady(ActivityView.this);
                }
            }
//省略

        }
        }

下面看看核心方法initVirtualDisplay:

private void initVirtualDisplay(SurfaceSession surfaceSession) {
    //创建对应的display
        mVirtualDisplay = displayManager.createVirtualDisplay(
                DISPLAY_NAME + "@" + System.identityHashCode(this), width, height,
                getBaseDisplayDensity(), null,
                VIRTUAL_DISPLAY_FLAG_PUBLIC | VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY
                        | VIRTUAL_DISPLAY_FLAG_DESTROY_CONTENT_ON_REMOVAL);
      //获取displayId
        final int displayId = mVirtualDisplay.getDisplay().getDisplayId();
        final IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
		//给surfaceiew的surfacecontrol多创建一个子surfacecontrol,专门装载新的display
        mRootSurfaceControl = new SurfaceControl.Builder(surfaceSession)
                .setContainerLayer()
                .setParent(mSurfaceView.getSurfaceControl())
                .setName(DISPLAY_NAME)
                .build();

   //把新的displayreparent到前面的mRootSurfaceControl
            WindowManagerGlobal.getWindowSession().reparentDisplayContent(
                    getWindow(), mRootSurfaceControl, displayId);
          //省略
        mTmpTransaction.show(mRootSurfaceControl).apply();
        mTaskStackListener = new TaskStackListenerImpl();
        try {
            mActivityTaskManager.registerTaskStackListener(mTaskStackListener);
        } catch (RemoteException e) {
            Log.e(TAG, "Failed to register task stack listener", e);
        }
    }

上面已经准备好了对应的display了,下面一步就是启动这个display下面的相关Activity

private final ActivityView.StateCallback mActivityViewCallback =
            new ActivityView.StateCallback() {
                @Override
                public void onActivityViewReady(ActivityView view) {
                  //启动Maps的Activity
                    startMapsInActivityView();
                }
}


    private void startMapsInActivityView() {
      //实际上只是调用了mActivityView的startActivity
        if (mActivityView != null) {
            mActivityView.startActivity(getMapsIntent());
        }
    }

下面看看mActivityView.startActivity

 public void startActivity(@NonNull Intent intent) {
 //准备好对应的ActivityOption
        final ActivityOptions options = prepareActivityOptions();
        getContext().startActivity(intent, options.toBundle());
    }
    private ActivityOptions prepareActivityOptions() {
    //这里其实只是获取了新displayId,然后setLaunchDisplayId给ActivityOption
        final ActivityOptions options = ActivityOptions.makeBasic();
        options.setLaunchDisplayId(mVirtualDisplay.getDisplay().getDisplayId());
        return options;
    }   

上面ActivityOption设置setLaunchDisplayId完成后,那么Activity启动就是在新的display上面
android 10车载CarLauncher的ActivityView源码方案分析_第2张图片

你可能感兴趣的:(分屏,wms,android,framework,车载车机开发,系统开发面试,分屏,CarLauncher,车载桌面)