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界面。
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*/);
}
}
}
先分析到这儿,后续有时间继续跟