Andorid N最近のタスクマネージャプロセスの詳細(一)
20364 ワード
前言
誰もがタスクマネージャを使ったことがあると信じています.携帯電話の起動方法によって異なる可能性があります.仮想ボタンや実体ボタンがある場合は、Menuボタンを短く押すか長く押すことでトリガーされる可能性があります.もしこれらがなければ、指紋ボタンが1つしかない場合は、長すぎるボタンでトリガーされる可能性があります.この機能はよく使われています.彼は私たちを早く前のタスクスタックに戻すことができます.はい、くだらないことはあまり言わないで、直接コードを分析します.私たちは5つの部分に分けて説明します.それぞれ:最近のタスクマネージャのトリガ Taskの取得 サムネイルの取得 Taskの除去 その他 1.最近のタスクマネージャのトリガー
ファイル:PhoneStatusBar.java
1.1 toggleRecentApps
ファイル:BaseStatusBar.java
1.1.1 toggleRecents
ファイル:BaseStatusBar.java
1.2 toggleRecents
ファイル:Recents.java
このメソッドの名前からも分かるようにRecents activityを起動するには、主にRecentsImplのtoggleRecentsメソッドを通じて、引き続き下を見ていきます
1.2.1 mImpl.toggleRecents
ファイル:RecentsImpl.java
ここで最も重要なのはstartRecentsActivity、つまりタスクマネージャを起動するActivityです
1.2.2 startRecentsActivity
ファイル:RecentsImpl.java
主にRecentsActivityを起動する前の準備をします.
1.2.3 RecentsActivityの起動開始
ファイル:RecentsImpl.java
1.3 RecentsActivity
まずonCreateファイルを見てみましょう.
1.3.1 stack viewの再ロード
ファイル:RecentsActivity.java
もしloadPlan.hasTasks()はfalseに等しいので、preLoadTasksでTaskをロードし、次に第2の部分であるTaskの取得に入ります.
誰もがタスクマネージャを使ったことがあると信じています.携帯電話の起動方法によって異なる可能性があります.仮想ボタンや実体ボタンがある場合は、Menuボタンを短く押すか長く押すことでトリガーされる可能性があります.もしこれらがなければ、指紋ボタンが1つしかない場合は、長すぎるボタンでトリガーされる可能性があります.この機能はよく使われています.彼は私たちを早く前のタスクスタックに戻すことができます.はい、くだらないことはあまり言わないで、直接コードを分析します.私たちは5つの部分に分けて説明します.それぞれ:
ファイル:PhoneStatusBar.java
private View.OnClickListener mRecentsClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
awakenDreams();
// 1.1
toggleRecentApps();
}
};
1.1 toggleRecentApps
ファイル:BaseStatusBar.java
@Override
public void toggleRecentApps() {
// 1.1.1
toggleRecents();
}
1.1.1 toggleRecents
ファイル:BaseStatusBar.java
protected void toggleRecents() {
if (mRecents != null) {
// 1.2
mRecents.toggleRecents(mDisplay);
}
}
1.2 toggleRecents
ファイル:Recents.java
@Override
public void toggleRecents(Display display) {
......
int currentUser = sSystemServicesProxy.getCurrentUser();
if (sSystemServicesProxy.isSystemUser(currentUser)) {
// 1.2.1
mImpl.toggleRecents(growTarget);
} else {
......
}
}
このメソッドの名前からも分かるようにRecents activityを起動するには、主にRecentsImplのtoggleRecentsメソッドを通じて、引き続き下を見ていきます
1.2.1 mImpl.toggleRecents
ファイル:RecentsImpl.java
public void toggleRecents(int growTarget) {
// Skip this toggle if we are already waiting to trigger recents via alt-tab
if (mFastAltTabTrigger.isDozing()) {
return;
}
mDraggingInRecents = false;
mLaunchedWhileDocking = false;
mTriggeredFromAltTab = false;
try {
SystemServicesProxy ssp = Recents.getSystemServices();
MutableBoolean isHomeStackVisible = new MutableBoolean(true);
long elapsedTime = SystemClock.elapsedRealtime() - mLastToggleTime;
if (ssp.isRecentsActivityVisible(isHomeStackVisible)) {
......
} else {
// 350
if (elapsedTime < MIN_TOGGLE_DELAY_MS) {
return;
}
//
ActivityManager.RunningTaskInfo runningTask = ssp.getRunningTask();
// 1.2.2
startRecentsActivity(runningTask, isHomeStackVisible.value, true /* animate */,
growTarget);
// Only close the other system windows if we are actually showing recents
ssp.sendCloseSystemWindows(BaseStatusBar.SYSTEM_DIALOG_REASON_RECENT_APPS);
mLastToggleTime = SystemClock.elapsedRealtime();
}
} catch (ActivityNotFoundException e) {
Log.e(TAG, "Failed to launch RecentsActivity", e);
}
}
ここで最も重要なのはstartRecentsActivity、つまりタスクマネージャを起動するActivityです
1.2.2 startRecentsActivity
ファイル:RecentsImpl.java
protected void startRecentsActivity(ActivityManager.RunningTaskInfo runningTask,
boolean isHomeStackVisible, boolean animate, int growTarget) {
......
// animate true
if (!animate) {
startRecentsActivity(ActivityOptions.makeCustomAnimation(mContext, -1, -1));
return;
}
ActivityOptions opts;
if (isBlacklisted) {
opts = getUnknownTransitionActivityOptions();
} else if (useThumbnailTransition) {
// Try starting with a thumbnail transition
opts = getThumbnailTransitionActivityOptions(runningTask, mDummyStackView,
windowOverrideRect);
} else {
// 0 ,hasRecentTasks true
opts = hasRecentTasks
? getHomeTransitionActivityOptions() // ,
: getUnknownTransitionActivityOptions();
}
// 1.2.3
startRecentsActivity(opts);
mLastToggleTime = SystemClock.elapsedRealtime();
}
主にRecentsActivityを起動する前の準備をします.
1.2.3 RecentsActivityの起動開始
ファイル:RecentsImpl.java
private void startRecentsActivity(ActivityOptions opts) {
Intent intent = new Intent();
intent.setClassName(RECENTS_PACKAGE, RECENTS_ACTIVITY);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
| Intent.FLAG_ACTIVITY_TASK_ON_HOME);
if (opts != null) {
// RecentsActivity
mContext.startActivityAsUser(intent, opts.toBundle(), UserHandle.CURRENT);
} else {
mContext.startActivityAsUser(intent, UserHandle.CURRENT);
}
EventBus.getDefault().send(new RecentsActivityStartingEvent());
}
1.3 RecentsActivity
まずonCreateファイルを見てみましょう.
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mFinishedOnStartup = false;
// Recents Activity, finish Acitivity
// debug ,push SysUI apk
SystemServicesProxy ssp = Recents.getSystemServices();
if (ssp == null) {
mFinishedOnStartup = true;
finish();
return;
}
// Register this activity with the event bus
EventBus.getDefault().register(this, EVENT_BUS_PRIORITY);
//
// PackageManagerd recent list
mPackageMonitor = new RecentsPackageMonitor();
mPackageMonitor.register(this);
// Set the Recents layout
setContentView(R.layout.recents);
takeKeyEvents(true); // Activity View,
mRecentsView = (RecentsView) findViewById(R.id.recents_view);
mRecentsView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
mScrimViews = new SystemBarScrimViews(this);
getWindow().getAttributes().privateFlags |=
WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY;
Configuration appConfiguration = Utilities.getAppConfiguration(this);
mLastDeviceOrientation = appConfiguration.orientation;
mLastDisplayDensity = appConfiguration.densityDpi;
mFocusTimerDuration = getResources().getInteger(R.integer.recents_auto_advance_duration);
mIterateTrigger = new DozeTrigger(mFocusTimerDuration, new Runnable() {
@Override
public void run() {
dismissRecentsToFocusedTask(MetricsEvent.OVERVIEW_SELECT_TIMEOUT);
}
});
// Set the window background
getWindow().setBackgroundDrawable(mRecentsView.getBackgroundScrim());
// Create the home intent runnable
mHomeIntent = new Intent(Intent.ACTION_MAIN, null);
mHomeIntent.addCategory(Intent.CATEGORY_HOME);
mHomeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
// ,
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.addAction(Intent.ACTION_TIME_CHANGED);
registerReceiver(mSystemBroadcastReceiver, filter);
getWindow().addPrivateFlags(LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION);
// 1.3.1 stack view
reloadStackView();
}
1.3.1 stack viewの再ロード
ファイル:RecentsActivity.java
private void reloadStackView() {
// If the Recents component has preloaded a load plan, then use that to prevent
// reconstructing the task stack
RecentsTaskLoader loader = Recents.getTaskLoader();
RecentsTaskLoadPlan loadPlan = RecentsImpl.consumeInstanceLoadPlan();
if (loadPlan == null) {
loadPlan = loader.createLoadPlan(this);
}
// Start loading tasks according to the load plan
RecentsConfiguration config = Recents.getConfiguration();
RecentsActivityLaunchState launchState = config.getLaunchState();
if (!loadPlan.hasTasks()) {
// 2,
loader.preloadTasks(loadPlan, launchState.launchedToTaskId,
!launchState.launchedFromHome);
}
RecentsTaskLoadPlan.Options loadOpts = new RecentsTaskLoadPlan.Options();
loadOpts.runningTaskId = launchState.launchedToTaskId;
loadOpts.numVisibleTasks = launchState.launchedNumVisibleTasks;
loadOpts.numVisibleTaskThumbnails = launchState.launchedNumVisibleThumbnails;
loader.loadTasks(this, loadPlan, loadOpts);
TaskStack stack = loadPlan.getTaskStack();
mRecentsView.onReload(mIsVisible, stack.getTaskCount() == 0);
mRecentsView.updateStack(stack, true /* setStackViewTasks */);
// Update the nav bar scrim, but defer the animation until the enter-window event
boolean animateNavBarScrim = !launchState.launchedViaDockGesture;
mScrimViews.updateNavBarScrim(animateNavBarScrim, stack.getTaskCount() > 0, null);
// If this is a new instance relaunched by AM, without going through the normal mechanisms,
// then we have to manually trigger the enter animation state
boolean wasLaunchedByAm = !launchState.launchedFromHome &&
!launchState.launchedFromApp;
if (wasLaunchedByAm) {
EventBus.getDefault().send(new EnterRecentsWindowAnimationCompletedEvent());
}
// Keep track of whether we launched from the nav bar button or via alt-tab
if (launchState.launchedWithAltTab) {
MetricsLogger.count(this, "overview_trigger_alttab", 1);
} else {
MetricsLogger.count(this, "overview_trigger_nav_btn", 1);
}
// Keep track of whether we launched from an app or from home
if (launchState.launchedFromApp) {
Task launchTarget = stack.getLaunchTarget();
int launchTaskIndexInStack = launchTarget != null
? stack.indexOfStackTask(launchTarget)
: 0;
MetricsLogger.count(this, "overview_source_app", 1);
// If from an app, track the stack index of the app in the stack (for affiliated tasks)
MetricsLogger.histogram(this, "overview_source_app_index", launchTaskIndexInStack);
} else {
MetricsLogger.count(this, "overview_source_home", 1);
}
// Keep track of the total stack task count
int taskCount = mRecentsView.getStack().getTaskCount();
MetricsLogger.histogram(this, "overview_task_count", taskCount);
// After we have resumed, set the visible state until the next onStop() call
mIsVisible = true;
}
もしloadPlan.hasTasks()はfalseに等しいので、preLoadTasksでTaskをロードし、次に第2の部分であるTaskの取得に入ります.