* commit 'd54b578e47fb410c776bb3a4272c2c523153f657': Fix issue #17305377: Don't kill process if it still has tasks.
This commit is contained in:
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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(
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
Reference in New Issue
Block a user