Android recents 流程分析

Android recents 流程分析(基于Android 7.1)

recents的启动流程

1.KeyEvent.java

    /** Key code constant: App switch key.
     * Should bring up the application switcher dialog. */
    public static final int KEYCODE_APP_SWITCH      = 187;

2.PhoneWindowManager.java

    /** {@inheritDoc} */
    @Override
    public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags) {
    	...
            } else if (keyCode == KeyEvent.KEYCODE_APP_SWITCH) {
            if (!keyguardOn) {
                if (down && repeatCount == 0) {
                    preloadRecentApps();
                } else if (!down) {
                    toggleRecentApps();
                }
            }
            return -1;
        }
        ...
    }    

我们看到当不在锁屏的时候,第一个 event down 事件会触发 preloadRecentApps(),预加载最新使用的App,而 up 事件会触发 toggleRecentApps(),切换到最近使用的App界面。

preloadRecentApps

    private void preloadRecentApps() {
        mPreloadedRecentApps = true;
        StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
        if (statusbar != null) {
            statusbar.preloadRecentApps();
        }
    }

首先将标志位 mPreloadedRecentApps 设为 true,其次获得 StatusBarManagerInternal 的对象并调用其 preloadRecentApps() 方法

StatusBarManagerInternal getStatusBarManagerInternal() {
        synchronized (mServiceAquireLock) {
            if (mStatusBarManagerInternal == null) {
                mStatusBarManagerInternal =
                        LocalServices.getService(StatusBarManagerInternal.class);
            }
            return mStatusBarManagerInternal;
        }
    }

我们看到这里获取的 StatusBarManagerInternal 是在 LocalServices 中注册的一个服务,而 StatusBarManagerInternal 是一个接口,我们找一下它的实现类。我们通过查找这个服务在哪里注册可以找到 StatusBarManagerInternal 的实现类。
3.StatusBarManagerService.java

	    /**
     * Construct the service, add the status bar view to the window manager
     */
    public StatusBarManagerService(Context context, WindowManagerService windowManager) {
        mContext = context;
        mWindowManager = windowManager;

        LocalServices.addService(StatusBarManagerInternal.class, mInternalService);
    }

这个服务是在 StatusBarManagerService 中注册的。

    /**
     * Private API used by NotificationManagerService.
     */
    private final StatusBarManagerInternal mInternalService = new StatusBarManagerInternal() {
        ...
        @Override
        public void preloadRecentApps() {
            if (mBar != null) {
                try {
                    mBar.preloadRecentApps();
                } catch (RemoteException ex) {}
            }
        }
        ...
	}

找到 StatusBarManagerInternal 的实现类,原来是在 StatusBarManagerService 中的一个匿名内部类。我们追踪其 preloadRecentApps() 方法。

    private volatile IStatusBar mBar;
    
    // ================================================================================
    // Callbacks from the status bar service.
    // ================================================================================
    @Override
    public void registerStatusBar(IStatusBar bar, List<String> iconSlots,
            List<StatusBarIcon> iconList, int switches[], List<IBinder> binders,
            Rect fullscreenStackBounds, Rect dockedStackBounds) {
            ...
            mBar = bar;
            ...
    }

mBar 是 IStatusBar 的实现类,我们找一下 registerStatusBar() 这个方法在哪里调用
4.BaseStatusBar.java

    public void start() {
		...
		mRecents = getComponent(Recents.class);
		...
        // Connect in to the status bar manager service
        mCommandQueue = new CommandQueue(this);

        int[] switches = new int[9];
        ArrayList<IBinder> binders = new ArrayList<IBinder>();
        ArrayList<String> iconSlots = new ArrayList<>();
        ArrayList<StatusBarIcon> icons = new ArrayList<>();
        Rect fullscreenStackBounds = new Rect();
        Rect dockedStackBounds = new Rect();
        try {
            mBarService.registerStatusBar(mCommandQueue, iconSlots, icons, switches, binders,
                    fullscreenStackBounds, dockedStackBounds);
        } catch (RemoteException ex) {
            // If the system process isn't there we're doomed anyway.
        }
		...
	}

我们看到这个 IStatusBar 的实现类是 CommandQueue,所以我们找一下 CommandQueue 里面的 preloadRecentApps() 方法
5.CommandQueue.java

    public void preloadRecentApps() {
        synchronized (mLock) {
            mHandler.removeMessages(MSG_PRELOAD_RECENT_APPS);
            mHandler.obtainMessage(MSG_PRELOAD_RECENT_APPS, 0, 0, null).sendToTarget();
        }
    }
   
    private final class H extends Handler {
        public void handleMessage(Message msg) {
            final int what = msg.what & MSG_MASK;
            switch (what) {
            	...
                case MSG_PRELOAD_RECENT_APPS:
                    mCallbacks.preloadRecentApps();
                    break;
                ...
            }
        }    
    }
    
    private Callbacks mCallbacks;
    
    /**
     * These methods are called back on the main thread.
     */
    public interface Callbacks {
  		...
        void preloadRecentApps();
  		...
    }
    
    public CommandQueue(Callbacks callbacks) {
        mCallbacks = callbacks;
    }

