diff options
author | Wale Ogunwale <ogunwale@google.com> | 2014-11-04 19:22:25 +0000 |
---|---|---|
committer | Android Git Automerger <android-git-automerger@android.com> | 2014-11-04 19:22:25 +0000 |
commit | a9868fbd7bd22a4a7cd97026ed293f889f92cf31 (patch) | |
tree | 98d44526accdaceab0fcf26a44a47597ceaaba68 | |
parent | daccecb263cad36b55dd84e25709d543ee887202 (diff) | |
parent | 2749a5e6cec41cbdc019134db6fc96e5283db9b4 (diff) | |
download | frameworks_base-a9868fbd7bd22a4a7cd97026ed293f889f92cf31.zip frameworks_base-a9868fbd7bd22a4a7cd97026ed293f889f92cf31.tar.gz frameworks_base-a9868fbd7bd22a4a7cd97026ed293f889f92cf31.tar.bz2 |
am 2749a5e6: am e54553c8: am d54b578e: Fix issue #17305377: Don\'t kill process if it still has tasks.
* commit '2749a5e6cec41cbdc019134db6fc96e5283db9b4':
Fix issue #17305377: Don't kill process if it still has tasks.
9 files changed, 74 insertions, 92 deletions
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index 37e8aa4..a285932 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -1243,26 +1243,16 @@ 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; diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java index 4e2ff0b..bc7114b 100644 --- a/core/java/android/app/ActivityManagerNative.java +++ b/core/java/android/app/ActivityManagerNative.java @@ -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; diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java index be26f30..efcb197 100644 --- a/core/java/android/app/IActivityManager.java +++ b/core/java/android/app/IActivityManager.java @@ -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; diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java index 2a782cc..4c3460e 100644 --- a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java @@ -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( diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java index 71a3ef1..b661385 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java +++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java @@ -291,18 +291,18 @@ 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); } /** * Returns the activity info for a given component name. - * + * * @param cn The component name of the activity. * @param userId The userId of the user that this is for. */ diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java b/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java index a0dee07..e1179fa 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java +++ b/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java @@ -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. diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java index 6b0d306..ff0330d 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java @@ -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 diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 9179cc4..91e2df0 100755 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -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,52 +8285,65 @@ 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. - final String pkg = component.getPackageName(); - ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>(); - ArrayMap<String, SparseArray<ProcessRecord>> pmap = mProcessNames.getMap(); - for (int i=0; i<pmap.size(); i++) { - SparseArray<ProcessRecord> uids = pmap.valueAt(i); - for (int j=0; j<uids.size(); j++) { - ProcessRecord proc = uids.valueAt(j); - if (proc.userId != tr.userId) { - continue; - } - if (!proc.pkgList.containsKey(pkg)) { - continue; - } - procs.add(proc); - } - } + // Determine if the process(es) for this task should be killed. + final String pkg = component.getPackageName(); + ArrayList<ProcessRecord> procsToKill = new ArrayList<ProcessRecord>(); + ArrayMap<String, SparseArray<ProcessRecord>> pmap = mProcessNames.getMap(); + for (int i = 0; i < pmap.size(); i++) { - // Kill the running processes. - for (int i=0; i<procs.size(); i++) { - ProcessRecord pr = procs.get(i); - if (pr == mHomeProcess) { + SparseArray<ProcessRecord> uids = pmap.valueAt(i); + 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 == mHomeProcess) { // Don't kill the home process along with tasks from the same package. continue; } - if (pr.setSchedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE) { - pr.kill("remove task", true); - } else { - pr.waitingToKill = "remove task"; + 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 { + pr.waitingToKill = "remove task"; } } } @@ -8341,15 +8352,14 @@ 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,19 +8369,19 @@ 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); } } } - + /** * TODO: Add mController hook */ @@ -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); } diff --git a/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java b/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java index 6837d22..94874c8 100644 --- a/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java +++ b/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java @@ -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; } |