diff options
| -rw-r--r-- | core/java/android/app/Activity.java | 35 | ||||
| -rw-r--r-- | core/java/android/app/ActivityManagerNative.java | 47 | ||||
| -rw-r--r-- | core/java/android/app/IActivityManager.java | 5 | ||||
| -rw-r--r-- | core/java/android/view/Window.java | 35 | ||||
| -rw-r--r-- | core/java/com/android/internal/policy/PhoneWindow.java | 2 | ||||
| -rw-r--r-- | core/java/com/android/internal/widget/NonClientDecorView.java | 39 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/ActivityManagerService.java | 48 |
7 files changed, 197 insertions, 14 deletions
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index 84892a365041..07fa52c9b676 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -31,7 +31,7 @@ import android.transition.Scene; import android.transition.TransitionManager; import android.util.ArrayMap; import android.util.SuperNotCalledException; -import android.view.Window.WindowStackCallback; +import android.view.Window.WindowControllerCallback; import android.widget.Toolbar; import com.android.internal.app.IVoiceInteractor; @@ -60,6 +60,7 @@ import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.drawable.Drawable; +import android.graphics.Rect; import android.media.AudioManager; import android.media.session.MediaController; import android.net.Uri; @@ -673,7 +674,7 @@ public class Activity extends ContextThemeWrapper implements LayoutInflater.Factory2, Window.Callback, KeyEvent.Callback, OnCreateContextMenuListener, ComponentCallbacks2, - Window.OnWindowDismissedCallback, WindowStackCallback { + Window.OnWindowDismissedCallback, WindowControllerCallback { private static final String TAG = "Activity"; private static final boolean DEBUG_LIFECYCLE = false; @@ -2712,7 +2713,8 @@ public class Activity extends ContextThemeWrapper } - /** Called to move the window and its activity/task to a different stack container. + /** + * Called to move the window and its activity/task to a different stack container. * For example, a window can move between * {@link android.app.ActivityManager#FULLSCREEN_WORKSPACE_STACK_ID} stack and * {@link android.app.ActivityManager#FREEFORM_WORKSPACE_STACK_ID} stack. @@ -2734,6 +2736,31 @@ public class Activity extends ContextThemeWrapper } /** + * Returns the bounds of the task that contains this activity. + * + * @return Rect The bounds that contains the activity. + * @hide + */ + @Override + public Rect getActivityBounds() throws RemoteException { + return ActivityManagerNative.getDefault().getActivityBounds(mToken); + } + + /** + * Sets the bounds (size and position) of the task or stack that contains this + * activity. + * NOTE: The requested bounds might not the fully honored by the system depending + * on the window placement policy. + * + * @param newBounds The new target bounds of the activity in task or stack. + * @hide + */ + @Override + public void setActivityBounds(Rect newBounds) throws RemoteException { + ActivityManagerNative.getDefault().setActivityBounds(mToken, newBounds); + } + + /** * Called to process key events. You can override this to intercept all * key events before they are dispatched to the window. Be sure to call * this implementation for key events that should be handled normally. @@ -6211,7 +6238,7 @@ public class Activity extends ContextThemeWrapper mFragments.attachHost(null /*parent*/); mWindow = new PhoneWindow(this); - mWindow.setWindowStackCallback(this); + mWindow.setWindowControllerCallback(this); mWindow.setCallback(this); mWindow.setOnWindowDismissedCallback(this); mWindow.getLayoutInflater().setPrivateFactory(this); diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java index 10c122aa94e7..5f33344236c5 100644 --- a/core/java/android/app/ActivityManagerNative.java +++ b/core/java/android/app/ActivityManagerNative.java @@ -752,6 +752,24 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM return true; } + case GET_ACTIVITY_BOUNDS_TRANSACTION: { + data.enforceInterface(IActivityManager.descriptor); + IBinder token = data.readStrongBinder(); + Rect r = getActivityBounds(token); + reply.writeNoException(); + r.writeToParcel(reply, 0); + return true; + } + + case SET_ACTIVITY_BOUNDS_TRANSACTION: { + data.enforceInterface(IActivityManager.descriptor); + IBinder token = data.readStrongBinder(); + Rect r = Rect.CREATOR.createFromParcel(data); + setActivityBounds(token, r); + reply.writeNoException(); + return true; + } + case POSITION_TASK_IN_STACK_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); int taskId = data.readInt(); @@ -5903,6 +5921,35 @@ class ActivityManagerProxy implements IActivityManager } @Override + public void setActivityBounds(IBinder token, Rect r) throws RemoteException + { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + data.writeStrongBinder(token); + r.writeToParcel(data, 0); + mRemote.transact(SET_ACTIVITY_BOUNDS_TRANSACTION, data, reply, 0); + reply.readException(); + data.recycle(); + reply.recycle(); + } + + @Override + public Rect getActivityBounds(IBinder token) throws RemoteException + { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + data.writeStrongBinder(token); + mRemote.transact(GET_ACTIVITY_BOUNDS_TRANSACTION, data, reply, 0); + reply.readException(); + Rect rect = Rect.CREATOR.createFromParcel(reply); + data.recycle(); + reply.recycle(); + return rect; + } + + @Override public Bitmap getTaskDescriptionIcon(String filename) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java index ff1d595ae360..d3552194b78a 100644 --- a/core/java/android/app/IActivityManager.java +++ b/core/java/android/app/IActivityManager.java @@ -490,6 +490,9 @@ public interface IActivityManager extends IInterface { throws RemoteException; public void setTaskResizeable(int taskId, boolean resizeable) throws RemoteException; public void resizeTask(int taskId, Rect bounds) throws RemoteException; + public void setActivityBounds(IBinder token, Rect bounds) throws RemoteException; + public Rect getActivityBounds(IBinder token) throws RemoteException; + public Rect getTaskBounds(int taskId) throws RemoteException; public Bitmap getTaskDescriptionIcon(String filename) throws RemoteException; @@ -887,4 +890,6 @@ public interface IActivityManager extends IInterface { int GET_ACTIVITY_STACK_ID_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 343; int MOVE_ACTIVITY_TO_STACK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 344; int REPORT_SIZE_CONFIGURATIONS = IBinder.FIRST_CALL_TRANSACTION + 345; + int GET_ACTIVITY_BOUNDS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 346; + int SET_ACTIVITY_BOUNDS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 347; } diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java index eecda8956782..1a9fb34339a7 100644 --- a/core/java/android/view/Window.java +++ b/core/java/android/view/Window.java @@ -28,8 +28,9 @@ import android.content.Context; import android.content.res.Configuration; import android.content.res.Resources; import android.content.res.TypedArray; -import android.graphics.PixelFormat; import android.graphics.drawable.Drawable; +import android.graphics.PixelFormat; +import android.graphics.Rect; import android.media.session.MediaController; import android.net.Uri; import android.os.Bundle; @@ -183,7 +184,7 @@ public abstract class Window { private TypedArray mWindowStyle; private Callback mCallback; private OnWindowDismissedCallback mOnWindowDismissedCallback; - private WindowStackCallback mWindowStackCallback; + private WindowControllerCallback mWindowControllerCallback; private WindowManager mWindowManager; private IBinder mAppToken; private String mAppName; @@ -479,8 +480,9 @@ public abstract class Window { } /** @hide */ - public interface WindowStackCallback { - /** Called to move the window and its activity/task to a different stack container. + public interface WindowControllerCallback { + /** + * Called to move the window and its activity/task to a different stack container. * For example, a window can move between * {@link android.app.ActivityManager#FULLSCREEN_WORKSPACE_STACK_ID} stack and * {@link android.app.ActivityManager#FREEFORM_WORKSPACE_STACK_ID} stack. @@ -491,6 +493,23 @@ public abstract class Window { /** Returns the current stack Id for the window. */ int getWindowStackId() throws RemoteException; + + /** + * Returns the bounds of the task that contains this activity. + * + * @return Rect The bounds that contains the activity. + */ + Rect getActivityBounds() throws RemoteException; + + /** + * Sets the bounds (size and position) of the task or stack that contains this + * activity. + * NOTE: The requested bounds might not the fully honored by the system depending + * on the window placement policy. + * + * @param newBounds The new target bounds of the activity in task or stack. + */ + void setActivityBounds(Rect newBounds) throws RemoteException; } public Window(Context context) { @@ -682,13 +701,13 @@ public abstract class Window { } /** @hide */ - public final void setWindowStackCallback(WindowStackCallback wscb) { - mWindowStackCallback = wscb; + public final void setWindowControllerCallback(WindowControllerCallback wccb) { + mWindowControllerCallback = wccb; } /** @hide */ - public final WindowStackCallback getWindowStackCallback() { - return mWindowStackCallback; + public final WindowControllerCallback getWindowControllerCallback() { + return mWindowControllerCallback; } /** diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java index 6c3728236f69..33595f2b9b37 100644 --- a/core/java/com/android/internal/policy/PhoneWindow.java +++ b/core/java/com/android/internal/policy/PhoneWindow.java @@ -5199,7 +5199,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { **/ private int getWorkspaceId() { int workspaceId = FULLSCREEN_WORKSPACE_STACK_ID; - WindowStackCallback callback = getWindowStackCallback(); + WindowControllerCallback callback = getWindowControllerCallback(); if (callback != null) { try { workspaceId = callback.getWindowStackId(); diff --git a/core/java/com/android/internal/widget/NonClientDecorView.java b/core/java/com/android/internal/widget/NonClientDecorView.java index d8626cd34ff1..dd5c5d7d0b6c 100644 --- a/core/java/com/android/internal/widget/NonClientDecorView.java +++ b/core/java/com/android/internal/widget/NonClientDecorView.java @@ -17,6 +17,7 @@ package com.android.internal.widget; import android.content.Context; +import android.graphics.Rect; import android.os.RemoteException; import android.util.AttributeSet; import android.view.View; @@ -243,7 +244,7 @@ public class NonClientDecorView extends ViewGroup implements View.OnClickListene * Maximize the window by moving it to the maximized workspace stack. **/ private void maximizeWindow() { - Window.WindowStackCallback callback = mOwner.getWindowStackCallback(); + Window.WindowControllerCallback callback = mOwner.getWindowControllerCallback(); if (callback != null) { try { callback.changeWindowStack( @@ -253,4 +254,40 @@ public class NonClientDecorView extends ViewGroup implements View.OnClickListene } } } + + /** + * Returns the bounds of this activity. + * @return Returns bounds of the activity. It will return null if either the window is + * fullscreen or the bounds could not be retrieved. + */ + private Rect getActivityBounds() { + Window.WindowControllerCallback callback = mOwner.getWindowControllerCallback(); + if (callback != null) { + try { + return callback.getActivityBounds(); + } catch (RemoteException ex) { + Log.e(TAG, "Failed to get the activity bounds."); + } + } + return null; + } + + /** + * Sets the bounds of this Activity on the stack. + * @param newBounds The bounds of the activity. Passing null is not allowed. + */ + private void setActivityBounds(Rect newBounds) { + if (newBounds == null) { + Log.e(TAG, "Failed to set null bounds to the activity."); + return; + } + Window.WindowControllerCallback callback = mOwner.getWindowControllerCallback(); + if (callback != null) { + try { + callback.setActivityBounds(newBounds); + } catch (RemoteException ex) { + Log.e(TAG, "Failed to set the activity bounds."); + } + } + } } diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 2be3bf796928..19ad9308bb52 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -8639,6 +8639,54 @@ public final class ActivityManagerService extends ActivityManagerNative } @Override + public void setActivityBounds(IBinder token, Rect bounds) { + long ident = Binder.clearCallingIdentity(); + try { + synchronized (this) { + final ActivityRecord r = ActivityRecord.isInStackLocked(token); + if (r == null) { + Slog.w(TAG, "setActivityBounds: token=" + token + " not found"); + return; + } + final TaskRecord task = r.task; + if (task == null) { + Slog.e(TAG, "setActivityBounds: No TaskRecord for the ActivityRecord r=" + r); + return; + } + mStackSupervisor.resizeTaskLocked(task, bounds); + } + } finally { + Binder.restoreCallingIdentity(ident); + } + } + + @Override + public Rect getActivityBounds(IBinder token) { + long ident = Binder.clearCallingIdentity(); + Rect rect = null; + try { + synchronized (this) { + final ActivityRecord r = ActivityRecord.isInStackLocked(token); + if (r == null) { + Slog.w(TAG, "getActivityBounds: token=" + token + " not found"); + return rect; + } + final TaskRecord task = r.task; + if (task == null) { + Slog.e(TAG, "getActivityBounds: No TaskRecord for the ActivityRecord r=" + r); + return rect; + } + if (task.mBounds != null) { + rect = new Rect(task.mBounds); + } + } + } finally { + Binder.restoreCallingIdentity(ident); + } + return rect; + } + + @Override public Bitmap getTaskDescriptionIcon(String filename) { if (!FileUtils.isValidExtFilename(filename) || !filename.contains(ActivityRecord.ACTIVITY_ICON_SUFFIX)) { |