am d54b578e: Fix issue #17305377: Don\'t kill process if it still has tasks.

* commit 'd54b578e47fb410c776bb3a4272c2c523153f657':
  Fix issue #17305377: Don't kill process if it still has tasks.
This commit is contained in:
Wale Ogunwale
2014-11-04 19:06:11 +00:00
committed by Android Git Automerger
9 changed files with 74 additions and 92 deletions

View File

@ -1242,27 +1242,17 @@ public class ActivityManager {
}
}
/**
* If set, the process of the root activity of the task will be killed
* as part of removing the task.
* @hide
*/
public static final int REMOVE_TASK_KILL_PROCESS = 0x0001;
/**
* Completely remove the given task.
*
* @param taskId Identifier of the task to be removed.
* @param flags Additional operational flags. May be 0 or
* {@link #REMOVE_TASK_KILL_PROCESS}.
* @return Returns true if the given task was found and removed.
*
* @hide
*/
public boolean removeTask(int taskId, int flags)
throws SecurityException {
public boolean removeTask(int taskId) throws SecurityException {
try {
return ActivityManagerNative.getDefault().removeTask(taskId, flags);
return ActivityManagerNative.getDefault().removeTask(taskId);
} catch (RemoteException e) {
// System dead, we will be dead too soon!
return false;

View File

@ -1884,8 +1884,7 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
{
data.enforceInterface(IActivityManager.descriptor);
int taskId = data.readInt();
int fl = data.readInt();
boolean result = removeTask(taskId, fl);
boolean result = removeTask(taskId);
reply.writeNoException();
reply.writeInt(result ? 1 : 0);
return true;
@ -4778,12 +4777,11 @@ class ActivityManagerProxy implements IActivityManager
return result;
}
public boolean removeTask(int taskId, int flags) throws RemoteException {
public boolean removeTask(int taskId) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeInt(taskId);
data.writeInt(flags);
mRemote.transact(REMOVE_TASK_TRANSACTION, data, reply, 0);
reply.readException();
boolean result = reply.readInt() != 0;

View File

@ -373,7 +373,7 @@ public interface IActivityManager extends IInterface {
public boolean isUserRunning(int userid, boolean orStopping) throws RemoteException;
public int[] getRunningUserIds() throws RemoteException;
public boolean removeTask(int taskId, int flags) throws RemoteException;
public boolean removeTask(int taskId) throws RemoteException;
public void registerProcessObserver(IProcessObserver observer) throws RemoteException;
public void unregisterProcessObserver(IProcessObserver observer) throws RemoteException;

View File

@ -728,7 +728,7 @@ public class RecentsPanelView extends FrameLayout implements OnItemClickListener
final ActivityManager am = (ActivityManager)
getContext().getSystemService(Context.ACTIVITY_SERVICE);
if (am != null) {
am.removeTask(ad.persistentTaskId, ActivityManager.REMOVE_TASK_KILL_PROCESS);
am.removeTask(ad.persistentTaskId);
// Accessibility feedback
setContentDescription(

View File

@ -291,13 +291,13 @@ public class SystemServicesProxy {
}
}
/** Removes the task and kills the process */
public void removeTask(int taskId, boolean isDocument) {
/** Removes the task */
public void removeTask(int taskId) {
if (mAm == null) return;
if (Constants.DebugFlags.App.EnableSystemServicesProxy) return;
// Remove the task, and only kill the process if it is not a document
mAm.removeTask(taskId, isDocument ? 0 : ActivityManager.REMOVE_TASK_KILL_PROCESS);
// Remove the task.
mAm.removeTask(taskId);
}
/**

View File

@ -17,7 +17,6 @@
package com.android.systemui.recents.misc;
import android.animation.Animator;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Rect;
@ -184,12 +183,6 @@ public class Utilities {
sPropertyMethod.invoke(null, property, value);
}
/** Returns whether the specified intent is a document. */
public static boolean isDocument(Intent intent) {
int flags = intent.getFlags();
return (flags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) == Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
}
/**
* Cancels an animation ensuring that if it has listeners, onCancel and onEnd
* are not called.

View File

@ -34,7 +34,6 @@ import android.widget.FrameLayout;
import com.android.systemui.recents.Constants;
import com.android.systemui.recents.RecentsConfiguration;
import com.android.systemui.recents.misc.SystemServicesProxy;
import com.android.systemui.recents.misc.Utilities;
import com.android.systemui.recents.model.RecentsPackageMonitor;
import com.android.systemui.recents.model.RecentsTaskLoader;
import com.android.systemui.recents.model.Task;
@ -522,8 +521,7 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
loader.deleteTaskData(t, false);
// Remove the old task from activity manager
RecentsTaskLoader.getInstance().getSystemServicesProxy().removeTask(t.key.id,
Utilities.isDocument(t.key.baseIntent));
RecentsTaskLoader.getInstance().getSystemServicesProxy().removeTask(t.key.id);
}
@Override

View File

@ -1836,8 +1836,8 @@ public final class ActivityManagerService extends ActivityManagerNative
ComponentName cn = tr.intent.getComponent();
if (cn != null && cn.getPackageName().equals(packageName)) {
// If the package name matches, remove the task and kill the process
removeTaskByIdLocked(tr.taskId, ActivityManager.REMOVE_TASK_KILL_PROCESS);
// If the package name matches, remove the task
removeTaskByIdLocked(tr.taskId, true);
}
}
}
@ -1891,9 +1891,7 @@ public final class ActivityManagerService extends ActivityManagerNative
// Prune all the tasks with removed components from the list of recent tasks
synchronized (ActivityManagerService.this) {
for (int i = tasksToRemove.size() - 1; i >= 0; i--) {
// Remove the task but don't kill the process (since other components in that
// package may still be running and in the background)
removeTaskByIdLocked(tasksToRemove.get(i), 0);
removeTaskByIdLocked(tasksToRemove.get(i), false);
}
}
}
@ -4313,9 +4311,9 @@ public final class ActivityManagerService extends ActivityManagerNative
boolean res;
if (finishTask && r == rootR) {
// If requested, remove the task that is associated to this activity only if it
// was the root activity in the task. The result code and data is ignored because
// we don't support returning them across task boundaries.
res = removeTaskByIdLocked(tr.taskId, 0);
// was the root activity in the task. The result code and data is ignored
// because we don't support returning them across task boundaries.
res = removeTaskByIdLocked(tr.taskId, false);
} else {
res = tr.stack.requestFinishActivityLocked(token, resultCode,
resultData, "app-request", true);
@ -5142,7 +5140,7 @@ public final class ActivityManagerService extends ActivityManagerNative
tr.getBaseIntent().getComponent().getPackageName();
if (tr.userId != userId) continue;
if (!taskPackageName.equals(packageName)) continue;
removeTaskByIdLocked(tr.taskId, 0);
removeTaskByIdLocked(tr.taskId, false);
}
}
@ -8287,47 +8285,61 @@ public final class ActivityManagerService extends ActivityManagerNative
return mTaskPersister.getTaskDescriptionIcon(filename);
}
private void cleanUpRemovedTaskLocked(TaskRecord tr, int flags) {
private void cleanUpRemovedTaskLocked(TaskRecord tr, boolean killProcess) {
mRecentTasks.remove(tr);
tr.removedFromRecents(mTaskPersister);
final boolean killProcesses = (flags&ActivityManager.REMOVE_TASK_KILL_PROCESS) != 0;
Intent baseIntent = new Intent(
tr.intent != null ? tr.intent : tr.affinityIntent);
ComponentName component = baseIntent.getComponent();
ComponentName component = tr.getBaseIntent().getComponent();
if (component == null) {
Slog.w(TAG, "Now component for base intent of task: " + tr);
Slog.w(TAG, "No component for base intent of task: " + tr);
return;
}
// Find any running services associated with this app.
mServices.cleanUpRemovedTaskLocked(tr, component, baseIntent);
if (!killProcess) {
return;
}
if (killProcesses) {
// Find any running processes associated with this app.
// Determine if the process(es) for this task should be killed.
final String pkg = component.getPackageName();
ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
ArrayList<ProcessRecord> procsToKill = new ArrayList<ProcessRecord>();
ArrayMap<String, SparseArray<ProcessRecord>> pmap = mProcessNames.getMap();
for (int i=0; i<pmap.size(); i++) {
for (int i = 0; i < pmap.size(); i++) {
SparseArray<ProcessRecord> uids = pmap.valueAt(i);
for (int j=0; j<uids.size(); j++) {
for (int j = 0; j < uids.size(); j++) {
ProcessRecord proc = uids.valueAt(j);
if (proc.userId != tr.userId) {
// Don't kill process for a different user.
continue;
}
if (!proc.pkgList.containsKey(pkg)) {
continue;
}
procs.add(proc);
}
}
// Kill the running processes.
for (int i=0; i<procs.size(); i++) {
ProcessRecord pr = procs.get(i);
if (pr == mHomeProcess) {
if (proc == mHomeProcess) {
// Don't kill the home process along with tasks from the same package.
continue;
}
if (!proc.pkgList.containsKey(pkg)) {
// Don't kill process that is not associated with this task.
continue;
}
for (int k = 0; k < proc.activities.size(); k++) {
TaskRecord otherTask = proc.activities.get(k).task;
if (tr.taskId != otherTask.taskId && otherTask.inRecents) {
// Don't kill process(es) that has an activity in a different task that is
// also in recents.
return;
}
}
// Add process to kill list.
procsToKill.add(proc);
}
}
// Find any running services associated with this app and stop if needed.
mServices.cleanUpRemovedTaskLocked(tr, component, new Intent(tr.getBaseIntent()));
// Kill the running processes.
for (int i = 0; i < procsToKill.size(); i++) {
ProcessRecord pr = procsToKill.get(i);
if (pr.setSchedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE) {
pr.kill("remove task", true);
} else {
@ -8335,21 +8347,19 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
}
}
/**
* Removes the task with the specified task id.
*
* @param taskId Identifier of the task to be removed.
* @param flags Additional operational flags. May be 0 or
* {@link ActivityManager#REMOVE_TASK_KILL_PROCESS}.
* @param killProcess Kill any process associated with the task if possible.
* @return Returns true if the given task was found and removed.
*/
private boolean removeTaskByIdLocked(int taskId, int flags) {
private boolean removeTaskByIdLocked(int taskId, boolean killProcess) {
TaskRecord tr = recentTaskForIdLocked(taskId);
if (tr != null) {
tr.removeTaskActivitiesLocked();
cleanUpRemovedTaskLocked(tr, flags);
cleanUpRemovedTaskLocked(tr, killProcess);
if (tr.isPersistable) {
notifyTaskPersisterLocked(null, true);
}
@ -8359,13 +8369,13 @@ public final class ActivityManagerService extends ActivityManagerNative
}
@Override
public boolean removeTask(int taskId, int flags) {
public boolean removeTask(int taskId) {
synchronized (this) {
enforceCallingPermission(android.Manifest.permission.REMOVE_TASKS,
"removeTask()");
long ident = Binder.clearCallingIdentity();
try {
return removeTaskByIdLocked(taskId, flags);
return removeTaskByIdLocked(taskId, true);
} finally {
Binder.restoreCallingIdentity(ident);
}
@ -19167,16 +19177,9 @@ public final class ActivityManagerService extends ActivityManagerNative
synchronized (ActivityManagerService.this) {
long origId = Binder.clearCallingIdentity();
try {
TaskRecord tr = recentTaskForIdLocked(mTaskId);
if (tr == null) {
if (!removeTaskByIdLocked(mTaskId, false)) {
throw new IllegalArgumentException("Unable to find task ID " + mTaskId);
}
// Only kill the process if we are not a new document
int flags = tr.getBaseIntent().getFlags();
boolean isDocument = (flags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) ==
Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
removeTaskByIdLocked(mTaskId,
!isDocument ? ActivityManager.REMOVE_TASK_KILL_PROCESS : 0);
} finally {
Binder.restoreCallingIdentity(origId);
}

View File

@ -127,7 +127,7 @@ public class ActivityTestMain extends Activity {
@Override
public boolean onLongClick(View v) {
if (task.id >= 0 && thumbs != null) {
mAm.removeTask(task.id, ActivityManager.REMOVE_TASK_KILL_PROCESS);
mAm.removeTask(task.id);
buildUi();
return true;
}