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. * Completely remove the given task.
* *
* @param taskId Identifier of the task to be removed. * @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. * @return Returns true if the given task was found and removed.
* *
* @hide * @hide
*/ */
public boolean removeTask(int taskId, int flags) public boolean removeTask(int taskId) throws SecurityException {
throws SecurityException {
try { try {
return ActivityManagerNative.getDefault().removeTask(taskId, flags); return ActivityManagerNative.getDefault().removeTask(taskId);
} catch (RemoteException e) { } catch (RemoteException e) {
// System dead, we will be dead too soon! // System dead, we will be dead too soon!
return false; return false;

View File

@ -1884,8 +1884,7 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
{ {
data.enforceInterface(IActivityManager.descriptor); data.enforceInterface(IActivityManager.descriptor);
int taskId = data.readInt(); int taskId = data.readInt();
int fl = data.readInt(); boolean result = removeTask(taskId);
boolean result = removeTask(taskId, fl);
reply.writeNoException(); reply.writeNoException();
reply.writeInt(result ? 1 : 0); reply.writeInt(result ? 1 : 0);
return true; return true;
@ -4778,12 +4777,11 @@ class ActivityManagerProxy implements IActivityManager
return result; return result;
} }
public boolean removeTask(int taskId, int flags) throws RemoteException { public boolean removeTask(int taskId) throws RemoteException {
Parcel data = Parcel.obtain(); Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain(); Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor); data.writeInterfaceToken(IActivityManager.descriptor);
data.writeInt(taskId); data.writeInt(taskId);
data.writeInt(flags);
mRemote.transact(REMOVE_TASK_TRANSACTION, data, reply, 0); mRemote.transact(REMOVE_TASK_TRANSACTION, data, reply, 0);
reply.readException(); reply.readException();
boolean result = reply.readInt() != 0; 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 boolean isUserRunning(int userid, boolean orStopping) throws RemoteException;
public int[] getRunningUserIds() 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 registerProcessObserver(IProcessObserver observer) throws RemoteException;
public void unregisterProcessObserver(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) final ActivityManager am = (ActivityManager)
getContext().getSystemService(Context.ACTIVITY_SERVICE); getContext().getSystemService(Context.ACTIVITY_SERVICE);
if (am != null) { if (am != null) {
am.removeTask(ad.persistentTaskId, ActivityManager.REMOVE_TASK_KILL_PROCESS); am.removeTask(ad.persistentTaskId);
// Accessibility feedback // Accessibility feedback
setContentDescription( setContentDescription(

View File

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

View File

@ -17,7 +17,6 @@
package com.android.systemui.recents.misc; package com.android.systemui.recents.misc;
import android.animation.Animator; import android.animation.Animator;
import android.content.Intent;
import android.graphics.Color; import android.graphics.Color;
import android.graphics.Matrix; import android.graphics.Matrix;
import android.graphics.Rect; import android.graphics.Rect;
@ -184,12 +183,6 @@ public class Utilities {
sPropertyMethod.invoke(null, property, value); 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 * Cancels an animation ensuring that if it has listeners, onCancel and onEnd
* are not called. * are not called.

View File

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

View File

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

View File

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