diff options
| -rw-r--r-- | api/current.txt | 1 | ||||
| -rw-r--r-- | core/java/android/app/Activity.java | 26 | ||||
| -rw-r--r-- | core/java/android/app/ActivityManagerNative.java | 6 | ||||
| -rw-r--r-- | core/java/android/app/ActivityThread.java | 4 | ||||
| -rw-r--r-- | core/java/android/app/IActivityManager.java | 2 | ||||
| -rw-r--r-- | core/java/android/util/Patterns.java | 5 | ||||
| -rw-r--r-- | libs/hwui/RenderNode.cpp | 7 | ||||
| -rw-r--r-- | libs/hwui/RenderProperties.cpp | 13 | ||||
| -rw-r--r-- | libs/hwui/utils/MathUtils.h | 37 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/ActivityManagerService.java | 65 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/TaskRecord.java | 20 |
11 files changed, 134 insertions, 52 deletions
diff --git a/api/current.txt b/api/current.txt index 08eee23..ef6aed7 100644 --- a/api/current.txt +++ b/api/current.txt @@ -3175,6 +3175,7 @@ package android.app { method public void finishActivity(int); method public void finishActivityFromChild(android.app.Activity, int); method public void finishAffinity(); + method public void finishAndRemoveTask(); method public void finishFromChild(android.app.Activity); method public void finishWithTransition(); method public android.app.ActionBar getActionBar(); diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index a5a06e3..599a608 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -4314,11 +4314,10 @@ public class Activity extends ContextThemeWrapper } /** - * Call this when your activity is done and should be closed. The - * ActivityResult is propagated back to whoever launched you via - * onActivityResult(). + * Finishes the current activity and specifies whether to remove the task associated with this + * activity. */ - public void finish() { + private void finish(boolean finishTask) { if (mParent == null) { int resultCode; Intent resultData; @@ -4332,7 +4331,7 @@ public class Activity extends ContextThemeWrapper resultData.prepareToLeaveProcess(); } if (ActivityManagerNative.getDefault() - .finishActivity(mToken, resultCode, resultData)) { + .finishActivity(mToken, resultCode, resultData, finishTask)) { mFinished = true; } } catch (RemoteException e) { @@ -4344,6 +4343,15 @@ public class Activity extends ContextThemeWrapper } /** + * Call this when your activity is done and should be closed. The + * ActivityResult is propagated back to whoever launched you via + * onActivityResult(). + */ + public void finish() { + finish(false); + } + + /** * Finish this activity as well as all activities immediately below it * in the current task that have the same affinity. This is typically * used when an application can be launched on to another task (such as @@ -4442,6 +4450,14 @@ public class Activity extends ContextThemeWrapper } /** + * Call this when your activity is done and should be closed and the task should be completely + * removed as a part of finishing the Activity. + */ + public void finishAndRemoveTask() { + finish(true); + } + + /** * Called when an activity you launched exits, giving you the requestCode * you started it with, the resultCode it returned, and any additional * data from it. The <var>resultCode</var> will be diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java index 44c74d8..10831f2 100644 --- a/core/java/android/app/ActivityManagerNative.java +++ b/core/java/android/app/ActivityManagerNative.java @@ -263,7 +263,8 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM if (data.readInt() != 0) { resultData = Intent.CREATOR.createFromParcel(data); } - boolean res = finishActivity(token, resultCode, resultData); + boolean finishTask = (data.readInt() != 0); + boolean res = finishActivity(token, resultCode, resultData, finishTask); reply.writeNoException(); reply.writeInt(res ? 1 : 0); return true; @@ -2342,7 +2343,7 @@ class ActivityManagerProxy implements IActivityManager data.recycle(); return result != 0; } - public boolean finishActivity(IBinder token, int resultCode, Intent resultData) + public boolean finishActivity(IBinder token, int resultCode, Intent resultData, boolean finishTask) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); @@ -2355,6 +2356,7 @@ class ActivityManagerProxy implements IActivityManager } else { data.writeInt(0); } + data.writeInt(finishTask ? 1 : 0); mRemote.transact(FINISH_ACTIVITY_TRANSACTION, data, reply, 0); reply.readException(); boolean res = reply.readInt() != 0; diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 965f815..88eae7f 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -2363,7 +2363,7 @@ public final class ActivityThread { // manager to stop us. try { ActivityManagerNative.getDefault() - .finishActivity(r.token, Activity.RESULT_CANCELED, null); + .finishActivity(r.token, Activity.RESULT_CANCELED, null, false); } catch (RemoteException ex) { // Ignore } @@ -2984,7 +2984,7 @@ public final class ActivityThread { // just end this activity. try { ActivityManagerNative.getDefault() - .finishActivity(token, Activity.RESULT_CANCELED, null); + .finishActivity(token, Activity.RESULT_CANCELED, null, false); } catch (RemoteException ex) { } } diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java index bfbd339..52003f1 100644 --- a/core/java/android/app/IActivityManager.java +++ b/core/java/android/app/IActivityManager.java @@ -79,7 +79,7 @@ public interface IActivityManager extends IInterface { int flagsMask, int flagsValues, Bundle options) throws RemoteException; public boolean startNextMatchingActivity(IBinder callingActivity, Intent intent, Bundle options) throws RemoteException; - public boolean finishActivity(IBinder token, int code, Intent data) + public boolean finishActivity(IBinder token, int code, Intent data, boolean finishTask) throws RemoteException; public void finishSubActivity(IBinder token, String resultWho, int requestCode) throws RemoteException; public boolean finishActivityAffinity(IBinder token) throws RemoteException; diff --git a/core/java/android/util/Patterns.java b/core/java/android/util/Patterns.java index 13cc88b..2cc91b9 100644 --- a/core/java/android/util/Patterns.java +++ b/core/java/android/util/Patterns.java @@ -130,7 +130,10 @@ public class Patterns { private static final String IRI = "[" + GOOD_IRI_CHAR + "]([" + GOOD_IRI_CHAR + "\\-]{0,61}[" + GOOD_IRI_CHAR + "]){0,1}"; - private static final String HOST_NAME = IRI + "(?:\\." + IRI + ")+"; + private static final String GOOD_GTLD_CHAR = + "a-zA-Z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF"; + private static final String GTLD = "[" + GOOD_GTLD_CHAR + "]{2,63}"; + private static final String HOST_NAME = "(" + IRI + "\\.)+" + GTLD; public static final Pattern DOMAIN_NAME = Pattern.compile("(" + HOST_NAME + "|" + IP_ADDRESS + ")"); diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp index cf21834..9aa47a3 100644 --- a/libs/hwui/RenderNode.cpp +++ b/libs/hwui/RenderNode.cpp @@ -26,6 +26,7 @@ #include "Debug.h" #include "DisplayListOp.h" #include "DisplayListLogBuffer.h" +#include "utils/MathUtils.h" namespace android { namespace uirenderer { @@ -217,7 +218,9 @@ void RenderNode::applyViewPropertyTransforms(mat4& matrix, bool true3dTransform) mat4 anim(*properties().getAnimationMatrix()); matrix.multiply(anim); } - if (properties().hasTransformMatrix()) { + + bool applyTranslationZ = true3dTransform && !MathUtils::isZero(properties().getTranslationZ()); + if (properties().hasTransformMatrix() || applyTranslationZ) { if (properties().isTransformTranslateOnly()) { matrix.translate(properties().getTranslationX(), properties().getTranslationY(), true3dTransform ? properties().getTranslationZ() : 0.0f); @@ -391,7 +394,7 @@ void RenderNode::buildZSortedChildList(Vector<ZDrawDisplayListOpPair>& zTranslat RenderNode* child = childOp->mDisplayList; float childZ = child->properties().getTranslationZ(); - if (childZ != 0.0f) { + if (!MathUtils::isZero(childZ)) { zTranslatedNodes.add(ZDrawDisplayListOpPair(childZ, childOp)); childOp->mSkipInOrderDraw = true; } else if (!child->properties().getProjectBackwards()) { diff --git a/libs/hwui/RenderProperties.cpp b/libs/hwui/RenderProperties.cpp index 58ec32d..a922db8 100644 --- a/libs/hwui/RenderProperties.cpp +++ b/libs/hwui/RenderProperties.cpp @@ -26,16 +26,7 @@ #include <SkPathOps.h> #include "Matrix.h" - -/** - * Convenience value to check for float values that are close enough to zero to be considered - * zero. - */ -#define NONZERO_EPSILON .001f - -static inline bool is_zero(float value) { - return (value >= -NONZERO_EPSILON) && (value <= NONZERO_EPSILON); -} +#include "utils/MathUtils.h" namespace android { namespace uirenderer { @@ -151,7 +142,7 @@ void RenderProperties::updateMatrix() { } SkMatrix* transform = mComputedFields.mTransformMatrix; transform->reset(); - if (is_zero(getRotationX()) && is_zero(getRotationY())) { + if (MathUtils::isZero(getRotationX()) && MathUtils::isZero(getRotationY())) { transform->setTranslate(getTranslationX(), getTranslationY()); transform->preRotate(getRotation(), getPivotX(), getPivotY()); transform->preScale(getScaleX(), getScaleY(), getPivotX(), getPivotY()); diff --git a/libs/hwui/utils/MathUtils.h b/libs/hwui/utils/MathUtils.h new file mode 100644 index 0000000..57ba8fa --- /dev/null +++ b/libs/hwui/utils/MathUtils.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MATHUTILS_H +#define MATHUTILS_H + +namespace android { +namespace uirenderer { + +class MathUtils { +private: + static const float gNonZeroEpsilon = 0.001f; +public: + /** + * Check for floats that are close enough to zero. + */ + inline static bool isZero(float value) { + return (value >= -gNonZeroEpsilon) && (value <= gNonZeroEpsilon); + } +}; // class MathUtils + +} /* namespace uirenderer */ +} /* namespace android */ + +#endif /* RENDERNODE_H */ diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 51296c1..8fa076b 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -3453,11 +3453,14 @@ public final class ActivityManagerService extends ActivityManagerNative * @param token The Binder token referencing the Activity we want to finish. * @param resultCode Result code, if any, from this Activity. * @param resultData Result data (Intent), if any, from this Activity. + * @param finishTask Whether to finish the task associated with this Activity. Only applies to + * the root Activity in the task. * * @return Returns true if the activity successfully finished, or false if it is still running. */ @Override - public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) { + public final boolean finishActivity(IBinder token, int resultCode, Intent resultData, + boolean finishTask) { // Refuse possible leaked file descriptors if (resultData != null && resultData.hasFileDescriptors() == true) { throw new IllegalArgumentException("File descriptors passed in Intent"); @@ -3468,6 +3471,9 @@ public final class ActivityManagerService extends ActivityManagerNative if (r == null) { return true; } + // Keep track of the root activity of the task before we finish it + TaskRecord tr = r.task; + ActivityRecord rootR = tr.getRootActivity(); if (mController != null) { // Find the first activity that is not finishing. ActivityRecord next = r.task.stack.topRunningActivityLocked(token, 0); @@ -3487,10 +3493,21 @@ public final class ActivityManagerService extends ActivityManagerNative } } final long origId = Binder.clearCallingIdentity(); - boolean res = r.task.stack.requestFinishActivityLocked(token, resultCode, - resultData, "app-request", true); - Binder.restoreCallingIdentity(origId); - return res; + try { + 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); + } else { + res = tr.stack.requestFinishActivityLocked(token, resultCode, + resultData, "app-request", true); + } + return res; + } finally { + Binder.restoreCallingIdentity(origId); + } } } @@ -7144,6 +7161,24 @@ 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}. + * @return Returns true if the given task was found and removed. + */ + private boolean removeTaskByIdLocked(int taskId, int flags) { + TaskRecord tr = recentTaskForIdLocked(taskId); + if (tr != null) { + tr.removeTaskActivitiesLocked(-1, false); + cleanUpRemovedTaskLocked(tr, flags); + return true; + } + return false; + } + @Override public boolean removeTask(int taskId, int flags) { synchronized (this) { @@ -7151,29 +7186,11 @@ public final class ActivityManagerService extends ActivityManagerNative "removeTask()"); long ident = Binder.clearCallingIdentity(); try { - TaskRecord tr = recentTaskForIdLocked(taskId); - if (tr != null) { - ActivityRecord r = tr.removeTaskActivitiesLocked(-1, false); - if (r != null) { - cleanUpRemovedTaskLocked(tr, flags); - return true; - } - if (tr.mActivities.size() == 0) { - // Caller is just removing a recent task that is - // not actively running. That is easy! - cleanUpRemovedTaskLocked(tr, flags); - return true; - } - Slog.w(TAG, "removeTask: task " + taskId - + " does not have activities to remove, " - + " but numActivities=" + tr.numActivities - + ": " + tr); - } + return removeTaskByIdLocked(taskId, flags); } finally { Binder.restoreCallingIdentity(ident); } } - return false; } /** diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java index 3a43521..80a219d 100644 --- a/services/core/java/com/android/server/am/TaskRecord.java +++ b/services/core/java/com/android/server/am/TaskRecord.java @@ -139,6 +139,18 @@ final class TaskRecord extends ThumbnailHolder { } } + /** Returns the first non-finishing activity from the root. */ + ActivityRecord getRootActivity() { + for (int i = 0; i < mActivities.size(); i++) { + final ActivityRecord r = mActivities.get(i); + if (r.finishing) { + continue; + } + return r; + } + return null; + } + ActivityRecord getTopActivity() { for (int i = mActivities.size() - 1; i >= 0; --i) { final ActivityRecord r = mActivities.get(i); @@ -305,7 +317,7 @@ final class TaskRecord extends ThumbnailHolder { } public ActivityManager.TaskThumbnails getTaskThumbnailsLocked() { - TaskAccessInfo info = getTaskAccessInfoLocked(true); + TaskAccessInfo info = getTaskAccessInfoLocked(); final ActivityRecord resumedActivity = stack.mResumedActivity; if (resumedActivity != null && resumedActivity.thumbHolder == this) { info.mainThumbnail = stack.screenshotActivities(resumedActivity); @@ -325,7 +337,7 @@ final class TaskRecord extends ThumbnailHolder { } // Return the information about the task, to figure out the top // thumbnail to return. - TaskAccessInfo info = getTaskAccessInfoLocked(true); + TaskAccessInfo info = getTaskAccessInfoLocked(); if (info.numSubThumbbails <= 0) { return info.mainThumbnail != null ? info.mainThumbnail : lastThumbnail; } @@ -334,7 +346,7 @@ final class TaskRecord extends ThumbnailHolder { public ActivityRecord removeTaskActivitiesLocked(int subTaskIndex, boolean taskRequired) { - TaskAccessInfo info = getTaskAccessInfoLocked(false); + TaskAccessInfo info = getTaskAccessInfoLocked(); if (info.root == null) { if (taskRequired) { Slog.w(TAG, "removeTaskLocked: unknown taskId " + taskId); @@ -369,7 +381,7 @@ final class TaskRecord extends ThumbnailHolder { return mTaskType == ActivityRecord.APPLICATION_ACTIVITY_TYPE; } - public TaskAccessInfo getTaskAccessInfoLocked(boolean inclThumbs) { + public TaskAccessInfo getTaskAccessInfoLocked() { final TaskAccessInfo thumbs = new TaskAccessInfo(); // How many different sub-thumbnails? final int NA = mActivities.size(); |
