<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      3D車模通過TaskView顯示在Launcher,首先需要知道,為什么要用TaskView,而不是Activity,然后在說加載流程

      1、surface比activity等效率更高,特別是針對車模跟地圖等重量級場景

      2、切換桌面等場景時,可以更精確的控制暫停恢復

      3、進程隔離,更精細的生命周期管理跟控制

      4、taskView中SurfaceControl的跨進程綁定機制(reparent操作)效率比binder通訊效率更高

      android.app.ActivityView(標記為棄用?)

      跟TaskView一樣都是Android系統中用于管理多窗口和任務嵌入的組件

      public class ActivityView extends ViewGroup {
          private static final String DISPLAY_NAME = "ActivityViewVirtualDisplay";
          private static final String TAG = "ActivityView";
          private final SurfaceView mSurfaceView;
          private Surface mSurface;
          private final SurfaceCallback mSurfaceCallback;
          private StateCallback mActivityViewCallback;
          private IActivityManager mActivityManager;
          private TaskStackListener mTaskStackListener;
      
          public ActivityView(Context context) {
              this(context, (AttributeSet)null);
          }
      
          public ActivityView(Context context, AttributeSet attrs) {
              this(context, attrs, 0);
          }
      
          public ActivityView(Context context, AttributeSet attrs, int defStyle) {
              super(context, attrs, defStyle);
              this.mActivityManager = ActivityManager.getService();
              this.mSurfaceView = new SurfaceView(context);
              this.mSurfaceCallback = new SurfaceCallback();
              this.mSurfaceView.getHolder().addCallback(this.mSurfaceCallback);
              this.addView(this.mSurfaceView);
          }
      View Code

      從源碼中看到,繼承自ViewGroup,基于SurfaceView實現,在初始化時將 SurfaceView addView到ViewGroup中

      ActivityView? 直接依賴傳統的窗口管理機制,通過 WindowManager 控制嵌入的 Activity 生命周期。

      com.android.wm.shell.TaskView

      public class TaskView extends SurfaceView implements SurfaceHolder.Callback, ShellTaskOrganizer.TaskListener, ViewTreeObserver.OnComputeInternalInsetsListener {
          private final ShellTaskOrganizer mTaskOrganizer;
          private ActivityManager.RunningTaskInfo mTaskInfo;
          private WindowContainerToken mTaskToken;
          private SurfaceControl mTaskLeash;
          private final SurfaceControl.Transaction mTransaction = new SurfaceControl.Transaction();
      
          public TaskView(Context context, ShellTaskOrganizer organizer, SyncTransactionQueue syncQueue) {
              super(context, (AttributeSet)null, 0, 0, true);
              this.getHolder().addCallback(this);
          }
      View Code
      public void onTaskAppeared(ActivityManager.RunningTaskInfo taskInfo, SurfaceControl leash) {
              this.mTaskInfo = taskInfo;
              this.mTaskToken = taskInfo.token;
              this.mTaskLeash = leash;
              if (this.mSurfaceCreated) {
                  this.mTransaction.reparent(this.mTaskLeash, this.getSurfaceControl()).show(this.mTaskLeash).apply();
              } else {
                  this.updateTaskVisibility();
              }
      
              this.mTaskOrganizer.setInterceptBackPressedOnTaskRoot(this.mTaskToken, true);
              this.onLocationChanged();
              if (taskInfo.taskDescription != null) {
                  int backgroundColor = taskInfo.taskDescription.getBackgroundColor();
                  this.mSyncQueue.runInSync((t) -> this.setResizeBackgroundColor(t, backgroundColor));
              }
      
              if (this.mListener != null) {
                  int taskId = taskInfo.taskId;
                  ComponentName baseActivity = taskInfo.baseActivity;
                  this.mListenerExecutor.execute(() -> this.mListener.onTaskCreated(taskId, baseActivity));
              }
      
          }
      View Code
      Android 12 引入的替代方案,專為 Android Automotive OS (AAOS) 優化,并擴展了 ShellTaskOrganizer.TaskListener 接口。

      直接繼承自SurfaceView,并且在onTaskAppeared回調中使用了reparent操作,支持動態調整嵌入任務的位置和大小?。

      車模加載流程

      車模屬于unity交互,在android中提供一個容器用于顯示,這里直接使用Activity

      <androidx.fragment.app.FragmentContainerView
              android:id="@+id/unity_player_fragment"
              android:name="com.test.UnityPlayerFragment"
              android:layout_width="match_parent"
              android:layout_height="match_parent" />
      View Code

      新建一個CarLauncherActivity用于顯示這個UnityPlayerFragment

      3DActivity有了,需要將它顯示到launcher桌面(MainActivity),自定義TaskView,用于3D桌面

      <com.test.TaskViewCompat
              android:id="@+id/launcher3d"
              android:layout_width="0dp"
              android:layout_height="0dp"
              android:visibility="invisible"
              app:layout_constraintBottom_toBottomOf="parent"
              app:layout_constraintEnd_toEndOf="parent"
              app:layout_constraintStart_toStartOf="parent"
              app:layout_constraintTop_toTopOf="parent" />
      View Code

      在MainActivity啟動時通過 surfaceCreated 回調,對桌面進行初始化操作

      public void surfaceCreated(SurfaceHolder holder) {
              this.mSurfaceCreated = true;
              if (this.mListener != null && !this.mIsInitialized) {
                  this.mIsInitialized = true;
                  this.mListenerExecutor.execute(() -> this.mListener.onInitialized());
              }
      
              this.mShellExecutor.execute(() -> {
                  if (this.mTaskToken != null) {
                      this.mTransaction.reparent(this.mTaskLeash, this.getSurfaceControl()).show(this.mTaskLeash).apply();
                      this.updateTaskVisibility();
                  }
              });
          }
      View Code

      接下來需要實現嵌入操作,可以看到在首次進入時,會調用 TaskView. Listener的 onInitialized 方法,在回調中需要執行taskview的startActivity進行內嵌

      public void startActivity(PendingIntent pendingIntent, Intent fillInIntent, ActivityOptions options, Rect launchBounds) {
              this.prepareActivityOptions(options, launchBounds);
      
              try {
                  pendingIntent.send(this.mContext, 0, fillInIntent, (PendingIntent.OnFinished)null, (Handler)null, (String)null, options.toBundle());
              } catch (Exception e) {
                  throw new RuntimeException(e);
              }
          }
      View Code

      startActivity后會觸發狀態變更,系統層處理后,在Systemui層通過TaskOrganizer監聽狀態

      android.window.TaskOrganizer

      當需要嵌入顯示另一個應用的 Activity 時,TaskOrganizer 會提供該任務窗口的 SurfaceControl(稱為 "leash"),但是TaskOrganizer位與SystemUI模塊,所以需要通過AIDL進行跨進程通訊

      首先在launcher模塊定義好接口

      package com.android.wm.shell;
      
      import android.view.SurfaceControl;
      import android.graphics.Rect;
      import android.window.WindowContainerToken;
      import com.android.wm.shell.RunningTaskInfo;
      
      /**
       * Interface for ActivityTaskManager/WindowManager to delegate control of tasks.
       * {@hide}
       */
      oneway interface ITaskView {
          /**
           * Called when a Task is starting and the system would like to show a UI to indicate that an
           * application is starting. The client is responsible to add/remove the starting window if it
           * has create a starting window for the Task.
           *
           * @param info The information about the Task that's available
           * @param appToken Token of the application being started.
           */
      
          /**
           * Called when the Task want to remove the starting window.
           * @param removalInfo The information used to remove the starting window.
           */
      
          /**
           * Called when the Task want to copy the splash screen.
           */
          void copySplashScreenView(int taskId);
      
          /**
           * Called when the Task removed the splash screen.
           */
          void onAppSplashScreenViewRemoved(int taskId);
      
          /**
           * A callback when the Task is available for the registered organizer. The client is responsible
           * for releasing the SurfaceControl in the callback. For non-root tasks, the leash may initially
           * be hidden so it is up to the organizer to show this task.
           *
           * @param taskInfo The information about the Task that's available
           * @param leash A persistent leash for this Task.
           */
          void onTaskAppeared(in RunningTaskInfo taskInfo, in SurfaceControl leash);
          void onTaskVanished(in RunningTaskInfo taskInfo);
      
          /**
           * Will fire when core attributes of a Task's info change. Relevant properties include the
           * {@link WindowConfiguration.ActivityType} and whether it is resizable.
           *
           * This is used, for example, during split-screen. The flow for starting is: Something sends an
           * Intent with windowingmode. Then WM finds a matching root task and launches the new task into
           * it. This causes the root task's info to change because now it has a task when it didn't
           * before. The default Divider implementation interprets this as a request to enter
           * split-screen mode and will move all other Tasks into the secondary root task. When WM
           * applies this change, it triggers an info change in the secondary root task because it now
           * has children. The Divider impl looks at the info and can see that the secondary root task
           * has adopted an ActivityType of HOME and proceeds to show the minimized dock UX.
           */
          void onTaskInfoChanged(in RunningTaskInfo taskInfo);
      
          /**
           * Called when the task organizer has requested
           * {@link ITaskOrganizerController.setInterceptBackPressedOnTaskRoot} to get notified when the
           * user has pressed back on the root activity of a task controlled by the task organizer.
           */
          void onBackPressedOnTaskRoot(in RunningTaskInfo taskInfo);
      
          /**
           * Called when the IME has drawn on the organized task.
           */
          void onImeDrawnOnTask(int taskId);
      }
      View Code

      并且提供Service

      <application android:name="com.testCarLauncherApp">
              <service
                  android:name="com.test.SharedTaskViewService"
                  android:enabled="true"
                  android:exported="true" />
          </application>
      
      package com.test.taskview;
      
      import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
      
      import android.app.Service;
      import android.content.Intent;
      import android.os.Handler;
      import android.os.IBinder;
      import android.os.Looper;
      import android.util.Log;
      import android.view.SurfaceControl;
      
      import com.android.wm.shell.ITaskView;
      import com.android.wm.shell.ShellTaskOrganizer;
      import com.android.wm.shell.RunningTaskInfo;
      import com.android.wm.shell.common.HandlerExecutor;
      
      import java.util.concurrent.ConcurrentHashMap;
      
      public class SharedTaskViewService extends Service {
          private static final String TAG = "SharedTaskViewService";
          private ConcurrentHashMap<Integer, Integer> taskIdDisplayMap = new ConcurrentHashMap<>();
          private final HandlerExecutor mExecutor = new HandlerExecutor(new Handler(Looper.getMainLooper()));
      
      
          private int getRealDisplayId(int taskId) {
              if (taskIdDisplayMap.containsKey(taskId)) {
                  Integer val = taskIdDisplayMap.get(taskId);
                  if (val == null) {
                      return -1;
                  }
                  return val.intValue();
              }
              return -2;
          }
      
          ITaskView taskView = new ITaskView.Stub() {
              public void copySplashScreenView(int taskId) {
      
              }
      
              public void onAppSplashScreenViewRemoved(int taskId) {
      
              }
      
              public void onTaskAppeared(RunningTaskInfo taskInfo, SurfaceControl leash) {
                  mExecutor.execute(() -> SharedTaskViewService.this.onTaskAppeared(taskInfo, leash));
              }
      
              public void onTaskVanished(RunningTaskInfo taskInfo) {
                  mExecutor.execute(() -> SharedTaskViewService.this.onTaskVanished(taskInfo));
              }
      
      
              public void onTaskInfoChanged(RunningTaskInfo taskInfo) {
                  mExecutor.execute(() -> SharedTaskViewService.this.onTaskInfoChanged(taskInfo));
              }
      
      
              public void onBackPressedOnTaskRoot(RunningTaskInfo taskInfo) {
      
              }
      
              /**
               * Called when the IME has drawn on the organized task.
               */
              public void onImeDrawnOnTask(int taskId) {
      
              }
          };
      
      
          public void onTaskAppeared(RunningTaskInfo taskInfo, SurfaceControl leash) {
              if (SharedTaskManager.getInstance().getListeners() != null) {
                  if (taskInfo != null && taskInfo.info != null && taskInfo.info.baseIntent != null && taskInfo.info.baseIntent.getComponent() != null) {
                      String pkgName = taskInfo.info.baseIntent.getComponent().getPackageName();
                      String clsName = taskInfo.info.baseIntent.getComponent().getClassName();
                      Log.w(TAG, "onTaskAppeared clsName:" + clsName);
                      boolean hasKey = SharedTaskManager.getInstance().getListeners().containsKey(clsName);
                      boolean hasTaskLeash = SharedTaskManager.getInstance().hasTaskLeash(clsName);
                      if (hasTaskLeash) {
                          SharedTaskManager.getInstance().addOrUpdateTaskLeash(clsName, new SharedTaskManager.SharedTaskInfo(leash, taskInfo.info.token));
                      }
      
                      if (hasKey) {
                          ShellTaskOrganizer.TaskListener taskListener = SharedTaskManager.getInstance().getListeners().get(clsName);
                          if (taskListener != null) {
                              Logger.w(TAG, "onTaskAppeared:" + pkgName + "displayId:" + taskInfo.info.displayId);
                              if (taskInfo.info.displayId == 0 && taskInfo.info.getWindowingMode() == WINDOWING_MODE_MULTI_WINDOW && taskInfo.info.numActivities > 0) {
                                  taskIdDisplayMap.put(taskInfo.info.taskId, 0);
                                  taskListener.onTaskAppeared(taskInfo.info, leash);
                              }
                          }
                      } else {
                          Log.w(TAG, "onTaskAppeared,no suiteable key in TaskManager.getInstance().getListeners:" + pkgName);
                      }
      
                  }
              }
          }
      
          public void onTaskVanished(RunningTaskInfo taskInfo) {
              if (SharedTaskManager.getInstance().getListeners() != null) {
                  if (taskInfo != null && taskInfo.info != null && taskInfo.info.realActivity != null) {
                      String pkgName = taskInfo.info.baseIntent.getComponent().getPackageName();
                      String clsName = taskInfo.info.baseIntent.getComponent().getClassName();
                      boolean hasKey = SharedTaskManager.getInstance().getListeners().containsKey(clsName);
                      if (hasKey) {
                          ShellTaskOrganizer.TaskListener taskListener = SharedTaskManager.getInstance().getListeners().get(clsName);
                          if (taskListener != null) {
                              int realDisplayId = getRealDisplayId(taskInfo.info.taskId);
                              Logger.w(TAG, "onTaskVanished:" + pkgName + ",displayId:" + taskInfo.info.displayId + ",realDisplayId:" + realDisplayId);
                              if (realDisplayId == 0) {
                                  taskListener.onTaskVanished(taskInfo.info);
                              }
                          }
                      } else {
                          Log.w(TAG, "onTaskVanished,no suiteable key in TaskManager.getInstance().getListeners:" + clsName);
                      }
                  }
              }
          }
      
      
          public void onTaskInfoChanged(RunningTaskInfo taskInfo) {
              if (SharedTaskManager.getInstance().getListeners() != null) {
                  if (taskInfo != null && taskInfo.info != null && taskInfo.info.realActivity != null) {
                      String pkgName = taskInfo.info.baseIntent.getComponent().getPackageName();
                      String clsName = taskInfo.info.baseIntent.getComponent().getClassName();
                      boolean hasKey = SharedTaskManager.getInstance().getListeners().containsKey(clsName);
                      if (hasKey) {
                          ShellTaskOrganizer.TaskListener taskListener = SharedTaskManager.getInstance().getListeners().get(clsName);
                          if (taskListener != null) {
                              Logger.w(TAG, "onTaskInfoChanged:" + taskInfo.info);
                              taskListener.onTaskInfoChanged(taskInfo.info);
                          }
                      } else {
                          Log.w(TAG, "onTaskInfoChanged,no suiteable key in TaskManager.getInstance().getListeners:" + clsName);
                      }
                  }
              }
          }
      
      
          @Override
          public IBinder onBind(Intent intent) {
              Logger.w(TAG, "onBind: ");
              return (IBinder) taskaskView;
          }
      
          @Override
          public void onCreate() {
              super.onCreate();
              Logger.w(TAG, "onCreate: ");
          }
      
          @Override
          public void onDestroy() {
              super.onDestroy();
              Logger.w(TAG, "onDestroy: ");
          }
      }
      View Code

       

      SystemUI模塊需要繼承TaskOrganizer,在TaskOrganizer的onTaskAppeared中去同步到Launcher模塊

      private void bind(){
              Intent intent = new Intent();
              intent.setComponent(new ComponentName(PACKAGE_LAUNCHER, SERVICE_LAUNCHER_TASK_VIEW));
              mContext.bindService(intent,connection,Context.BIND_AUTO_CREATE);
              Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "bind SharedTaskViewService");
          }
      
      private final ServiceConnection connection = new ServiceConnection() {
              @Override
              public void onServiceConnected(ComponentName name, IBinder service) {
                  synchronized (mLock) {
                      StringBuilder tempInfoString = new StringBuilder();
                      for (TaskAppearedInfo taskAppearedInfo : tempInfoList) {
                          tempInfoString.append(getPackageName(taskAppearedInfo.getTaskInfo())).append(",");
                      }
                      Log.d(TAG, "onServiceConnected name = " + name + ", tempInfoList = " + tempInfoString);
                      ProtoLog.v(WM_SHELL_TASK_ORG, "onServiceConnected name = " + name);
                      Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
                      iTaskView = ITaskView.Stub.asInterface(service);
                      isConnecting = false;
                      if(tempInfoList.size()>0){
                          try {
                              Log.d(TAG, "tempInfo is not null, notify launcher");
                              for (TaskAppearedInfo taskAppearedInfo : tempInfoList) {
                                  Log.d(TAG, "tempInfo = " + getPackageName(taskAppearedInfo.getTaskInfo()));
                                  RunningTaskInfo runningTaskInfo = taskAppearedInfo.getTaskInfo();
                                  if (runningTaskInfo == null || runningTaskInfo.numActivities == 0) {
                                      Log.d(TAG, "ignore empty taskInfo " + runningTaskInfo);
                                  } else {
                                      iTaskView.onTaskAppeared(new RunningTaskInfo(taskAppearedInfo.getTaskInfo()), taskAppearedInfo.getLeash());
                                  }
                              }
                              tempInfoList.clear();
                          } catch (RemoteException e) {
                              e.printStackTrace();
                          }
                      }
                  }
              }
      
              @Override
              public void onServiceDisconnected(ComponentName name) {
                  Log.d(TAG,"onServiceDisconnected componentName="+name);
                  iTaskView = null;
                  bind();
              }
      
              @Override
              public void onBindingDied(ComponentName name) {
                  Log.d(TAG,"onBindingDied componentName="+name);
                  iTaskView = null;
                  bind();
              }
          };
      
      @Override
          public void onTaskAppeared(RunningTaskInfo taskInfo, SurfaceControl leash) {
              Log.d(TAG, "task appeared " + getPackageName(taskInfo));
              synchronized (mLock) {
                  iTaskView.onTaskAppeared(new RunningTaskInfo(info.getTaskInfo()), info.getLeash());
              }
          }
      View Code

      初始化時通過bind()方法綁定服務,在onTaskAppeared回調中調用服務方法

      Launcher在收到AIDL方法onTaskAppeared時會執行 mTransaction.reparent(mTaskLeash, getSurfaceControl()) 顯示當前車模桌面

       

       
      posted on 2025-10-24 16:47  翻滾的咸魚  閱讀(21)  評論(0)    收藏  舉報

      主站蜘蛛池模板: 莆田市| 亚洲偷自拍国综合| 亚洲色欲在线播放一区| 欧美成人午夜在线观看视频| 潞城市| 少妇人妻综合久久中文字幕| 欧美高清freexxxx性| 噜噜噜噜私人影院| 亚洲天堂激情av在线| 国产精品自拍中文字幕| 亚洲欧洲日产国产av无码| 视频二区中文字幕在线| 六十路老熟妇乱子伦视频| 伊人欧美在线| 国产91久久精品一区二区| 欧美伦费免费全部午夜最新| 石台县| 国产精品一二二区视在线| mm1313亚洲国产精品| 日韩大片在线永久免费观看网站| 色午夜一av男人的天堂| 成人免费A级毛片无码片2022| 天天综合色一区二区三区| 无码AV无码免费一区二区| 亚洲大尺度视频在线播放| 热久久美女精品天天吊色| 丰满多毛的大隂户视频| 久久国产精品老女人| 日本高清在线观看WWW色| 四虎永久免费高清视频| 国产精品自在自线免费观看| 亚洲综合视频一区二区三区| 日本一卡二卡不卡视频查询| 97在线碰| 夜夜爽77777妓女免费看| 亚洲AV成人片不卡无码| 日本免费一区二区三区| 亚洲精品国产第一区二区| 重口SM一区二区三区视频| 欧美精品V欧洲精品| 国产极品美女高潮抽搐免费网站 |