回顾一下4中的 mCommandQueue 的创建,传的 Callbacks 对象是 this,即 BaseStatusBar 就是 Callbacks 的实现类,我们在BaseStatusBar 中找一下 preloadRecentApps() 方法。
6.BaseStatusBar.java

public abstract class BaseStatusBar extends SystemUI implements
        CommandQueue.Callbacks, ActivatableNotificationView.OnActivatedListener,
        ExpandableNotificationRow.ExpansionLogger, NotificationData.Environment,
        ExpandableNotificationRow.OnExpandClickListener, OnGutsClosedListener {
    ...
    @Override
    public void preloadRecentApps() {
        int msg = MSG_PRELOAD_RECENT_APPS;
        mHandler.removeMessages(msg);
        mHandler.sendEmptyMessage(msg);
    }

我们看到 BaseStatusBar 确实实现了 CommandQueue.Callbacks 方法,

    protected class H extends Handler {
        public void handleMessage(Message m) {
            switch (m.what) {
			...
             case MSG_PRELOAD_RECENT_APPS:
                  preloadRecents();
                  break;
  			...
            }
        }
    }
    
    protected void preloadRecents() {
        if (mRecents != null) {
            mRecents.preloadRecents();
        }
    }
    
    protected RecentsComponent mRecents;

我们回顾一下4中的 start() 方法,发现 mRecents = getComponent(Recents.class),该方法在父类 SystemUI 中实现
7.SystemUI.java

    public <T> T getComponent(Class<T> interfaceType) {
        return (T) (mComponents != null ? mComponents.get(interfaceType) : null);
    }

    public <T, C extends T> void putComponent(Class<T> interfaceType, C component) {
        if (mComponents != null) {
            mComponents.put(interfaceType, component);
        }
    }
    
    public Map<Class<?>, Object> mComponents;

我们看到这边用了泛型,mComponents 里面是一个个键值对,键是接口的Class,值是该接口的实现类。

public class Recents extends SystemUI
        implements RecentsComponent {
    @Override
    public void start() {
        putComponent(Recents.class, this);
    }
}

我们在 Recents 的 start() 方法中找到 putComponent 操作,值为 this,所以 mRecents 其实就是 Recents 类的实例。我们继续追踪 preloadRecents() 方法

    /**
     * Preloads info for the Recents activity.
     */
    @Override
    public void preloadRecents() {
        // Ensure the device has been provisioned before allowing the user to interact with
        // recents
        if (!isUserSetup()) {
            return;
        }

        int currentUser = sSystemServicesProxy.getCurrentUser();
        if (sSystemServicesProxy.isSystemUser(currentUser)) {
            mImpl.preloadRecents();
        } else {
            if (mSystemToUserCallbacks != null) {
                IRecentsNonSystemUserCallbacks callbacks =
                        mSystemToUserCallbacks.getNonSystemUserRecentsForUser(currentUser);
                if (callbacks != null) {
                    try {
                        callbacks.preloadRecents();
                    } catch (RemoteException e) {
                        Log.e(TAG, "Callback failed", e);
                    }
                } else {
                    Log.e(TAG, "No SystemUI callbacks found for user: " + currentUser);
                }
            }
        }
    }
    
    private RecentsImpl mImpl;

8.RecentsImpl.java

    public void preloadRecents() {
        // Preload only the raw task list into a new load plan (which will be consumed by the
        // RecentsActivity) only if there is a task to animate to.
        SystemServicesProxy ssp = Recents.getSystemServices();
        MutableBoolean isHomeStackVisible = new MutableBoolean(true);
        if (!ssp.isRecentsActivityVisible(isHomeStackVisible)) {
            ActivityManager.RunningTaskInfo runningTask = ssp.getRunningTask();
            RecentsTaskLoader loader = Recents.getTaskLoader();
            sInstanceLoadPlan = loader.createLoadPlan(mContext);
            sInstanceLoadPlan.preloadRawTasks(!isHomeStackVisible.value);
            loader.preloadTasks(sInstanceLoadPlan, runningTask.id, !isHomeStackVisible.value);
            TaskStack stack = sInstanceLoadPlan.getTaskStack();
            if (stack.getTaskCount() > 0) {
                // Only preload the icon (but not the thumbnail since it may not have been taken for
                // the pausing activity)
                preloadIcon(runningTask.id);

                // At this point, we don't know anything about the stack state.  So only calculate
                // the dimensions of the thumbnail that we need for the transition into Recents, but
                // do not draw it until we construct the activity options when we start Recents
                updateHeaderBarLayout(stack, null /* window rect override*/);
            }
        }
    }

先分析到这儿,后续有时间继续跟

你可能感兴趣的:(Android recents 流程分析)