Android app启动流程:关于FocusedStack的研究(9)

  • A+
所属分类:AMS
final int startActivityMayWait(IApplicationThread caller, int callingUid,
        String callingPackage, Intent intent, String resolvedType,
      ....
        IActivityContainer iContainer, TaskRecord inTask) {
....
  
      ActivityOptions options = ActivityOptions.fromBundle(bOptions);
      ActivityStackSupervisor.ActivityContainer container =
          (ActivityStackSupervisor.ActivityContainer)iContainer;
  
      synchronized (mService) {
        if (container != null && container.mParentActivity != null &&
            container.mParentActivity.state != RESUMED) {
          // Cannot start a child activity if the parent is not resumed.
          return ActivityManager.START_CANCELED;
        }
    			final ActivityStack stack;
        if (container == null || container.mStack.isOnHomeDisplay()) {
          stack = mSupervisor.mFocusedStack;
        } else {
          stack = container.mStack;
        }

 

在启动activity的初期,这边先要定位一个堆栈,是怎么定位的呢?

container 是否是空,我们假设是空,因为我们要研究这个mFocusedStack ,实际上我们用am.java启动的其实是空的 那么这个堆栈就定位给了 mSupervisor.mFocusedStack

顾名思义,就是当前焦点堆栈。

如果我们dump一份activity信息来看:

Stack #1:
  mFullscreen=true
  mBounds=null
    Task id #75
    mFullscreen=true
    mBounds=null
    mMinWidth=-1
    mMinHeight=-1
    mLastNonFullscreenBounds=null
      TaskRecord{97e7cc8 #75 A=com.example.djh.demo2 U=0 StackId=1 sz=1}
      Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 pkg=com.example.djh.demo2 cmp=com.example.djh.demo2/.MainActivity (has extras) }
        Hist #0: ActivityRecord{4c94602 u0 com.example.djh.demo2/.MainActivity t75}
          Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 pkg=com.example.djh.demo2 cmp=com.example.djh.demo2/.MainActivity (has extras) }
          ProcessRecord{f2551e4 4772:com.example.djh.demo2/u0a116}
    Task id #76
    mFullscreen=true
    mBounds=null
    mMinWidth=-1
    mMinHeight=-1
    mLastNonFullscreenBounds=null
      TaskRecord{289fa63 #76 A=com.eebbk.djh.eebbkdemo U=0 StackId=1 sz=1}
      Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=com.eebbk.djh.eebbkdemo/.MainActivity (has extras) }
        Hist #0: ActivityRecord{2d7bcc4 u0 com.eebbk.djh.eebbkdemo/.MainActivity t76}
          Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=com.eebbk.djh.eebbkdemo/.MainActivity (has extras) }
          ProcessRecord{996b721 5316:com.eebbk.djh.eebbkdemo/u0a117}

    Running activities (most recent first):
      TaskRecord{289fa63 #76 A=com.eebbk.djh.eebbkdemo U=0 StackId=1 sz=1}
        Run #1: ActivityRecord{2d7bcc4 u0 com.eebbk.djh.eebbkdemo/.MainActivity t76}
      TaskRecord{97e7cc8 #75 A=com.example.djh.demo2 U=0 StackId=1 sz=1}
        Run #0: ActivityRecord{4c94602 u0 com.example.djh.demo2/.MainActivity t75}

    mResumedActivity: ActivityRecord{2d7bcc4 u0 com.eebbk.djh.eebbkdemo/.MainActivity t76}

  Stack #0:
  mFullscreen=true
  mBounds=null
    Task id #72
    mFullscreen=true
    mBounds=null
    mMinWidth=-1
    mMinHeight=-1
    mLastNonFullscreenBounds=null
      TaskRecord{b5164bd #72 A=com.bbk.studyos.launcher U=0 StackId=0 sz=1}
      Intent { act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10000100 cmp=com.bbk.studyos.launcher/.activity.Launcher }
        Hist #0: ActivityRecord{ca2297f u0 com.bbk.studyos.launcher/.activity.Launcher t72}
          Intent { act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10000100 cmp=com.bbk.studyos.launcher/.activity.Launcher }
          ProcessRecord{7a4d4b1 1750:com.bbk.studyos.launcher/u0a70}

    Running activities (most recent first):
      TaskRecord{b5164bd #72 A=com.bbk.studyos.launcher U=0 StackId=0 sz=1}
        Run #0: ActivityRecord{ca2297f u0 com.bbk.studyos.launcher/.activity.Launcher t72}

  mFocusedActivity: ActivityRecord{4c94602 u0 com.example.djh.demo2/.MainActivity t75}
  mFocusedStack=ActivityStack{4a1598b stackId=1, 2 tasks} mLastFocusedStack=ActivityStack{4a1598b stackId=1, 2 tasks}

 

它会明确告诉你mFocusedStack 是 ActivityStack这个类4a1598b,堆栈编号是1,里面有两个tasks,往上看,它指示的内容应该是:

Stack #1:
  mFullscreen=true
  mBounds=null
    Task id #75
   ....
      TaskRecord{97e7cc8 #75 A=com.example.djh.demo2 U=0 StackId=1 sz=1}
   ....
    Task id #76
   ....
      TaskRecord{289fa63 #76 A=com.eebbk.djh.eebbkdemo U=0 StackId=1 sz=1}
   ....

应该是这个堆栈,对吧,task 75 和 76 对吧。

那么我们看下代码是怎么管理这个mFocusedStack

刚开始

ActivityStack mFocusedStack;
  void setWindowManager(WindowManagerService wm) {
        synchronized (mService) {
            mWindowManager = wm;
....
            mHomeStack = mFocusedStack = mLastFocusedStack =
                    getStack(HOME_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
....
        }
    }

 

变量定义,然后在setWindowManager中设置,这个setWindowManager是ActivityManagerService在启动的时候调用的。

然后调用getStack 把 三个mHomeStack和mFocusedStack和mLastFocusedStack设置成一样的。

public static final int INVALID_STACK_ID = -1;
      public static final int FIRST_STATIC_STACK_ID = 0;
      public static final int HOME_STACK_ID = FIRST_STATIC_STACK_ID;
      public static final int FULLSCREEN_WORKSPACE_STACK_ID = 1;

      /** ID of stack where freeform/resized activities are normally launched into. */
      public static final int FREEFORM_WORKSPACE_STACK_ID = FULLSCREEN_WORKSPACE_STACK_ID + 1;

      /** ID of stack that occupies a dedicated region of the screen. */
      public static final int DOCKED_STACK_ID = FREEFORM_WORKSPACE_STACK_ID + 1;

      /** ID of stack that always on top (always visible) when it exist. */
      public static final int PINNED_STACK_ID = DOCKED_STACK_ID + 1;

      /** Last static stack stack ID. */
      public static final int LAST_STATIC_STACK_ID = PINNED_STACK_ID;

      /** Start of ID range used by stacks that are created dynamically. */
      public static final int FIRST_DYNAMIC_STACK_ID = LAST_STATIC_STACK_ID + 1;

这里有必要先提及下这个HOME_STACK_ID,和其他的标签id,他们的意思分别有注释。

ActivityStack getStack(int stackId, boolean createStaticStackIfNeeded, boolean createOnTop) {
....
        return createStackOnDisplay(stackId, Display.DEFAULT_DISPLAY, createOnTop);
    }

这里调用create函数创建堆栈:

ActivityStack createStackOnDisplay(int stackId, int displayId, boolean onTop) {
        ActivityDisplay activityDisplay = mActivityDisplays.get(displayId);
        if (activityDisplay == null) {
            return null;
        }

        ActivityContainer activityContainer = new ActivityContainer(stackId);
        mActivityContainers.put(stackId, activityContainer);
        activityContainer.attachToDisplayLocked(activityDisplay, onTop);
        return activityContainer.mStack;
    }

好的这里去创建一个ActivityContainer 对象,传进去的是stackid = 0

然后返回的是activityContainer.mStack。

那么意思就是说关键在这个ActivityContainer的创建。

ActivityContainer(int stackId) {
            synchronized (mService) {
                mStackId = stackId;
                mStack = new ActivityStack(this, mRecentTasks);
                mIdString = "ActivtyContainer{" + mStackId + "}";
                if (DEBUG_STACK) Slog.d(TAG_STACK, "Creating " + this);
            }
        }

 

这边new 了一个ActivityStack,它的参数是mRecentTasks,mRecentTasks这个是历史记录的,在开机的时候会把上次的记录下来。

所以我们可以梳理下,display 有了,stack有了,tasks也有了,那么这个堆栈算是完成了。

操作函数

ActivityStack getFocusedStack() {
        return mFocusedStack;
    }

 

获取

boolean isFocusedStack(ActivityStack stack) {
        if (stack == null) {
            return false;
        }

        final ActivityRecord parent = stack.mActivityContainer.mParentActivity;
        if (parent != null) {
            stack = parent.task.stack;
        }
        return stack == mFocusedStack;
    }

 

判断是否是FocusedStack

void setFocusStackUnchecked(String reason, ActivityStack focusCandidate) {
        if (!focusCandidate.isFocusable()) {
            // The focus candidate isn't focusable. Move focus to the top stack that is focusable.
            focusCandidate = focusCandidate.getNextFocusableStackLocked();
        }

        if (focusCandidate != mFocusedStack) {
            mLastFocusedStack = mFocusedStack;
            mFocusedStack = focusCandidate;
        }

        final ActivityRecord r = topRunningActivityLocked();
        if (!mService.mDoingSetFocusedActivity && mService.mFocusedActivity != r) {
            mService.setFocusedActivityLocked(r, reason + " setFocusStack");
        }

    }

 

设置一个堆栈为FocusedStack ,这里

  • 1、设置的这个focusCandidate 不等于目前的这个 就设置mFocusedStack = focusCandidate,还把原来的给mLastFocusedStack,说明你已经成为过去时。
  • 2、topRunningActivityLocked拿到目前最前面的Activity,设置目前的FocusedActivity。

那么这个setFocusStackUnchecked 在什么时候调用呢?

在ActivityStack.java里面。

void moveToFront(String reason, TaskRecord task) {

        if (isOnHomeDisplay()) {
            mStackSupervisor.setFocusStackUnchecked(reason, this);
        }

        if (task != null) {
            mWindowManager.moveTaskToTop(task.taskId);
        }
 
    }

这里还移动了mWindowManager的task。进行同步。

Android app启动流程:调用startProcessLocked的几种情况(1)

Android app启动流程:startProcessLocked函数分析(2)

Android app启动流程:Process.start(3)

Android app启动流程:startservice(4)

Android app启动流程:broadcast广播的注册(5)

Android app启动流程:广播的发送broadcastIntentLocked(6)

Android app启动流程:广播的发送scheduleBroadcastsLocked(7)

Android app启动流程:广播的发送processNextBroadcast(8)

Android app启动流程:关于FocusedStack的研究(9)

Android app启动流程:startActivityMayWait分析(10)

Android app启动流程:startActivityLocked分析(11)

Android app启动流程:Ams对activitystack和task的管理(12)

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: