* 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.
|
* 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;
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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(
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -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.
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user