summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Android.mk3
-rw-r--r--CleanSpec.mk5
-rw-r--r--api/current.txt1
-rw-r--r--core/java/android/accessibilityservice/AccessibilityService.java9
-rw-r--r--core/java/android/accessibilityservice/IAccessibilityServiceClient.aidl2
-rw-r--r--core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl21
-rw-r--r--core/java/android/view/AccessibilityInteractionController.java120
-rw-r--r--core/java/android/view/IDisplayMagnificationController.aidl (renamed from core/java/android/view/IDisplayContentChangeListener.aidl)16
-rw-r--r--core/java/android/view/IDisplayMagnificationMediator.aidl31
-rw-r--r--core/java/android/view/IWindowManager.aidl32
-rw-r--r--core/java/android/view/MagnificationSpec.aidl (renamed from core/java/android/view/WindowInfo.aidl)2
-rw-r--r--core/java/android/view/MagnificationSpec.java120
-rw-r--r--core/java/android/view/Surface.java26
-rw-r--r--core/java/android/view/ViewRootImpl.java23
-rw-r--r--core/java/android/view/WindowInfo.java175
-rw-r--r--core/java/android/view/WindowManagerPolicy.java8
-rw-r--r--core/java/android/view/accessibility/AccessibilityInteractionClient.java73
-rw-r--r--core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl11
-rw-r--r--core/java/com/android/internal/policy/PolicyManager.java2
-rw-r--r--policy/src/com/android/internal/policy/impl/PhoneWindowManager.java78
-rw-r--r--policy/src/com/android/internal/policy/impl/Policy.java3
-rw-r--r--services/java/com/android/server/accessibility/AccessibilityInputFilter.java4
-rw-r--r--services/java/com/android/server/accessibility/AccessibilityManagerService.java153
-rw-r--r--services/java/com/android/server/accessibility/ScreenMagnifier.java1331
-rw-r--r--services/java/com/android/server/wm/DisplayContent.java11
-rw-r--r--services/java/com/android/server/wm/DisplayMagnificationMediator.java616
-rw-r--r--services/java/com/android/server/wm/MagnificationSpec.java46
-rw-r--r--services/java/com/android/server/wm/WindowManagerService.java371
-rw-r--r--services/java/com/android/server/wm/WindowState.java15
-rw-r--r--services/java/com/android/server/wm/WindowStateAnimator.java23
-rw-r--r--tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java34
31 files changed, 1675 insertions, 1690 deletions
diff --git a/Android.mk b/Android.mk
index f338fa1e..dc45b1c 100644
--- a/Android.mk
+++ b/Android.mk
@@ -154,7 +154,8 @@ LOCAL_SRC_FILES += \
core/java/android/view/accessibility/IAccessibilityManager.aidl \
core/java/android/view/accessibility/IAccessibilityManagerClient.aidl \
core/java/android/view/IApplicationToken.aidl \
- core/java/android/view/IDisplayContentChangeListener.aidl \
+ core/java/android/view/IDisplayMagnificationMediator.aidl \
+ core/java/android/view/IDisplayMagnificationController.aidl \
core/java/android/view/IInputFilter.aidl \
core/java/android/view/IInputFilterHost.aidl \
core/java/android/view/IOnKeyguardExitResult.aidl \
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 01d09f6..425794a 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -141,6 +141,11 @@ $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/media/audio/ui/*.ogg)
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/telephony/java/com/android/internal/telephony/IExtendedNetworkService.java)
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/telephony/java/com/android/internal/telephony/IExtendedNetworkService.P)
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/ImageProcessing_intermediates)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/view/IDisplayContentChangeListener.java)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/view/IDisplayContentChangeListener.P)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/view/IWindowManager.java)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/view/IWindowManager.P)
+
# ************************************************
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
# ************************************************
diff --git a/api/current.txt b/api/current.txt
index 454e5da..2be13a0 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -24746,6 +24746,7 @@ package android.view {
method public android.graphics.Canvas lockCanvas(android.graphics.Rect) throws java.lang.IllegalArgumentException, android.view.Surface.OutOfResourcesException;
method public void readFromParcel(android.os.Parcel);
method public void release();
+ method public static java.lang.String rotationToString(int);
method public deprecated void unlockCanvas(android.graphics.Canvas);
method public void unlockCanvasAndPost(android.graphics.Canvas);
method public void writeToParcel(android.os.Parcel, int);
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index b0bad07..ecf3b19 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -548,6 +548,7 @@ public abstract class AccessibilityService extends Service {
private static final int DO_ON_INTERRUPT = 20;
private static final int DO_ON_ACCESSIBILITY_EVENT = 30;
private static final int DO_ON_GESTURE = 40;
+ private static final int DO_CLEAR_ACCESSIBILITY_NODE_INFO_CACHE = 50;
private final HandlerCaller mCaller;
@@ -580,6 +581,11 @@ public abstract class AccessibilityService extends Service {
mCaller.sendMessage(message);
}
+ public void clearAccessibilityNodeInfoCache() {
+ Message message = mCaller.obtainMessage(DO_CLEAR_ACCESSIBILITY_NODE_INFO_CACHE);
+ mCaller.sendMessage(message);
+ }
+
public void executeMessage(Message message) {
switch (message.what) {
case DO_ON_ACCESSIBILITY_EVENT :
@@ -611,6 +617,9 @@ public abstract class AccessibilityService extends Service {
final int gestureId = message.arg1;
mCallback.onGesture(gestureId);
return;
+ case DO_CLEAR_ACCESSIBILITY_NODE_INFO_CACHE:
+ AccessibilityInteractionClient.getInstance().clearCache();
+ return;
default :
Log.w(LOG_TAG, "Unknown message type " + message.what);
}
diff --git a/core/java/android/accessibilityservice/IAccessibilityServiceClient.aidl b/core/java/android/accessibilityservice/IAccessibilityServiceClient.aidl
index d459fd5..5d684e3 100644
--- a/core/java/android/accessibilityservice/IAccessibilityServiceClient.aidl
+++ b/core/java/android/accessibilityservice/IAccessibilityServiceClient.aidl
@@ -33,4 +33,6 @@ import android.view.accessibility.AccessibilityEvent;
void onInterrupt();
void onGesture(int gesture);
+
+ void clearAccessibilityNodeInfoCache();
}
diff --git a/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
index dd50f3c..f33f503 100644
--- a/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
+++ b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
@@ -18,6 +18,7 @@ package android.accessibilityservice;
import android.os.Bundle;
import android.accessibilityservice.AccessibilityServiceInfo;
+import android.view.MagnificationSpec;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.IAccessibilityInteractionConnectionCallback;
@@ -44,9 +45,9 @@ interface IAccessibilityServiceConnection {
* @param callback Callback which to receive the result.
* @param flags Additional flags.
* @param threadId The id of the calling thread.
- * @return The current window scale, where zero means a failure.
+ * @return Whether the call succeeded.
*/
- float findAccessibilityNodeInfoByAccessibilityId(int accessibilityWindowId,
+ boolean findAccessibilityNodeInfoByAccessibilityId(int accessibilityWindowId,
long accessibilityNodeId, int interactionId,
IAccessibilityInteractionConnectionCallback callback, int flags, long threadId);
@@ -66,9 +67,9 @@ interface IAccessibilityServiceConnection {
* @param interactionId The id of the interaction for matching with the callback result.
* @param callback Callback which to receive the result.
* @param threadId The id of the calling thread.
- * @return The current window scale, where zero means a failure.
+ * @return Whether the call succeeded.
*/
- float findAccessibilityNodeInfosByText(int accessibilityWindowId, long accessibilityNodeId,
+ boolean findAccessibilityNodeInfosByText(int accessibilityWindowId, long accessibilityNodeId,
String text, int interactionId, IAccessibilityInteractionConnectionCallback callback,
long threadId);
@@ -88,9 +89,9 @@ interface IAccessibilityServiceConnection {
* @param interactionId The id of the interaction for matching with the callback result.
* @param callback Callback which to receive the result.
* @param threadId The id of the calling thread.
- * @return The current window scale, where zero means a failure.
+ * @return Whether the call succeeded.
*/
- float findAccessibilityNodeInfoByViewId(int accessibilityWindowId, long accessibilityNodeId,
+ boolean findAccessibilityNodeInfoByViewId(int accessibilityWindowId, long accessibilityNodeId,
int viewId, int interactionId, IAccessibilityInteractionConnectionCallback callback,
long threadId);
@@ -110,9 +111,9 @@ interface IAccessibilityServiceConnection {
* @param interactionId The id of the interaction for matching with the callback result.
* @param callback Callback which to receive the result.
* @param threadId The id of the calling thread.
- * @return The current window scale, where zero means a failure.
+ * @return Whether the call succeeded.
*/
- float findFocus(int accessibilityWindowId, long accessibilityNodeId, int focusType,
+ boolean findFocus(int accessibilityWindowId, long accessibilityNodeId, int focusType,
int interactionId, IAccessibilityInteractionConnectionCallback callback, long threadId);
/**
@@ -131,9 +132,9 @@ interface IAccessibilityServiceConnection {
* @param interactionId The id of the interaction for matching with the callback result.
* @param callback Callback which to receive the result.
* @param threadId The id of the calling thread.
- * @return The current window scale, where zero means a failure.
+ * @return Whether the call succeeded.
*/
- float focusSearch(int accessibilityWindowId, long accessibilityNodeId, int direction,
+ boolean focusSearch(int accessibilityWindowId, long accessibilityNodeId, int direction,
int interactionId, IAccessibilityInteractionConnectionCallback callback, long threadId);
/**
diff --git a/core/java/android/view/AccessibilityInteractionController.java b/core/java/android/view/AccessibilityInteractionController.java
index 9bee4bf..ba82d79 100644
--- a/core/java/android/view/AccessibilityInteractionController.java
+++ b/core/java/android/view/AccessibilityInteractionController.java
@@ -18,6 +18,7 @@ package android.view;
import static android.view.accessibility.AccessibilityNodeInfo.INCLUDE_NOT_IMPORTANT_VIEWS;
+import android.graphics.Point;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.Handler;
@@ -26,6 +27,7 @@ import android.os.Message;
import android.os.Process;
import android.os.RemoteException;
import android.util.SparseLongArray;
+import android.view.View.AttachInfo;
import android.view.accessibility.AccessibilityInteractionClient;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.AccessibilityNodeProvider;
@@ -62,7 +64,10 @@ final class AccessibilityInteractionController {
private final ArrayList<View> mTempArrayList = new ArrayList<View>();
+ private final Point mTempPoint = new Point();
private final Rect mTempRect = new Rect();
+ private final Rect mTempRect1 = new Rect();
+ private final Rect mTempRect2 = new Rect();
public AccessibilityInteractionController(ViewRootImpl viewRootImpl) {
Looper looper = viewRootImpl.mHandler.getLooper();
@@ -86,7 +91,7 @@ final class AccessibilityInteractionController {
public void findAccessibilityNodeInfoByAccessibilityIdClientThread(
long accessibilityNodeId, int interactionId,
IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid,
- long interrogatingTid) {
+ long interrogatingTid, MagnificationSpec spec) {
Message message = mHandler.obtainMessage();
message.what = PrivateHandler.MSG_FIND_ACCESSIBLITY_NODE_INFO_BY_ACCESSIBILITY_ID;
message.arg1 = flags;
@@ -96,6 +101,7 @@ final class AccessibilityInteractionController {
args.argi2 = AccessibilityNodeInfo.getVirtualDescendantId(accessibilityNodeId);
args.argi3 = interactionId;
args.arg1 = callback;
+ args.arg2 = spec;
message.obj = args;
// If the interrogation is performed by the same thread as the main UI
@@ -119,6 +125,7 @@ final class AccessibilityInteractionController {
final int interactionId = args.argi3;
final IAccessibilityInteractionConnectionCallback callback =
(IAccessibilityInteractionConnectionCallback) args.arg1;
+ final MagnificationSpec spec = (MagnificationSpec) args.arg2;
args.recycle();
@@ -142,7 +149,10 @@ final class AccessibilityInteractionController {
} finally {
try {
mViewRootImpl.mAttachInfo.mIncludeNotImportantViews = false;
- applyApplicationScaleIfNeeded(infos);
+ applyAppScaleAndMagnificationSpecIfNeeded(infos, spec);
+ if (spec != null) {
+ spec.recycle();
+ }
callback.setFindAccessibilityNodeInfosResult(infos, interactionId);
infos.clear();
} catch (RemoteException re) {
@@ -153,7 +163,7 @@ final class AccessibilityInteractionController {
public void findAccessibilityNodeInfoByViewIdClientThread(long accessibilityNodeId,
int viewId, int interactionId, IAccessibilityInteractionConnectionCallback callback,
- int flags, int interrogatingPid, long interrogatingTid) {
+ int flags, int interrogatingPid, long interrogatingTid, MagnificationSpec spec) {
Message message = mHandler.obtainMessage();
message.what = PrivateHandler.MSG_FIND_ACCESSIBLITY_NODE_INFO_BY_VIEW_ID;
message.arg1 = flags;
@@ -163,6 +173,7 @@ final class AccessibilityInteractionController {
args.argi1 = viewId;
args.argi2 = interactionId;
args.arg1 = callback;
+ args.arg2 = spec;
message.obj = args;
@@ -187,6 +198,7 @@ final class AccessibilityInteractionController {
final int interactionId = args.argi2;
final IAccessibilityInteractionConnectionCallback callback =
(IAccessibilityInteractionConnectionCallback) args.arg1;
+ final MagnificationSpec spec = (MagnificationSpec) args.arg2;
args.recycle();
@@ -212,7 +224,10 @@ final class AccessibilityInteractionController {
} finally {
try {
mViewRootImpl.mAttachInfo.mIncludeNotImportantViews = false;
- applyApplicationScaleIfNeeded(info);
+ applyAppScaleAndMagnificationSpecIfNeeded(info, spec);
+ if (spec != null) {
+ spec.recycle();
+ }
callback.setFindAccessibilityNodeInfoResult(info, interactionId);
} catch (RemoteException re) {
/* ignore - the other side will time out */
@@ -222,7 +237,7 @@ final class AccessibilityInteractionController {
public void findAccessibilityNodeInfosByTextClientThread(long accessibilityNodeId,
String text, int interactionId, IAccessibilityInteractionConnectionCallback callback,
- int flags, int interrogatingPid, long interrogatingTid) {
+ int flags, int interrogatingPid, long interrogatingTid, MagnificationSpec spec) {
Message message = mHandler.obtainMessage();
message.what = PrivateHandler.MSG_FIND_ACCESSIBLITY_NODE_INFO_BY_TEXT;
message.arg1 = flags;
@@ -230,10 +245,10 @@ final class AccessibilityInteractionController {
SomeArgs args = SomeArgs.obtain();
args.arg1 = text;
args.arg2 = callback;
+ args.arg3 = spec;
args.argi1 = AccessibilityNodeInfo.getAccessibilityViewId(accessibilityNodeId);
args.argi2 = AccessibilityNodeInfo.getVirtualDescendantId(accessibilityNodeId);
args.argi3 = interactionId;
-
message.obj = args;
// If the interrogation is performed by the same thread as the main UI
@@ -255,6 +270,7 @@ final class AccessibilityInteractionController {
final String text = (String) args.arg1;
final IAccessibilityInteractionConnectionCallback callback =
(IAccessibilityInteractionConnectionCallback) args.arg2;
+ final MagnificationSpec spec = (MagnificationSpec) args.arg3;
final int accessibilityViewId = args.argi1;
final int virtualDescendantId = args.argi2;
final int interactionId = args.argi3;
@@ -310,7 +326,10 @@ final class AccessibilityInteractionController {
} finally {
try {
mViewRootImpl.mAttachInfo.mIncludeNotImportantViews = false;
- applyApplicationScaleIfNeeded(infos);
+ applyAppScaleAndMagnificationSpecIfNeeded(infos, spec);
+ if (spec != null) {
+ spec.recycle();
+ }
callback.setFindAccessibilityNodeInfosResult(infos, interactionId);
} catch (RemoteException re) {
/* ignore - the other side will time out */
@@ -320,7 +339,7 @@ final class AccessibilityInteractionController {
public void findFocusClientThread(long accessibilityNodeId, int focusType, int interactionId,
IAccessibilityInteractionConnectionCallback callback, int flags, int interogatingPid,
- long interrogatingTid) {
+ long interrogatingTid, MagnificationSpec spec) {
Message message = mHandler.obtainMessage();
message.what = PrivateHandler.MSG_FIND_FOCUS;
message.arg1 = flags;
@@ -331,6 +350,7 @@ final class AccessibilityInteractionController {
args.argi2 = AccessibilityNodeInfo.getAccessibilityViewId(accessibilityNodeId);
args.argi3 = AccessibilityNodeInfo.getVirtualDescendantId(accessibilityNodeId);
args.arg1 = callback;
+ args.arg2 = spec;
message.obj = args;
@@ -356,7 +376,7 @@ final class AccessibilityInteractionController {
final int virtualDescendantId = args.argi3;
final IAccessibilityInteractionConnectionCallback callback =
(IAccessibilityInteractionConnectionCallback) args.arg1;
-
+ final MagnificationSpec spec = (MagnificationSpec) args.arg2;
args.recycle();
AccessibilityNodeInfo focused = null;
@@ -407,7 +427,10 @@ final class AccessibilityInteractionController {
} finally {
try {
mViewRootImpl.mAttachInfo.mIncludeNotImportantViews = false;
- applyApplicationScaleIfNeeded(focused);
+ applyAppScaleAndMagnificationSpecIfNeeded(focused, spec);
+ if (spec != null) {
+ spec.recycle();
+ }
callback.setFindAccessibilityNodeInfoResult(focused, interactionId);
} catch (RemoteException re) {
/* ignore - the other side will time out */
@@ -417,7 +440,7 @@ final class AccessibilityInteractionController {
public void focusSearchClientThread(long accessibilityNodeId, int direction, int interactionId,
IAccessibilityInteractionConnectionCallback callback, int flags, int interogatingPid,
- long interrogatingTid) {
+ long interrogatingTid, MagnificationSpec spec) {
Message message = mHandler.obtainMessage();
message.what = PrivateHandler.MSG_FOCUS_SEARCH;
message.arg1 = flags;
@@ -427,6 +450,7 @@ final class AccessibilityInteractionController {
args.argi2 = direction;
args.argi3 = interactionId;
args.arg1 = callback;
+ args.arg2 = spec;
message.obj = args;
@@ -451,6 +475,7 @@ final class AccessibilityInteractionController {
final int interactionId = args.argi3;
final IAccessibilityInteractionConnectionCallback callback =
(IAccessibilityInteractionConnectionCallback) args.arg1;
+ final MagnificationSpec spec = (MagnificationSpec) args.arg2;
args.recycle();
@@ -476,7 +501,10 @@ final class AccessibilityInteractionController {
} finally {
try {
mViewRootImpl.mAttachInfo.mIncludeNotImportantViews = false;
- applyApplicationScaleIfNeeded(next);
+ applyAppScaleAndMagnificationSpecIfNeeded(next, spec);
+ if (spec != null) {
+ spec.recycle();
+ }
callback.setFindAccessibilityNodeInfoResult(next, interactionId);
} catch (RemoteException re) {
/* ignore - the other side will time out */
@@ -572,38 +600,84 @@ final class AccessibilityInteractionController {
return foundView;
}
- private void applyApplicationScaleIfNeeded(List<AccessibilityNodeInfo> infos) {
+ private void applyAppScaleAndMagnificationSpecIfNeeded(List<AccessibilityNodeInfo> infos,
+ MagnificationSpec spec) {
if (infos == null) {
return;
}
final float applicationScale = mViewRootImpl.mAttachInfo.mApplicationScale;
- if (applicationScale != 1.0f) {
+ if (shouldApplyAppScaleAndMagnificationSpec(applicationScale, spec)) {
final int infoCount = infos.size();
for (int i = 0; i < infoCount; i++) {
AccessibilityNodeInfo info = infos.get(i);
- applyApplicationScaleIfNeeded(info);
+ applyAppScaleAndMagnificationSpecIfNeeded(info, spec);
}
}
}
- private void applyApplicationScaleIfNeeded(AccessibilityNodeInfo info) {
+ private void applyAppScaleAndMagnificationSpecIfNeeded(AccessibilityNodeInfo info,
+ MagnificationSpec spec) {
if (info == null) {
return;
}
+
final float applicationScale = mViewRootImpl.mAttachInfo.mApplicationScale;
+ if (!shouldApplyAppScaleAndMagnificationSpec(applicationScale, spec)) {
+ return;
+ }
+
+ Rect boundsInParent = mTempRect;
+ Rect boundsInScreen = mTempRect1;
+
+ info.getBoundsInParent(boundsInParent);
+ info.getBoundsInScreen(boundsInScreen);
if (applicationScale != 1.0f) {
- Rect bounds = mTempRect;
+ boundsInParent.scale(applicationScale);
+ boundsInScreen.scale(applicationScale);
+ }
+ if (spec != null) {
+ boundsInParent.scale(spec.scale);
+ // boundsInParent must not be offset.
+ boundsInScreen.scale(spec.scale);
+ boundsInScreen.offset((int) spec.offsetX, (int) spec.offsetY);
+ }
+ info.setBoundsInParent(boundsInParent);
+ info.setBoundsInScreen(boundsInScreen);
+
+ if (spec != null) {
+ AttachInfo attachInfo = mViewRootImpl.mAttachInfo;
+ if (attachInfo.mDisplay == null) {
+ return;
+ }
- info.getBoundsInParent(bounds);
- bounds.scale(applicationScale);
- info.setBoundsInParent(bounds);
+ final float scale = attachInfo.mApplicationScale * spec.scale;
- info.getBoundsInScreen(bounds);
- bounds.scale(applicationScale);
- info.setBoundsInScreen(bounds);
+ Rect visibleWinFrame = mTempRect1;
+ visibleWinFrame.left = (int) (attachInfo.mWindowLeft * scale + spec.offsetX);
+ visibleWinFrame.top = (int) (attachInfo.mWindowTop * scale + spec.offsetY);
+ visibleWinFrame.right = (int) (visibleWinFrame.left + mViewRootImpl.mWidth * scale);
+ visibleWinFrame.bottom = (int) (visibleWinFrame.top + mViewRootImpl.mHeight * scale);
+
+ attachInfo.mDisplay.getRealSize(mTempPoint);
+ final int displayWidth = mTempPoint.x;
+ final int displayHeight = mTempPoint.y;
+
+ Rect visibleDisplayFrame = mTempRect2;
+ visibleDisplayFrame.set(0, 0, displayWidth, displayHeight);
+
+ visibleWinFrame.intersect(visibleDisplayFrame);
+
+ if (!visibleWinFrame.intersects(boundsInScreen.left, boundsInScreen.top,
+ boundsInScreen.right, boundsInScreen.bottom)) {
+ info.setVisibleToUser(false);
+ }
}
}
+ private boolean shouldApplyAppScaleAndMagnificationSpec(float appScale,
+ MagnificationSpec spec) {
+ return (appScale != 1.0f || (spec != null && !spec.isNop()));
+ }
/**
* This class encapsulates a prefetching strategy for the accessibility APIs for
diff --git a/core/java/android/view/IDisplayContentChangeListener.aidl b/core/java/android/view/IDisplayMagnificationController.aidl
index ef7edea..efe2775 100644
--- a/core/java/android/view/IDisplayContentChangeListener.aidl
+++ b/core/java/android/view/IDisplayMagnificationController.aidl
@@ -1,7 +1,7 @@
/*
** Copyright 2012, The Android Open Source Project
**
-** Licensed under the Apache License, Version 2.0 (the "License")
+** 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
**
@@ -16,18 +16,12 @@
package android.view;
-import android.os.IBinder;
-import android.view.WindowInfo;
-import android.graphics.Rect;
-
/**
- * Interface for observing content changes on a display.
- *
* {@hide}
*/
-oneway interface IDisplayContentChangeListener {
- void onWindowTransition(int displayId, int transition, in WindowInfo info);
- void onRectangleOnScreenRequested(int displayId, in Rect rectangle, boolean immediate);
- void onWindowLayersChanged(int displayId);
+oneway interface IDisplayMagnificationController {
+ void onMagnifedFrameChanged(int left, int top, int right, int bottom);
+ void onRectangleOnScreenRequested(int left, int top, int right, int bottom);
void onRotationChanged(int rotation);
+ void onUserContextChanged();
}
diff --git a/core/java/android/view/IDisplayMagnificationMediator.aidl b/core/java/android/view/IDisplayMagnificationMediator.aidl
new file mode 100644
index 0000000..aa25dac
--- /dev/null
+++ b/core/java/android/view/IDisplayMagnificationMediator.aidl
@@ -0,0 +1,31 @@
+/*
+** Copyright 2012, 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.
+*/
+
+package android.view;
+
+import android.view.IDisplayMagnificationController;
+import android.view.MagnificationSpec;
+
+/**
+ * {@hide}
+ */
+interface IDisplayMagnificationMediator {
+ void addController(int displayId, in IDisplayMagnificationController controller);
+ void removeController(in IDisplayMagnificationController controller);
+ void setMagnificationSpec(in IDisplayMagnificationController controller,
+ in MagnificationSpec spec);
+ MagnificationSpec getCompatibleMagnificationSpec(in IBinder windowToken);
+}
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 0fe2a8e..17f04e9 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -27,17 +27,17 @@ import android.graphics.Rect;
import android.os.Bundle;
import android.os.IRemoteCallback;
import android.view.IApplicationToken;
-import android.view.IDisplayContentChangeListener;
+import android.view.IDisplayMagnificationMediator;
import android.view.IOnKeyguardExitResult;
import android.view.IRotationWatcher;
import android.view.IWindowSession;
import android.view.KeyEvent;
import android.view.InputEvent;
+import android.view.MagnificationSpec;
import android.view.MotionEvent;
import android.view.InputChannel;
import android.view.InputDevice;
import android.view.IInputFilter;
-import android.view.WindowInfo;
/**
* System private interface to the window manager.
@@ -221,39 +221,19 @@ interface IWindowManager
IBinder getFocusedWindowToken();
/**
- * Gets the compatibility scale of e window given its token.
- */
- float getWindowCompatibilityScale(IBinder windowToken);
-
- /**
* Sets an input filter for manipulating the input event stream.
*/
void setInputFilter(in IInputFilter filter);
/**
- * Sets the scale and offset for implementing accessibility magnification.
- */
- void magnifyDisplay(int dipslayId, float scale, float offsetX, float offsetY);
-
- /**
- * Adds a listener for display content changes.
- */
- void addDisplayContentChangeListener(int displayId, IDisplayContentChangeListener listener);
-
- /**
- * Removes a listener for display content changes.
- */
- void removeDisplayContentChangeListener(int displayId, IDisplayContentChangeListener listener);
-
- /**
- * Gets the info for a window given its token.
+ * Gets the display magnification mediator.
*/
- WindowInfo getWindowInfo(IBinder token);
+ IDisplayMagnificationMediator getDisplayMagnificationMediator();
/**
- * Gets the infos for all visible windows.
+ * Gets the frame of a window given its token.
*/
- void getVisibleWindowsForDisplay(int displayId, out List<WindowInfo> outInfos);
+ void getWindowFrame(IBinder token, out Rect outFrame);
/**
* Device is in safe mode.
diff --git a/core/java/android/view/WindowInfo.aidl b/core/java/android/view/MagnificationSpec.aidl
index 23e927a..d5fbdef 100644
--- a/core/java/android/view/WindowInfo.aidl
+++ b/core/java/android/view/MagnificationSpec.aidl
@@ -17,4 +17,4 @@
package android.view;
-parcelable WindowInfo;
+parcelable MagnificationSpec;
diff --git a/core/java/android/view/MagnificationSpec.java b/core/java/android/view/MagnificationSpec.java
new file mode 100644
index 0000000..7fb5615
--- /dev/null
+++ b/core/java/android/view/MagnificationSpec.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+package android.view;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.Pools.SynchronizedPool;
+
+/**
+ * This class represents spec for performing screen magnification.
+ *
+ * @hide
+ */
+public class MagnificationSpec implements Parcelable {
+ private static final int MAX_POOL_SIZE = 20;
+ private static final SynchronizedPool<MagnificationSpec> sPool =
+ new SynchronizedPool<MagnificationSpec>(MAX_POOL_SIZE);
+
+ public float scale = 1.0f;
+ public float offsetX;
+ public float offsetY;
+
+ private MagnificationSpec() {
+ /* do nothing - reducing visibility */
+ }
+
+ public void initialize(float scale, float offsetX, float offsetY) {
+ this.scale = scale;
+ this.offsetX = offsetX;
+ this.offsetY = offsetY;
+ }
+
+ public boolean isNop() {
+ return scale == 1.0f && offsetX == 0 && offsetY == 0;
+ }
+
+ public static MagnificationSpec obtain(MagnificationSpec other) {
+ MagnificationSpec info = obtain();
+ info.scale = other.scale;
+ info.offsetX = other.offsetX;
+ info.offsetY = other.offsetY;
+ return info;
+ }
+
+ public static MagnificationSpec obtain() {
+ MagnificationSpec spec = sPool.acquire();
+ return (spec != null) ? spec : new MagnificationSpec();
+ }
+
+ public void recycle() {
+ clear();
+ sPool.release(this);
+ }
+
+ public void clear() {
+ scale = 1.0f;
+ offsetX = 0.0f;
+ offsetY = 0.0f;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel parcel, int flags) {
+ parcel.writeFloat(scale);
+ parcel.writeFloat(offsetX);
+ parcel.writeFloat(offsetY);
+ recycle();
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("<scale:");
+ builder.append(scale);
+ builder.append(",offsetX:");
+ builder.append(offsetX);
+ builder.append(",offsetY:");
+ builder.append(offsetY);
+ builder.append(">");
+ return builder.toString();
+ }
+
+ private void initFromParcel(Parcel parcel) {
+ scale = parcel.readFloat();
+ offsetX = parcel.readFloat();
+ offsetY = parcel.readFloat();
+ }
+
+ public static final Creator<MagnificationSpec> CREATOR = new Creator<MagnificationSpec>() {
+ @Override
+ public MagnificationSpec[] newArray(int size) {
+ return new MagnificationSpec[size];
+ }
+
+ @Override
+ public MagnificationSpec createFromParcel(Parcel parcel) {
+ MagnificationSpec spec = MagnificationSpec.obtain();
+ spec.initFromParcel(parcel);
+ return spec;
+ }
+ };
+}
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index 550a740..f2c5eac 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -808,6 +808,32 @@ public class Surface implements Parcelable {
}
/**
+ * Returns a human readable representation of a rotation.
+ *
+ * @param rotation The rotation.
+ * @return The rotation symbolic name.
+ */
+ public static String rotationToString(int rotation) {
+ switch (rotation) {
+ case Surface.ROTATION_0: {
+ return "ROTATION_0";
+ }
+ case Surface.ROTATION_90: {
+ return "ROATATION_90";
+ }
+ case Surface.ROTATION_180: {
+ return "ROATATION_180";
+ }
+ case Surface.ROTATION_270: {
+ return "ROATATION_270";
+ }
+ default: {
+ throw new IllegalArgumentException("Invalid rotation: " + rotation);
+ }
+ }
+ }
+
+ /**
* A Canvas class that can handle the compatibility mode.
* This does two things differently.
* <ul>
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index e66e30f..5ad7bb3 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -5416,12 +5416,13 @@ public final class ViewRootImpl implements ViewParent,
@Override
public void findAccessibilityNodeInfoByAccessibilityId(long accessibilityNodeId,
int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags,
- int interrogatingPid, long interrogatingTid) {
+ int interrogatingPid, long interrogatingTid, MagnificationSpec spec) {
ViewRootImpl viewRootImpl = mViewRootImpl.get();
if (viewRootImpl != null && viewRootImpl.mView != null) {
viewRootImpl.getAccessibilityInteractionController()
.findAccessibilityNodeInfoByAccessibilityIdClientThread(accessibilityNodeId,
- interactionId, callback, flags, interrogatingPid, interrogatingTid);
+ interactionId, callback, flags, interrogatingPid, interrogatingTid,
+ spec);
} else {
// We cannot make the call and notify the caller so it does not wait.
try {
@@ -5455,12 +5456,13 @@ public final class ViewRootImpl implements ViewParent,
@Override
public void findAccessibilityNodeInfoByViewId(long accessibilityNodeId, int viewId,
int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags,
- int interrogatingPid, long interrogatingTid) {
+ int interrogatingPid, long interrogatingTid, MagnificationSpec spec) {
ViewRootImpl viewRootImpl = mViewRootImpl.get();
if (viewRootImpl != null && viewRootImpl.mView != null) {
viewRootImpl.getAccessibilityInteractionController()
.findAccessibilityNodeInfoByViewIdClientThread(accessibilityNodeId, viewId,
- interactionId, callback, flags, interrogatingPid, interrogatingTid);
+ interactionId, callback, flags, interrogatingPid, interrogatingTid,
+ spec);
} else {
// We cannot make the call and notify the caller so it does not wait.
try {
@@ -5474,12 +5476,13 @@ public final class ViewRootImpl implements ViewParent,
@Override
public void findAccessibilityNodeInfosByText(long accessibilityNodeId, String text,
int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags,
- int interrogatingPid, long interrogatingTid) {
+ int interrogatingPid, long interrogatingTid, MagnificationSpec spec) {
ViewRootImpl viewRootImpl = mViewRootImpl.get();
if (viewRootImpl != null && viewRootImpl.mView != null) {
viewRootImpl.getAccessibilityInteractionController()
.findAccessibilityNodeInfosByTextClientThread(accessibilityNodeId, text,
- interactionId, callback, flags, interrogatingPid, interrogatingTid);
+ interactionId, callback, flags, interrogatingPid, interrogatingTid,
+ spec);
} else {
// We cannot make the call and notify the caller so it does not wait.
try {
@@ -5493,12 +5496,12 @@ public final class ViewRootImpl implements ViewParent,
@Override
public void findFocus(long accessibilityNodeId, int focusType, int interactionId,
IAccessibilityInteractionConnectionCallback callback, int flags,
- int interrogatingPid, long interrogatingTid) {
+ int interrogatingPid, long interrogatingTid, MagnificationSpec spec) {
ViewRootImpl viewRootImpl = mViewRootImpl.get();
if (viewRootImpl != null && viewRootImpl.mView != null) {
viewRootImpl.getAccessibilityInteractionController()
.findFocusClientThread(accessibilityNodeId, focusType, interactionId, callback,
- flags, interrogatingPid, interrogatingTid);
+ flags, interrogatingPid, interrogatingTid, spec);
} else {
// We cannot make the call and notify the caller so it does not wait.
try {
@@ -5512,12 +5515,12 @@ public final class ViewRootImpl implements ViewParent,
@Override
public void focusSearch(long accessibilityNodeId, int direction, int interactionId,
IAccessibilityInteractionConnectionCallback callback, int flags,
- int interrogatingPid, long interrogatingTid) {
+ int interrogatingPid, long interrogatingTid, MagnificationSpec spec) {
ViewRootImpl viewRootImpl = mViewRootImpl.get();
if (viewRootImpl != null && viewRootImpl.mView != null) {
viewRootImpl.getAccessibilityInteractionController()
.focusSearchClientThread(accessibilityNodeId, direction, interactionId,
- callback, flags, interrogatingPid, interrogatingTid);
+ callback, flags, interrogatingPid, interrogatingTid, spec);
} else {
// We cannot make the call and notify the caller so it does not wait.
try {
diff --git a/core/java/android/view/WindowInfo.java b/core/java/android/view/WindowInfo.java
deleted file mode 100644
index 7d16e14..0000000
--- a/core/java/android/view/WindowInfo.java
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * Copyright (C) 2012 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.
- */
-
-package android.view;
-
-import android.graphics.Rect;
-import android.os.IBinder;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * Information the state of a window.
- *
- * @hide
- */
-public class WindowInfo implements Parcelable {
-
- private static final int MAX_POOL_SIZE = 20;
-
- private static int UNDEFINED = -1;
-
- private static Object sPoolLock = new Object();
- private static WindowInfo sPool;
- private static int sPoolSize;
-
- private WindowInfo mNext;
- private boolean mInPool;
-
- public IBinder token;
-
- public final Rect frame = new Rect();
-
- public final Rect touchableRegion = new Rect();
-
- public int type = UNDEFINED;
-
- public float compatibilityScale = UNDEFINED;
-
- public boolean visible;
-
- public int displayId = UNDEFINED;
-
- public int layer = UNDEFINED;
-
- private WindowInfo() {
- /* do nothing - reduce visibility */
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel parcel, int flags) {
- parcel.writeStrongBinder(token);
- parcel.writeParcelable(frame, 0);
- parcel.writeParcelable(touchableRegion, 0);
- parcel.writeInt(type);
- parcel.writeFloat(compatibilityScale);
- parcel.writeInt(visible ? 1 : 0);
- parcel.writeInt(displayId);
- parcel.writeInt(layer);
- recycle();
- }
-
- private void initFromParcel(Parcel parcel) {
- token = parcel.readStrongBinder();
- frame.set((Rect) parcel.readParcelable(null));
- touchableRegion.set((Rect) parcel.readParcelable(null));
- type = parcel.readInt();
- compatibilityScale = parcel.readFloat();
- visible = (parcel.readInt() == 1);
- displayId = parcel.readInt();
- layer = parcel.readInt();
- }
-
- public static WindowInfo obtain(WindowInfo other) {
- WindowInfo info = obtain();
- info.token = other.token;
- info.frame.set(other.frame);
- info.touchableRegion.set(other.touchableRegion);
- info.type = other.type;
- info.compatibilityScale = other.compatibilityScale;
- info.visible = other.visible;
- info.displayId = other.displayId;
- info.layer = other.layer;
- return info;
- }
-
- public static WindowInfo obtain() {
- synchronized (sPoolLock) {
- if (sPoolSize > 0) {
- WindowInfo info = sPool;
- sPool = info.mNext;
- info.mNext = null;
- info.mInPool = false;
- sPoolSize--;
- return info;
- } else {
- return new WindowInfo();
- }
- }
- }
-
- public void recycle() {
- if (mInPool) {
- throw new IllegalStateException("Already recycled.");
- }
- clear();
- synchronized (sPoolLock) {
- if (sPoolSize < MAX_POOL_SIZE) {
- mNext = sPool;
- sPool = this;
- mInPool = true;
- sPoolSize++;
- }
- }
- }
-
- private void clear() {
- token = null;
- frame.setEmpty();
- touchableRegion.setEmpty();
- type = UNDEFINED;
- compatibilityScale = UNDEFINED;
- visible = false;
- displayId = UNDEFINED;
- layer = UNDEFINED;
- }
-
- @Override
- public String toString() {
- StringBuilder builder = new StringBuilder();
- builder.append("Window [token:").append((token != null) ? token.hashCode() : null);
- builder.append(", displayId:").append(displayId);
- builder.append(", type:").append(type);
- builder.append(", visible:").append(visible);
- builder.append(", layer:").append(layer);
- builder.append(", compatibilityScale:").append(compatibilityScale);
- builder.append(", frame:").append(frame);
- builder.append(", touchableRegion:").append(touchableRegion);
- builder.append("]");
- return builder.toString();
- }
-
- /**
- * @see Parcelable.Creator
- */
- public static final Parcelable.Creator<WindowInfo> CREATOR =
- new Parcelable.Creator<WindowInfo>() {
- public WindowInfo createFromParcel(Parcel parcel) {
- WindowInfo info = WindowInfo.obtain();
- info.initFromParcel(parcel);
- return info;
- }
-
- public WindowInfo[] newArray(int size) {
- return new WindowInfo[size];
- }
- };
-}
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index 26739b3..7bdb44c 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -1112,14 +1112,6 @@ public interface WindowManagerPolicy {
public void setLastInputMethodWindowLw(WindowState ime, WindowState target);
/**
- * Returns whether magnification can be applied to the given window type.
- *
- * @param attrs The window's LayoutParams.
- * @return Whether magnification can be applied.
- */
- public boolean canMagnifyWindowLw(WindowManager.LayoutParams attrs);
-
- /**
* Called when the current user changes. Guaranteed to be called before the broadcast
* of the new user id is made to all listeners.
*
diff --git a/core/java/android/view/accessibility/AccessibilityInteractionClient.java b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
index 20b5f17..67df684 100644
--- a/core/java/android/view/accessibility/AccessibilityInteractionClient.java
+++ b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
@@ -17,7 +17,6 @@
package android.view.accessibility;
import android.accessibilityservice.IAccessibilityServiceConnection;
-import android.graphics.Rect;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
@@ -102,8 +101,6 @@ public final class AccessibilityInteractionClient
private Message mSameThreadMessage;
- private final Rect mTempBounds = new Rect();
-
// The connection cache is shared between all interrogating threads.
private static final SparseArray<IAccessibilityServiceConnection> sConnectionCache =
new SparseArray<IAccessibilityServiceConnection>();
@@ -194,14 +191,14 @@ public final class AccessibilityInteractionClient
return cachedInfo;
}
final int interactionId = mInteractionIdCounter.getAndIncrement();
- final float windowScale = connection.findAccessibilityNodeInfoByAccessibilityId(
+ final boolean success = connection.findAccessibilityNodeInfoByAccessibilityId(
accessibilityWindowId, accessibilityNodeId, interactionId, this,
prefetchFlags, Thread.currentThread().getId());
// If the scale is zero the call has failed.
- if (windowScale > 0) {
+ if (success) {
List<AccessibilityNodeInfo> infos = getFindAccessibilityNodeInfosResultAndClear(
interactionId);
- finalizeAndCacheAccessibilityNodeInfos(infos, connectionId, windowScale);
+ finalizeAndCacheAccessibilityNodeInfos(infos, connectionId);
if (infos != null && !infos.isEmpty()) {
return infos.get(0);
}
@@ -242,15 +239,13 @@ public final class AccessibilityInteractionClient
IAccessibilityServiceConnection connection = getConnection(connectionId);
if (connection != null) {
final int interactionId = mInteractionIdCounter.getAndIncrement();
- final float windowScale =
- connection.findAccessibilityNodeInfoByViewId(accessibilityWindowId,
- accessibilityNodeId, viewId, interactionId, this,
- Thread.currentThread().getId());
- // If the scale is zero the call has failed.
- if (windowScale > 0) {
+ final boolean success =connection.findAccessibilityNodeInfoByViewId(
+ accessibilityWindowId, accessibilityNodeId, viewId, interactionId, this,
+ Thread.currentThread().getId());
+ if (success) {
AccessibilityNodeInfo info = getFindAccessibilityNodeInfoResultAndClear(
interactionId);
- finalizeAndCacheAccessibilityNodeInfo(info, connectionId, windowScale);
+ finalizeAndCacheAccessibilityNodeInfo(info, connectionId);
return info;
}
} else {
@@ -290,14 +285,13 @@ public final class AccessibilityInteractionClient
IAccessibilityServiceConnection connection = getConnection(connectionId);
if (connection != null) {
final int interactionId = mInteractionIdCounter.getAndIncrement();
- final float windowScale = connection.findAccessibilityNodeInfosByText(
+ final boolean success = connection.findAccessibilityNodeInfosByText(
accessibilityWindowId, accessibilityNodeId, text, interactionId, this,
Thread.currentThread().getId());
- // If the scale is zero the call has failed.
- if (windowScale > 0) {
+ if (success) {
List<AccessibilityNodeInfo> infos = getFindAccessibilityNodeInfosResultAndClear(
interactionId);
- finalizeAndCacheAccessibilityNodeInfos(infos, connectionId, windowScale);
+ finalizeAndCacheAccessibilityNodeInfos(infos, connectionId);
return infos;
}
} else {
@@ -336,14 +330,13 @@ public final class AccessibilityInteractionClient
IAccessibilityServiceConnection connection = getConnection(connectionId);
if (connection != null) {
final int interactionId = mInteractionIdCounter.getAndIncrement();
- final float windowScale = connection.findFocus(accessibilityWindowId,
+ final boolean success = connection.findFocus(accessibilityWindowId,
accessibilityNodeId, focusType, interactionId, this,
Thread.currentThread().getId());
- // If the scale is zero the call has failed.
- if (windowScale > 0) {
+ if (success) {
AccessibilityNodeInfo info = getFindAccessibilityNodeInfoResultAndClear(
interactionId);
- finalizeAndCacheAccessibilityNodeInfo(info, connectionId, windowScale);
+ finalizeAndCacheAccessibilityNodeInfo(info, connectionId);
return info;
}
} else {
@@ -381,14 +374,13 @@ public final class AccessibilityInteractionClient
IAccessibilityServiceConnection connection = getConnection(connectionId);
if (connection != null) {
final int interactionId = mInteractionIdCounter.getAndIncrement();
- final float windowScale = connection.focusSearch(accessibilityWindowId,
+ final boolean success = connection.focusSearch(accessibilityWindowId,
accessibilityNodeId, direction, interactionId, this,
Thread.currentThread().getId());
- // If the scale is zero the call has failed.
- if (windowScale > 0) {
+ if (success) {
AccessibilityNodeInfo info = getFindAccessibilityNodeInfoResultAndClear(
interactionId);
- finalizeAndCacheAccessibilityNodeInfo(info, connectionId, windowScale);
+ finalizeAndCacheAccessibilityNodeInfo(info, connectionId);
return info;
}
} else {
@@ -604,36 +596,14 @@ public final class AccessibilityInteractionClient
}
/**
- * Applies compatibility scale to the info bounds if it is not equal to one.
- *
- * @param info The info whose bounds to scale.
- * @param scale The scale to apply.
- */
- private void applyCompatibilityScaleIfNeeded(AccessibilityNodeInfo info, float scale) {
- if (scale == 1.0f) {
- return;
- }
- Rect bounds = mTempBounds;
- info.getBoundsInParent(bounds);
- bounds.scale(scale);
- info.setBoundsInParent(bounds);
-
- info.getBoundsInScreen(bounds);
- bounds.scale(scale);
- info.setBoundsInScreen(bounds);
- }
-
- /**
* Finalize an {@link AccessibilityNodeInfo} before passing it to the client.
*
* @param info The info.
* @param connectionId The id of the connection to the system.
- * @param windowScale The source window compatibility scale.
*/
- private void finalizeAndCacheAccessibilityNodeInfo(AccessibilityNodeInfo info, int connectionId,
- float windowScale) {
+ private void finalizeAndCacheAccessibilityNodeInfo(AccessibilityNodeInfo info,
+ int connectionId) {
if (info != null) {
- applyCompatibilityScaleIfNeeded(info, windowScale);
info.setConnectionId(connectionId);
info.setSealed(true);
sAccessibilityNodeInfoCache.add(info);
@@ -645,15 +615,14 @@ public final class AccessibilityInteractionClient
*
* @param infos The {@link AccessibilityNodeInfo}s.
* @param connectionId The id of the connection to the system.
- * @param windowScale The source window compatibility scale.
*/
private void finalizeAndCacheAccessibilityNodeInfos(List<AccessibilityNodeInfo> infos,
- int connectionId, float windowScale) {
+ int connectionId) {
if (infos != null) {
final int infosCount = infos.size();
for (int i = 0; i < infosCount; i++) {
AccessibilityNodeInfo info = infos.get(i);
- finalizeAndCacheAccessibilityNodeInfo(info, connectionId, windowScale);
+ finalizeAndCacheAccessibilityNodeInfo(info, connectionId);
}
}
}
diff --git a/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl b/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl
index 9b39300..c313b07 100644
--- a/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl
+++ b/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl
@@ -17,6 +17,7 @@
package android.view.accessibility;
import android.os.Bundle;
+import android.view.MagnificationSpec;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.IAccessibilityInteractionConnectionCallback;
@@ -30,23 +31,23 @@ oneway interface IAccessibilityInteractionConnection {
void findAccessibilityNodeInfoByAccessibilityId(long accessibilityNodeId, int interactionId,
IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid,
- long interrogatingTid);
+ long interrogatingTid, in MagnificationSpec spec);
void findAccessibilityNodeInfoByViewId(long accessibilityNodeId, int viewId, int interactionId,
IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid,
- long interrogatingTid);
+ long interrogatingTid, in MagnificationSpec spec);
void findAccessibilityNodeInfosByText(long accessibilityNodeId, String text, int interactionId,
IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid,
- long interrogatingTid);
+ long interrogatingTid, in MagnificationSpec spec);
void findFocus(long accessibilityNodeId, int focusType, int interactionId,
IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid,
- long interrogatingTid);
+ long interrogatingTid, in MagnificationSpec spec);
void focusSearch(long accessibilityNodeId, int direction, int interactionId,
IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid,
- long interrogatingTid);
+ long interrogatingTid, in MagnificationSpec spec);
void performAccessibilityAction(long accessibilityNodeId, int action, in Bundle arguments,
int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags,
diff --git a/core/java/com/android/internal/policy/PolicyManager.java b/core/java/com/android/internal/policy/PolicyManager.java
index 5274e54..462b3a9 100644
--- a/core/java/com/android/internal/policy/PolicyManager.java
+++ b/core/java/com/android/internal/policy/PolicyManager.java
@@ -22,8 +22,6 @@ import android.view.LayoutInflater;
import android.view.Window;
import android.view.WindowManagerPolicy;
-import com.android.internal.policy.IPolicy;
-
/**
* {@hide}
*/
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index e978a8f..6262e4b 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -4520,19 +4520,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
@Override
- public boolean canMagnifyWindowLw(WindowManager.LayoutParams attrs) {
- switch (attrs.type) {
- case WindowManager.LayoutParams.TYPE_INPUT_METHOD:
- case WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG:
- case WindowManager.LayoutParams.TYPE_NAVIGATION_BAR:
- case WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY: {
- return false;
- }
- }
- return true;
- }
-
- @Override
public void setCurrentUserLw(int newUserId) {
if (mKeyguardMediator != null) {
mKeyguardMediator.setCurrentUser(newUserId);
@@ -4552,6 +4539,71 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mKeyguardMediator.showAssistant();
}
+ /**
+ * Returns the human readable name of a window transition.
+ *
+ * @param transition The window transition.
+ * @return The transition symbolic name.
+ */
+ public static String windowTransitionToString(int transition) {
+ switch (transition) {
+ case WindowManagerPolicy.TRANSIT_UNSET: {
+ return "TRANSIT_UNSET";
+ }
+ case WindowManagerPolicy.TRANSIT_NONE: {
+ return "TRANSIT_NONE";
+ }
+ case WindowManagerPolicy.TRANSIT_ENTER: {
+ return "TRANSIT_ENTER";
+ }
+ case WindowManagerPolicy.TRANSIT_EXIT: {
+ return "TRANSIT_EXIT";
+ }
+ case WindowManagerPolicy.TRANSIT_SHOW: {
+ return "TRANSIT_SHOW";
+ }
+ case WindowManagerPolicy.TRANSIT_EXIT_MASK: {
+ return "TRANSIT_EXIT_MASK";
+ }
+ case WindowManagerPolicy.TRANSIT_PREVIEW_DONE: {
+ return "TRANSIT_PREVIEW_DONE";
+ }
+ case WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN: {
+ return "TRANSIT_ACTIVITY_OPEN";
+ }
+ case WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE: {
+ return "TRANSIT_ACTIVITY_CLOSE";
+ }
+ case WindowManagerPolicy.TRANSIT_TASK_OPEN: {
+ return "TRANSIT_TASK_OPEN";
+ }
+ case WindowManagerPolicy.TRANSIT_TASK_CLOSE: {
+ return "TRANSIT_TASK_CLOSE";
+ }
+ case WindowManagerPolicy.TRANSIT_TASK_TO_FRONT: {
+ return "TRANSIT_TASK_TO_FRONT";
+ }
+ case WindowManagerPolicy.TRANSIT_TASK_TO_BACK: {
+ return "TRANSIT_TASK_TO_BACK";
+ }
+ case WindowManagerPolicy.TRANSIT_WALLPAPER_CLOSE: {
+ return "TRANSIT_WALLPAPER_CLOSE";
+ }
+ case WindowManagerPolicy.TRANSIT_WALLPAPER_OPEN: {
+ return "TRANSIT_WALLPAPER_OPEN";
+ }
+ case WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_OPEN: {
+ return "TRANSIT_WALLPAPER_INTRA_OPEN";
+ }
+ case WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_CLOSE: {
+ return "TRANSIT_WALLPAPER_INTRA_CLOSE";
+ }
+ default: {
+ return "<UNKNOWN>";
+ }
+ }
+ }
+
@Override
public void dump(String prefix, PrintWriter pw, String[] args) {
pw.print(prefix); pw.print("mSafeMode="); pw.print(mSafeMode);
diff --git a/policy/src/com/android/internal/policy/impl/Policy.java b/policy/src/com/android/internal/policy/impl/Policy.java
index 153ef0f..42bfc5f 100644
--- a/policy/src/com/android/internal/policy/impl/Policy.java
+++ b/policy/src/com/android/internal/policy/impl/Policy.java
@@ -24,9 +24,6 @@ import android.view.Window;
import android.view.WindowManagerPolicy;
import com.android.internal.policy.IPolicy;
-import com.android.internal.policy.impl.PhoneLayoutInflater;
-import com.android.internal.policy.impl.PhoneWindow;
-import com.android.internal.policy.impl.PhoneWindowManager;
/**
* {@hide}
diff --git a/services/java/com/android/server/accessibility/AccessibilityInputFilter.java b/services/java/com/android/server/accessibility/AccessibilityInputFilter.java
index eb414fa..45da1e1 100644
--- a/services/java/com/android/server/accessibility/AccessibilityInputFilter.java
+++ b/services/java/com/android/server/accessibility/AccessibilityInputFilter.java
@@ -19,6 +19,7 @@ package com.android.server.accessibility;
import android.content.Context;
import android.os.PowerManager;
import android.util.Slog;
+import android.view.Display;
import android.view.InputDevice;
import android.view.InputEvent;
import android.view.InputFilter;
@@ -169,7 +170,8 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo
private void enableFeatures() {
if ((mEnabledFeatures & FLAG_FEATURE_SCREEN_MAGNIFIER) != 0) {
- mEventHandler = mScreenMagnifier = new ScreenMagnifier(mContext);
+ mEventHandler = mScreenMagnifier = new ScreenMagnifier(mContext,
+ Display.DEFAULT_DISPLAY, mAms);
mEventHandler.setNext(this);
}
if ((mEnabledFeatures & FLAG_FEATURE_TOUCH_EXPLORATION) != 0) {
diff --git a/services/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
index 65bfa7e..3e2540d 100644
--- a/services/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -65,12 +65,13 @@ import android.text.TextUtils.SimpleStringSplitter;
import android.util.Slog;
import android.util.SparseArray;
import android.view.Display;
+import android.view.IDisplayMagnificationMediator;
import android.view.IWindow;
import android.view.IWindowManager;
import android.view.InputDevice;
import android.view.KeyCharacterMap;
import android.view.KeyEvent;
-import android.view.WindowInfo;
+import android.view.MagnificationSpec;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityInteractionClient;
@@ -158,6 +159,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
private final MainHandler mMainHandler;
+ private IDisplayMagnificationMediator mMagnificationMediator;
+
private Service mUiAutomationService;
private Service mQueryBridge;
@@ -621,6 +624,13 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
return false;
}
focus.getBoundsInScreen(outBounds);
+
+ MagnificationSpec spec = service.getCompatibleMagnificationSpec(focus.getWindowId());
+ if (spec != null && !spec.isNop()) {
+ outBounds.offset((int) -spec.offsetX, (int) -spec.offsetY);
+ outBounds.scale(1 / spec.scale);
+ }
+
// Clip to the window rectangle.
Rect windowBounds = mTempRect;
getActiveWindowBounds(windowBounds);
@@ -628,6 +638,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
// Clip to the screen rectangle.
mDefaultDisplay.getRealSize(mTempPoint);
outBounds.intersect(0, 0, mTempPoint.x, mTempPoint.y);
+
return true;
} finally {
client.removeConnection(connectionId);
@@ -648,19 +659,13 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
token = getCurrentUserStateLocked().mWindowTokens.get(windowId);
}
}
- WindowInfo info = null;
try {
- info = mWindowManagerService.getWindowInfo(token);
- if (info != null) {
- outBounds.set(info.frame);
+ mWindowManagerService.getWindowFrame(token, outBounds);
+ if (!outBounds.isEmpty()) {
return true;
}
} catch (RemoteException re) {
/* ignore */
- } finally {
- if (info != null) {
- info.recycle();
- }
}
return false;
}
@@ -677,6 +682,10 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
mSecurityPolicy.onTouchInteractionEnd();
}
+ void onMagnificationStateChanged() {
+ notifyClearAccessibilityNodeInfoCacheLocked();
+ }
+
private void switchUser(int userId) {
synchronized (mLock) {
// The user switched so we do not need to restore the current user
@@ -762,6 +771,14 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
return false;
}
+ private void notifyClearAccessibilityNodeInfoCacheLocked() {
+ UserState state = getCurrentUserStateLocked();
+ for (int i = state.mServices.size() - 1; i >= 0; i--) {
+ Service service = state.mServices.get(i);
+ service.notifyClearAccessibilityNodeInfoCache();
+ }
+ }
+
/**
* Removes an AccessibilityInteractionConnection.
*
@@ -1438,9 +1455,10 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
class Service extends IAccessibilityServiceConnection.Stub
implements ServiceConnection, DeathRecipient {
- // We pick the MSB to avoid collision since accessibility event types are
+ // We pick the MSBs to avoid collision since accessibility event types are
// used as message types allowing us to remove messages per event type.
private static final int MSG_ON_GESTURE = 0x80000000;
+ private static final int MSG_CLEAR_ACCESSIBILITY_NODE_INFO_CACHE = 0x40000000;
final int mUserId;
@@ -1494,6 +1512,9 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
final int gestureId = message.arg1;
notifyGestureInternal(gestureId);
} break;
+ case MSG_CLEAR_ACCESSIBILITY_NODE_INFO_CACHE: {
+ notifyClearAccessibilityNodeInfoCacheInternal();
+ } break;
default: {
final int eventType = type;
notifyAccessibilityEventInternal(eventType);
@@ -1636,7 +1657,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
}
@Override
- public float findAccessibilityNodeInfoByViewId(int accessibilityWindowId,
+ public boolean findAccessibilityNodeInfoByViewId(int accessibilityWindowId,
long accessibilityNodeId, int viewId, int interactionId,
IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
throws RemoteException {
@@ -1647,17 +1668,17 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
.resolveCallingUserIdEnforcingPermissionsLocked(
UserHandle.getCallingUserId());
if (resolvedUserId != mCurrentUserId) {
- return -1;
+ return false;
}
mSecurityPolicy.enforceCanRetrieveWindowContent(this);
final boolean permissionGranted = mSecurityPolicy.canRetrieveWindowContent(this);
if (!permissionGranted) {
- return 0;
+ return false;
} else {
resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
connection = getConnectionLocked(resolvedWindowId);
if (connection == null) {
- return 0;
+ return false;
}
}
}
@@ -1665,10 +1686,11 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
AccessibilityNodeInfo.INCLUDE_NOT_IMPORTANT_VIEWS : 0;
final int interrogatingPid = Binder.getCallingPid();
final long identityToken = Binder.clearCallingIdentity();
+ MagnificationSpec spec = getCompatibleMagnificationSpec(resolvedWindowId);
try {
connection.findAccessibilityNodeInfoByViewId(accessibilityNodeId, viewId,
- interactionId, callback, flags, interrogatingPid, interrogatingTid);
- return getCompatibilityScale(resolvedWindowId);
+ interactionId, callback, flags, interrogatingPid, interrogatingTid, spec);
+ return true;
} catch (RemoteException re) {
if (DEBUG) {
Slog.e(LOG_TAG, "Error findAccessibilityNodeInfoByViewId().");
@@ -1676,11 +1698,11 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
} finally {
Binder.restoreCallingIdentity(identityToken);
}
- return 0;
+ return false;
}
@Override
- public float findAccessibilityNodeInfosByText(int accessibilityWindowId,
+ public boolean findAccessibilityNodeInfosByText(int accessibilityWindowId,
long accessibilityNodeId, String text, int interactionId,
IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
throws RemoteException {
@@ -1691,18 +1713,18 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
.resolveCallingUserIdEnforcingPermissionsLocked(
UserHandle.getCallingUserId());
if (resolvedUserId != mCurrentUserId) {
- return -1;
+ return false;
}
mSecurityPolicy.enforceCanRetrieveWindowContent(this);
resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
final boolean permissionGranted =
mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId);
if (!permissionGranted) {
- return 0;
+ return false;
} else {
connection = getConnectionLocked(resolvedWindowId);
if (connection == null) {
- return 0;
+ return false;
}
}
}
@@ -1710,11 +1732,11 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
AccessibilityNodeInfo.INCLUDE_NOT_IMPORTANT_VIEWS : 0;
final int interrogatingPid = Binder.getCallingPid();
final long identityToken = Binder.clearCallingIdentity();
+ MagnificationSpec spec = getCompatibleMagnificationSpec(resolvedWindowId);
try {
connection.findAccessibilityNodeInfosByText(accessibilityNodeId, text,
- interactionId, callback, flags, interrogatingPid,
- interrogatingTid);
- return getCompatibilityScale(resolvedWindowId);
+ interactionId, callback, flags, interrogatingPid, interrogatingTid, spec);
+ return true;
} catch (RemoteException re) {
if (DEBUG) {
Slog.e(LOG_TAG, "Error calling findAccessibilityNodeInfosByText()");
@@ -1722,12 +1744,12 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
} finally {
Binder.restoreCallingIdentity(identityToken);
}
- return 0;
+ return false;
}
@Override
- public float findAccessibilityNodeInfoByAccessibilityId(int accessibilityWindowId,
- long accessibilityNodeId, int interactionId,
+ public boolean findAccessibilityNodeInfoByAccessibilityId(
+ int accessibilityWindowId, long accessibilityNodeId, int interactionId,
IAccessibilityInteractionConnectionCallback callback, int flags,
long interrogatingTid) throws RemoteException {
final int resolvedWindowId;
@@ -1737,18 +1759,18 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
.resolveCallingUserIdEnforcingPermissionsLocked(
UserHandle.getCallingUserId());
if (resolvedUserId != mCurrentUserId) {
- return -1;
+ return false;
}
mSecurityPolicy.enforceCanRetrieveWindowContent(this);
resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
final boolean permissionGranted =
mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId);
if (!permissionGranted) {
- return 0;
+ return false;
} else {
connection = getConnectionLocked(resolvedWindowId);
if (connection == null) {
- return 0;
+ return false;
}
}
}
@@ -1756,10 +1778,12 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
AccessibilityNodeInfo.INCLUDE_NOT_IMPORTANT_VIEWS : 0);
final int interrogatingPid = Binder.getCallingPid();
final long identityToken = Binder.clearCallingIdentity();
+ MagnificationSpec spec = getCompatibleMagnificationSpec(resolvedWindowId);
try {
connection.findAccessibilityNodeInfoByAccessibilityId(accessibilityNodeId,
- interactionId, callback, allFlags, interrogatingPid, interrogatingTid);
- return getCompatibilityScale(resolvedWindowId);
+ interactionId, callback, allFlags, interrogatingPid, interrogatingTid,
+ spec);
+ return true;
} catch (RemoteException re) {
if (DEBUG) {
Slog.e(LOG_TAG, "Error calling findAccessibilityNodeInfoByAccessibilityId()");
@@ -1767,11 +1791,11 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
} finally {
Binder.restoreCallingIdentity(identityToken);
}
- return 0;
+ return false;
}
@Override
- public float findFocus(int accessibilityWindowId, long accessibilityNodeId,
+ public boolean findFocus(int accessibilityWindowId, long accessibilityNodeId,
int focusType, int interactionId,
IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
throws RemoteException {
@@ -1782,18 +1806,18 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
.resolveCallingUserIdEnforcingPermissionsLocked(
UserHandle.getCallingUserId());
if (resolvedUserId != mCurrentUserId) {
- return -1;
+ return false;
}
mSecurityPolicy.enforceCanRetrieveWindowContent(this);
resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
final boolean permissionGranted =
mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId);
if (!permissionGranted) {
- return 0;
+ return false;
} else {
connection = getConnectionLocked(resolvedWindowId);
if (connection == null) {
- return 0;
+ return false;
}
}
}
@@ -1801,10 +1825,11 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
AccessibilityNodeInfo.INCLUDE_NOT_IMPORTANT_VIEWS : 0;
final int interrogatingPid = Binder.getCallingPid();
final long identityToken = Binder.clearCallingIdentity();
+ MagnificationSpec spec = getCompatibleMagnificationSpec(resolvedWindowId);
try {
connection.findFocus(accessibilityNodeId, focusType, interactionId, callback,
- flags, interrogatingPid, interrogatingTid);
- return getCompatibilityScale(resolvedWindowId);
+ flags, interrogatingPid, interrogatingTid, spec);
+ return true;
} catch (RemoteException re) {
if (DEBUG) {
Slog.e(LOG_TAG, "Error calling findAccessibilityFocus()");
@@ -1812,11 +1837,11 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
} finally {
Binder.restoreCallingIdentity(identityToken);
}
- return 0;
+ return false;
}
@Override
- public float focusSearch(int accessibilityWindowId, long accessibilityNodeId,
+ public boolean focusSearch(int accessibilityWindowId, long accessibilityNodeId,
int direction, int interactionId,
IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
throws RemoteException {
@@ -1827,18 +1852,18 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
.resolveCallingUserIdEnforcingPermissionsLocked(
UserHandle.getCallingUserId());
if (resolvedUserId != mCurrentUserId) {
- return -1;
+ return false;
}
mSecurityPolicy.enforceCanRetrieveWindowContent(this);
resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
final boolean permissionGranted =
mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId);
if (!permissionGranted) {
- return 0;
+ return false;
} else {
connection = getConnectionLocked(resolvedWindowId);
if (connection == null) {
- return 0;
+ return false;
}
}
}
@@ -1846,10 +1871,11 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
AccessibilityNodeInfo.INCLUDE_NOT_IMPORTANT_VIEWS : 0;
final int interrogatingPid = Binder.getCallingPid();
final long identityToken = Binder.clearCallingIdentity();
+ MagnificationSpec spec = getCompatibleMagnificationSpec(resolvedWindowId);
try {
connection.focusSearch(accessibilityNodeId, direction, interactionId, callback,
- flags, interrogatingPid, interrogatingTid);
- return getCompatibilityScale(resolvedWindowId);
+ flags, interrogatingPid, interrogatingTid, spec);
+ return true;
} catch (RemoteException re) {
if (DEBUG) {
Slog.e(LOG_TAG, "Error calling accessibilityFocusSearch()");
@@ -1857,7 +1883,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
} finally {
Binder.restoreCallingIdentity(identityToken);
}
- return 0;
+ return false;
}
@Override
@@ -2082,6 +2108,10 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
mHandler.obtainMessage(MSG_ON_GESTURE, gestureId, 0).sendToTarget();
}
+ public void notifyClearAccessibilityNodeInfoCache() {
+ mHandler.sendEmptyMessage(MSG_CLEAR_ACCESSIBILITY_NODE_INFO_CACHE);
+ }
+
private void notifyGestureInternal(int gestureId) {
IAccessibilityServiceClient listener = mServiceInterface;
if (listener != null) {
@@ -2094,6 +2124,18 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
}
}
+ private void notifyClearAccessibilityNodeInfoCacheInternal() {
+ IAccessibilityServiceClient listener = mServiceInterface;
+ if (listener != null) {
+ try {
+ listener.clearAccessibilityNodeInfoCache();
+ } catch (RemoteException re) {
+ Slog.e(LOG_TAG, "Error during requesting accessibility info cache"
+ + " to be cleared.", re);
+ }
+ }
+ }
+
private void sendDownAndUpKeyEvents(int keyCode) {
final long token = Binder.clearCallingIdentity();
@@ -2176,20 +2218,23 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
return accessibilityWindowId;
}
- private float getCompatibilityScale(int windowId) {
+ private MagnificationSpec getCompatibleMagnificationSpec(int windowId) {
try {
- IBinder windowToken = mGlobalWindowTokens.get(windowId);
- if (windowToken != null) {
- return mWindowManagerService.getWindowCompatibilityScale(windowToken);
+ if (mMagnificationMediator == null) {
+ mMagnificationMediator = mWindowManagerService
+ .getDisplayMagnificationMediator();
}
- windowToken = getCurrentUserStateLocked().mWindowTokens.get(windowId);
+ IBinder windowToken = mGlobalWindowTokens.get(windowId);
+ if (windowToken == null) {
+ windowToken = getCurrentUserStateLocked().mWindowTokens.get(windowId);
+ }
if (windowToken != null) {
- return mWindowManagerService.getWindowCompatibilityScale(windowToken);
+ return mMagnificationMediator.getCompatibleMagnificationSpec(windowToken);
}
} catch (RemoteException re) {
/* ignore */
}
- return 1.0f;
+ return null;
}
}
diff --git a/services/java/com/android/server/accessibility/ScreenMagnifier.java b/services/java/com/android/server/accessibility/ScreenMagnifier.java
index 482bff5..e5f0924 100644
--- a/services/java/com/android/server/accessibility/ScreenMagnifier.java
+++ b/services/java/com/android/server/accessibility/ScreenMagnifier.java
@@ -21,6 +21,7 @@ import android.animation.Animator.AnimatorListener;
import android.animation.ObjectAnimator;
import android.animation.TypeEvaluator;
import android.animation.ValueAnimator;
+import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -48,20 +49,19 @@ import android.view.DisplayInfo;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.Gravity;
-import android.view.IDisplayContentChangeListener;
+import android.view.IDisplayMagnificationController;
+import android.view.IDisplayMagnificationMediator;
import android.view.IWindowManager;
+import android.view.MagnificationSpec;
import android.view.MotionEvent;
import android.view.MotionEvent.PointerCoords;
import android.view.MotionEvent.PointerProperties;
import android.view.ScaleGestureDetector;
import android.view.ScaleGestureDetector.OnScaleGestureListener;
-import android.view.Surface;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
-import android.view.WindowInfo;
import android.view.WindowManager;
-import android.view.WindowManagerPolicy;
import android.view.accessibility.AccessibilityEvent;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.Interpolator;
@@ -69,9 +69,6 @@ import android.view.animation.Interpolator;
import com.android.internal.R;
import com.android.internal.os.SomeArgs;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
import java.util.Locale;
/**
@@ -91,7 +88,7 @@ import java.util.Locale;
* moving finger will be magnified to fit the screen. For example, if the
* screen was not magnified and the user triple taps and holds the screen
* would magnify and the viewport will follow the user's finger. When the
- * finger goes up the screen will clear zoom out. If the same user interaction
+ * finger goes up the screen will zoom out. If the same user interaction
* is performed when the screen is magnified, the viewport movement will
* be the same but when the finger goes up the screen will stay magnified.
* In other words, the initial magnified state is sticky.
@@ -106,26 +103,25 @@ import java.util.Locale;
* to pan the viewport. Note that in this mode the content is panned as
* opposed to the viewport dragging mode in which the viewport is moved.
*
- * 5. When in a permanent magnified state the user can use three or more
+ * 5. When in a permanent magnified state the user can use two or more
* fingers to change the magnification scale which will become the current
* default magnification scale. The next time the user magnifies the same
* magnification scale would be used.
*
* 6. The magnification scale will be persisted in settings and in the cloud.
*/
-public final class ScreenMagnifier implements EventStreamTransformation {
+public final class ScreenMagnifier extends IDisplayMagnificationController.Stub
+ implements EventStreamTransformation {
+
+ private static final String LOG_TAG = ScreenMagnifier.class.getSimpleName();
private static final boolean DEBUG_STATE_TRANSITIONS = false;
private static final boolean DEBUG_DETECTING = false;
- private static final boolean DEBUG_TRANSFORMATION = false;
+ private static final boolean DEBUG_SET_MAGNIFICATION_SPEC = false;
private static final boolean DEBUG_PANNING = false;
private static final boolean DEBUG_SCALING = false;
- private static final boolean DEBUG_VIEWPORT_WINDOW = false;
- private static final boolean DEBUG_WINDOW_TRANSITIONS = false;
- private static final boolean DEBUG_ROTATION = false;
private static final boolean DEBUG_MAGNIFICATION_CONTROLLER = false;
-
- private static final String LOG_TAG = ScreenMagnifier.class.getSimpleName();
+ private static final boolean DEBUG_VIEWPORT_WINDOW = false;
private static final int STATE_DELEGATING = 1;
private static final int STATE_DETECTING = 2;
@@ -133,27 +129,30 @@ public final class ScreenMagnifier implements EventStreamTransformation {
private static final int STATE_MAGNIFIED_INTERACTION = 4;
private static final float DEFAULT_MAGNIFICATION_SCALE = 2.0f;
- private static final int DEFAULT_SCREEN_MAGNIFICATION_AUTO_UPDATE = 1;
- private static final float DEFAULT_WINDOW_ANIMATION_SCALE = 1.0f;
-
private static final int MULTI_TAP_TIME_SLOP_ADJUSTMENT = 50;
- private final IWindowManager mWindowManagerService = IWindowManager.Stub.asInterface(
- ServiceManager.getService("window"));
- private final WindowManager mWindowManager;
- private final DisplayProvider mDisplayProvider;
+ private static final int MESSAGE_ON_MAGNIFIED_FRAME_CHANGED = 1;
+ private static final int MESSAGE_ON_RECTANGLE_ON_SCREEN_REQUESTED = 2;
+ private static final int MESSAGE_ON_USER_CONTEXT_CHANGED = 3;
+ private static final int MESSAGE_ON_ROTATION_CHANGED = 4;
+ private static final int MESSAGE_SHOW_VIEWPORT_FRAME = 5;
- private final DetectingStateHandler mDetectingStateHandler = new DetectingStateHandler();
- private final MagnifiedContentInteractonStateHandler mMagnifiedContentInteractonStateHandler;
- private final StateViewportDraggingHandler mStateViewportDraggingHandler =
- new StateViewportDraggingHandler();
+ private static final int DEFAULT_SCREEN_MAGNIFICATION_AUTO_UPDATE = 1;
+ private static final float DEFAULT_WINDOW_ANIMATION_SCALE = 1.0f;
- private final Interpolator mInterpolator = new DecelerateInterpolator(2.5f);
+ private final Rect mTempRect = new Rect();
+ private final Rect mTempRect1 = new Rect();
+ private final Context mContext;
private final MagnificationController mMagnificationController;
- private final DisplayContentObserver mDisplayContentObserver;
private final ScreenStateObserver mScreenStateObserver;
- private final Viewport mViewport;
+ private final ViewportWindow mViewportWindow;
+
+ private final DetectingStateHandler mDetectingStateHandler;
+ private final MagnifiedContentInteractonStateHandler mMagnifiedContentInteractonStateHandler;
+ private final StateViewportDraggingHandler mStateViewportDraggingHandler;
+
+ private final AccessibilityManagerService mAms;
private final int mTapTimeSlop = ViewConfiguration.getTapTimeout();
private final int mMultiTapTimeSlop =
@@ -161,11 +160,12 @@ public final class ScreenMagnifier implements EventStreamTransformation {
private final int mTapDistanceSlop;
private final int mMultiTapDistanceSlop;
- private final int mShortAnimationDuration;
- private final int mLongAnimationDuration;
+ private final long mLongAnimationDuration;
private final float mWindowAnimationScale;
- private final Context mContext;
+ private final Rect mMagnifiedFrame = new Rect();
+
+ private IDisplayMagnificationMediator mDisplayMagnifier;
private EventStreamTransformation mNext;
@@ -178,12 +178,46 @@ public final class ScreenMagnifier implements EventStreamTransformation {
private long mDelegatingStateDownTime;
- public ScreenMagnifier(Context context) {
+ private final Handler mHandler = new Handler() {
+ @Override
+ public void handleMessage(Message message) {
+ switch (message.what) {
+ case MESSAGE_ON_MAGNIFIED_FRAME_CHANGED: {
+ SomeArgs args = (SomeArgs) message.obj;
+ final int left = args.argi1;
+ final int top = args.argi2;
+ final int right = args.argi3;
+ final int bottom = args.argi4;
+ handleOnMagnifiedFrameChanged(left, top, right, bottom);
+ args.recycle();
+ } break;
+ case MESSAGE_ON_RECTANGLE_ON_SCREEN_REQUESTED: {
+ SomeArgs args = (SomeArgs) message.obj;
+ final int left = args.argi1;
+ final int top = args.argi2;
+ final int right = args.argi3;
+ final int bottom = args.argi4;
+ handleOnRectangleOnScreenRequested(left, top, right, bottom);
+ args.recycle();
+ } break;
+ case MESSAGE_ON_USER_CONTEXT_CHANGED: {
+ handleOnUserContextChanged();
+ } break;
+ case MESSAGE_ON_ROTATION_CHANGED: {
+ final int rotation = message.arg1;
+ handleOnRotationChanged(rotation);
+ } break;
+ case MESSAGE_SHOW_VIEWPORT_FRAME: {
+ mViewportWindow.setShown(true, true);
+ } break;
+ }
+ }
+ };
+
+ public ScreenMagnifier(Context context, int displayId, AccessibilityManagerService service) {
mContext = context;
- mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
+ mAms = service;
- mShortAnimationDuration = context.getResources().getInteger(
- com.android.internal.R.integer.config_shortAnimTime);
mLongAnimationDuration = context.getResources().getInteger(
com.android.internal.R.integer.config_longAnimTime);
mTapDistanceSlop = ViewConfiguration.get(context).getScaledTouchSlop();
@@ -191,23 +225,132 @@ public final class ScreenMagnifier implements EventStreamTransformation {
mWindowAnimationScale = Settings.Global.getFloat(context.getContentResolver(),
Settings.Global.WINDOW_ANIMATION_SCALE, DEFAULT_WINDOW_ANIMATION_SCALE);
- mMagnificationController = new MagnificationController(mShortAnimationDuration);
- mDisplayProvider = new DisplayProvider(context, mWindowManager);
- mViewport = new Viewport(mContext, mWindowManager, mWindowManagerService,
- mDisplayProvider, mInterpolator, mShortAnimationDuration);
- mDisplayContentObserver = new DisplayContentObserver(mContext, mViewport,
- mMagnificationController, mWindowManagerService, mDisplayProvider,
- mLongAnimationDuration, mWindowAnimationScale);
- mScreenStateObserver = new ScreenStateObserver(mContext, mViewport,
- mMagnificationController);
-
+ mDetectingStateHandler = new DetectingStateHandler();
+ mStateViewportDraggingHandler = new StateViewportDraggingHandler();
mMagnifiedContentInteractonStateHandler = new MagnifiedContentInteractonStateHandler(
context);
+ mMagnificationController = new MagnificationController(mLongAnimationDuration);
+ mViewportWindow = new ViewportWindow(context, displayId);
+ mScreenStateObserver = new ScreenStateObserver(context, mMagnificationController,
+ mViewportWindow);
+
+ try {
+ IWindowManager windowManagerService = IWindowManager.Stub.asInterface(
+ ServiceManager.getService("window"));
+ mDisplayMagnifier = windowManagerService.getDisplayMagnificationMediator();
+ mDisplayMagnifier.addController(Display.DEFAULT_DISPLAY, this);
+ } catch (RemoteException re) {
+ /* ignore */
+ }
+
transitionToState(STATE_DETECTING);
}
@Override
+ public void onMagnifedFrameChanged(int left, int top, int right, int bottom) {
+ SomeArgs args = SomeArgs.obtain();
+ args.argi1 = left;
+ args.argi2 = top;
+ args.argi3 = right;
+ args.argi4 = bottom;
+ mHandler.obtainMessage(MESSAGE_ON_MAGNIFIED_FRAME_CHANGED, args).sendToTarget();
+ }
+
+ private void handleOnMagnifiedFrameChanged(int left, int top, int right, int bottom) {
+ mMagnifiedFrame.set(left, top, right, bottom);
+ mViewportWindow.setBounds(mMagnifiedFrame, mMagnificationController.isMagnifying());
+ mAms.onMagnificationStateChanged();
+ }
+
+ @Override
+ public void onRectangleOnScreenRequested(int left, int top, int right, int bottom) {
+ SomeArgs args = SomeArgs.obtain();
+ args.argi1 = left;
+ args.argi2 = top;
+ args.argi3 = right;
+ args.argi4 = bottom;
+ mHandler.obtainMessage(MESSAGE_ON_RECTANGLE_ON_SCREEN_REQUESTED, args).sendToTarget();
+ }
+
+ private void handleOnRectangleOnScreenRequested(int left, int top, int right, int bottom) {
+ Rect rectangle = mTempRect;
+ rectangle.set(left, top, right, bottom);
+ if (!Rect.intersects(rectangle, mMagnifiedFrame)) {
+ return;
+ }
+ Rect magnifFrameInScreenCoords = mTempRect1;
+ getMagnifiedFrameInContentCoords(magnifFrameInScreenCoords);
+ final float scrollX;
+ final float scrollY;
+ if (rectangle.width() > magnifFrameInScreenCoords.width()) {
+ final int direction = TextUtils.getLayoutDirectionFromLocale(Locale.getDefault());
+ if (direction == View.LAYOUT_DIRECTION_LTR) {
+ scrollX = rectangle.left - magnifFrameInScreenCoords.left;
+ } else {
+ scrollX = rectangle.right - magnifFrameInScreenCoords.right;
+ }
+ } else if (rectangle.left < magnifFrameInScreenCoords.left) {
+ scrollX = rectangle.left - magnifFrameInScreenCoords.left;
+ } else if (rectangle.right > magnifFrameInScreenCoords.right) {
+ scrollX = rectangle.right - magnifFrameInScreenCoords.right;
+ } else {
+ scrollX = 0;
+ }
+ if (rectangle.height() > magnifFrameInScreenCoords.height()) {
+ scrollY = rectangle.top - magnifFrameInScreenCoords.top;
+ } else if (rectangle.top < magnifFrameInScreenCoords.top) {
+ scrollY = rectangle.top - magnifFrameInScreenCoords.top;
+ } else if (rectangle.bottom > magnifFrameInScreenCoords.bottom) {
+ scrollY = rectangle.bottom - magnifFrameInScreenCoords.bottom;
+ } else {
+ scrollY = 0;
+ }
+ final float scale = mMagnificationController.getScale();
+ mMagnificationController.offsetMagnifiedRegionCenter(scrollX * scale, scrollY * scale);
+ }
+
+ private void getMagnifiedFrameInContentCoords(Rect rect) {
+ MagnificationSpec spec = mMagnificationController.getMagnificationSpec();
+ rect.set(mMagnifiedFrame);
+ rect.offset((int) -spec.offsetX, (int) -spec.offsetY);
+ rect.scale(1.0f / spec.scale);
+ }
+
+ @Override
+ public void onRotationChanged(int rotation) {
+ mHandler.obtainMessage(MESSAGE_ON_ROTATION_CHANGED, rotation, 0).sendToTarget();
+ }
+
+ private void handleOnRotationChanged(int rotation) {
+ resetMagnificationIfNeeded();
+ mViewportWindow.setShown(false, false);
+ mViewportWindow.rotationChanged();
+ if (mMagnificationController.isMagnifying()) {
+ final long delay = (long) (2 * mLongAnimationDuration * mWindowAnimationScale);
+ Message message = mHandler.obtainMessage(MESSAGE_SHOW_VIEWPORT_FRAME);
+ mHandler.sendMessageDelayed(message, delay);
+ }
+ }
+
+ @Override
+ public void onUserContextChanged() {
+ mHandler.sendEmptyMessage(MESSAGE_ON_USER_CONTEXT_CHANGED);
+ }
+
+ private void handleOnUserContextChanged() {
+ resetMagnificationIfNeeded();
+ }
+
+ private void resetMagnificationIfNeeded() {
+ if (mMagnificationController.isMagnifying()
+ && isScreenMagnificationAutoUpdateEnabled(mContext)) {
+ mMagnificationController.reset(true);
+ mViewportWindow.setShown(false, true);
+ }
+ }
+
+ @Override
public void onMotionEvent(MotionEvent event, MotionEvent rawEvent,
int policyFlags) {
mMagnifiedContentInteractonStateHandler.onMotionEvent(event);
@@ -257,12 +400,8 @@ public final class ScreenMagnifier implements EventStreamTransformation {
@Override
public void onDestroy() {
- mMagnificationController.setScaleAndMagnifiedRegionCenter(1.0f,
- 0, 0, true);
- mViewport.setFrameShown(false, true);
- mDisplayProvider.destroy();
- mDisplayContentObserver.destroy();
mScreenStateObserver.destroy();
+ mViewportWindow.destroy();
}
private void handleMotionEventStateDelegating(MotionEvent event,
@@ -284,10 +423,10 @@ public final class ScreenMagnifier implements EventStreamTransformation {
final float eventX = event.getX();
final float eventY = event.getY();
if (mMagnificationController.isMagnifying()
- && mViewport.getBounds().contains((int) eventX, (int) eventY)) {
+ && mMagnifiedFrame.contains((int) eventX, (int) eventY)) {
final float scale = mMagnificationController.getScale();
- final float scaledOffsetX = mMagnificationController.getScaledOffsetX();
- final float scaledOffsetY = mMagnificationController.getScaledOffsetY();
+ final float scaledOffsetX = mMagnificationController.getOffsetX();
+ final float scaledOffsetY = mMagnificationController.getOffsetY();
final int pointerCount = event.getPointerCount();
PointerCoords[] coords = getTempPointerCoordsWithMinSize(pointerCount);
PointerProperties[] properties = getTempPointerPropertiesWithMinSize(pointerCount);
@@ -412,16 +551,11 @@ public final class ScreenMagnifier implements EventStreamTransformation {
if (mCurrentState != STATE_MAGNIFIED_INTERACTION) {
return true;
}
- final float scale = mMagnificationController.getScale();
- final float scrollX = distanceX / scale;
- final float scrollY = distanceY / scale;
- final float centerX = mMagnificationController.getMagnifiedRegionCenterX() + scrollX;
- final float centerY = mMagnificationController.getMagnifiedRegionCenterY() + scrollY;
if (DEBUG_PANNING) {
- Slog.i(LOG_TAG, "Panned content by scrollX: " + scrollX
- + " scrollY: " + scrollY);
+ Slog.i(LOG_TAG, "Panned content by scrollX: " + distanceX
+ + " scrollY: " + distanceY);
}
- mMagnificationController.setMagnifiedRegionCenter(centerX, centerY, false);
+ mMagnificationController.offsetMagnifiedRegionCenter(distanceX, distanceY);
return true;
}
@@ -485,7 +619,7 @@ public final class ScreenMagnifier implements EventStreamTransformation {
}
final float eventX = event.getX();
final float eventY = event.getY();
- if (mViewport.getBounds().contains((int) eventX, (int) eventY)) {
+ if (mMagnifiedFrame.contains((int) eventX, (int) eventY)) {
if (mLastMoveOutsideMagnifiedRegion) {
mLastMoveOutsideMagnifiedRegion = false;
mMagnificationController.setMagnifiedRegionCenter(eventX,
@@ -501,7 +635,7 @@ public final class ScreenMagnifier implements EventStreamTransformation {
case MotionEvent.ACTION_UP: {
if (!mTranslationEnabledBeforePan) {
mMagnificationController.reset(true);
- mViewport.setFrameShown(false, true);
+ mViewportWindow.setShown(false, true);
}
clear();
transitionToState(STATE_DETECTING);
@@ -559,7 +693,7 @@ public final class ScreenMagnifier implements EventStreamTransformation {
switch (action) {
case MotionEvent.ACTION_DOWN: {
mHandler.removeMessages(MESSAGE_TRANSITION_TO_DELEGATING_STATE);
- if (!mViewport.getBounds().contains((int) event.getX(),
+ if (!mMagnifiedFrame.contains((int) event.getX(),
(int) event.getY())) {
transitionToDelegatingStateAndClear();
return;
@@ -601,7 +735,7 @@ public final class ScreenMagnifier implements EventStreamTransformation {
return;
}
mHandler.removeMessages(MESSAGE_ON_ACTION_TAP_AND_HOLD);
- if (!mViewport.getBounds().contains((int) event.getX(), (int) event.getY())) {
+ if (!mMagnifiedFrame.contains((int) event.getX(), (int) event.getY())) {
transitionToDelegatingStateAndClear();
return;
}
@@ -727,10 +861,10 @@ public final class ScreenMagnifier implements EventStreamTransformation {
if (!mMagnificationController.isMagnifying()) {
mMagnificationController.setScaleAndMagnifiedRegionCenter(getPersistedScale(),
up.getX(), up.getY(), true);
- mViewport.setFrameShown(true, true);
+ mViewportWindow.setShown(true, true);
} else {
mMagnificationController.reset(true);
- mViewport.setFrameShown(false, true);
+ mViewportWindow.setShown(false, true);
}
}
@@ -742,7 +876,7 @@ public final class ScreenMagnifier implements EventStreamTransformation {
mTranslationEnabledBeforePan = mMagnificationController.isMagnifying();
mMagnificationController.setScaleAndMagnifiedRegionCenter(getPersistedScale(),
down.getX(), down.getY(), true);
- mViewport.setFrameShown(true, true);
+ mViewportWindow.setShown(true, true);
transitionToState(STATE_VIEWPORT_DRAGGING);
}
}
@@ -837,443 +971,35 @@ public final class ScreenMagnifier implements EventStreamTransformation {
}
}
- private static final class ScreenStateObserver extends BroadcastReceiver {
-
- private static final int MESSAGE_ON_SCREEN_STATE_CHANGE = 1;
-
- private final Handler mHandler = new Handler() {
- @Override
- public void handleMessage(Message message) {
- switch (message.what) {
- case MESSAGE_ON_SCREEN_STATE_CHANGE: {
- String action = (String) message.obj;
- handleOnScreenStateChange(action);
- } break;
- }
- }
- };
-
- private final Context mContext;
- private final Viewport mViewport;
- private final MagnificationController mMagnificationController;
-
- public ScreenStateObserver(Context context, Viewport viewport,
- MagnificationController magnificationController) {
- mContext = context;
- mViewport = viewport;
- mMagnificationController = magnificationController;
- mContext.registerReceiver(this, new IntentFilter(Intent.ACTION_SCREEN_OFF));
- }
-
- public void destroy() {
- mContext.unregisterReceiver(this);
- }
-
- @Override
- public void onReceive(Context context, Intent intent) {
- mHandler.obtainMessage(MESSAGE_ON_SCREEN_STATE_CHANGE,
- intent.getAction()).sendToTarget();
- }
-
- private void handleOnScreenStateChange(String action) {
- if (action.equals(Intent.ACTION_SCREEN_OFF)
- && mMagnificationController.isMagnifying()
- && isScreenMagnificationAutoUpdateEnabled(mContext)) {
- mMagnificationController.reset(false);
- mViewport.setFrameShown(false, false);
- }
- }
- }
-
- private static final class DisplayContentObserver {
-
- private static final int MESSAGE_SHOW_VIEWPORT_FRAME = 1;
- private static final int MESSAGE_ON_RECTANGLE_ON_SCREEN_REQUESTED = 3;
- private static final int MESSAGE_ON_WINDOW_TRANSITION = 4;
- private static final int MESSAGE_ON_ROTATION_CHANGED = 5;
- private static final int MESSAGE_ON_WINDOW_LAYERS_CHANGED = 6;
-
- private final Handler mHandler = new MyHandler();
-
- private final Rect mTempRect = new Rect();
-
- private final IDisplayContentChangeListener mDisplayContentChangeListener;
-
- private final Context mContext;
- private final Viewport mViewport;
- private final MagnificationController mMagnificationController;
- private final IWindowManager mWindowManagerService;
- private final DisplayProvider mDisplayProvider;
- private final long mLongAnimationDuration;
- private final float mWindowAnimationScale;
-
- public DisplayContentObserver(Context context, Viewport viewport,
- MagnificationController magnificationController,
- IWindowManager windowManagerService, DisplayProvider displayProvider,
- long longAnimationDuration, float windowAnimationScale) {
- mContext = context;
- mViewport = viewport;
- mMagnificationController = magnificationController;
- mWindowManagerService = windowManagerService;
- mDisplayProvider = displayProvider;
- mLongAnimationDuration = longAnimationDuration;
- mWindowAnimationScale = windowAnimationScale;
-
- mDisplayContentChangeListener = new IDisplayContentChangeListener.Stub() {
- @Override
- public void onWindowTransition(int displayId, int transition, WindowInfo info) {
- mHandler.obtainMessage(MESSAGE_ON_WINDOW_TRANSITION,
- transition, 0, WindowInfo.obtain(info)).sendToTarget();
- }
-
- @Override
- public void onRectangleOnScreenRequested(int dsiplayId, Rect rectangle,
- boolean immediate) {
- SomeArgs args = SomeArgs.obtain();
- args.argi1 = rectangle.left;
- args.argi2 = rectangle.top;
- args.argi3 = rectangle.right;
- args.argi4 = rectangle.bottom;
- mHandler.obtainMessage(MESSAGE_ON_RECTANGLE_ON_SCREEN_REQUESTED, 0,
- immediate ? 1 : 0, args).sendToTarget();
- }
-
- @Override
- public void onRotationChanged(int rotation) throws RemoteException {
- mHandler.obtainMessage(MESSAGE_ON_ROTATION_CHANGED, rotation, 0)
- .sendToTarget();
- }
-
- @Override
- public void onWindowLayersChanged(int displayId) throws RemoteException {
- mHandler.sendEmptyMessage(MESSAGE_ON_WINDOW_LAYERS_CHANGED);
- }
- };
-
- try {
- mWindowManagerService.addDisplayContentChangeListener(
- mDisplayProvider.getDisplay().getDisplayId(),
- mDisplayContentChangeListener);
- } catch (RemoteException re) {
- /* ignore */
- }
- }
-
- public void destroy() {
- try {
- mWindowManagerService.removeDisplayContentChangeListener(
- mDisplayProvider.getDisplay().getDisplayId(),
- mDisplayContentChangeListener);
- } catch (RemoteException re) {
- /* ignore*/
- }
- }
-
- private void handleOnRotationChanged(int rotation) {
- if (DEBUG_ROTATION) {
- Slog.i(LOG_TAG, "Rotation: " + rotationToString(rotation));
- }
- resetMagnificationIfNeeded();
- mViewport.setFrameShown(false, false);
- mViewport.rotationChanged();
- mViewport.recomputeBounds(false);
- if (mMagnificationController.isMagnifying()) {
- final long delay = (long) (2 * mLongAnimationDuration * mWindowAnimationScale);
- Message message = mHandler.obtainMessage(MESSAGE_SHOW_VIEWPORT_FRAME);
- mHandler.sendMessageDelayed(message, delay);
- }
- }
-
- private void handleOnWindowTransition(int transition, WindowInfo info) {
- if (DEBUG_WINDOW_TRANSITIONS) {
- Slog.i(LOG_TAG, "Window transitioning: "
- + windowTransitionToString(transition));
- }
- try {
- final boolean magnifying = mMagnificationController.isMagnifying();
- if (magnifying) {
- switch (transition) {
- case WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN:
- case WindowManagerPolicy.TRANSIT_TASK_OPEN:
- case WindowManagerPolicy.TRANSIT_TASK_TO_FRONT:
- case WindowManagerPolicy.TRANSIT_WALLPAPER_OPEN:
- case WindowManagerPolicy.TRANSIT_WALLPAPER_CLOSE:
- case WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_OPEN: {
- resetMagnificationIfNeeded();
- }
- }
- }
- if (info.type == WindowManager.LayoutParams.TYPE_NAVIGATION_BAR
- || info.type == WindowManager.LayoutParams.TYPE_INPUT_METHOD
- || info.type == WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG
- || info.type == WindowManager.LayoutParams.TYPE_KEYGUARD
- || info.type == WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG) {
- switch (transition) {
- case WindowManagerPolicy.TRANSIT_ENTER:
- case WindowManagerPolicy.TRANSIT_SHOW:
- case WindowManagerPolicy.TRANSIT_EXIT:
- case WindowManagerPolicy.TRANSIT_HIDE: {
- mViewport.recomputeBounds(mMagnificationController.isMagnifying());
- } break;
- }
- }
- switch (transition) {
- case WindowManagerPolicy.TRANSIT_ENTER:
- case WindowManagerPolicy.TRANSIT_SHOW: {
- if (!magnifying || !isScreenMagnificationAutoUpdateEnabled(mContext)) {
- break;
- }
- final int type = info.type;
- switch (type) {
- // TODO: Are these all the windows we want to make
- // visible when they appear on the screen?
- // Do we need to take some of them out?
- case WindowManager.LayoutParams.TYPE_APPLICATION:
- case WindowManager.LayoutParams.TYPE_APPLICATION_PANEL:
- case WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA:
- case WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL:
- case WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG:
- case WindowManager.LayoutParams.TYPE_SEARCH_BAR:
- case WindowManager.LayoutParams.TYPE_PHONE:
- case WindowManager.LayoutParams.TYPE_SYSTEM_ALERT:
- case WindowManager.LayoutParams.TYPE_TOAST:
- case WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY:
- case WindowManager.LayoutParams.TYPE_PRIORITY_PHONE:
- case WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG:
- case WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG:
- case WindowManager.LayoutParams.TYPE_SYSTEM_ERROR:
- case WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY:
- case WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL:
- case WindowManager.LayoutParams.TYPE_RECENTS_OVERLAY: {
- Rect magnifiedRegionBounds = mMagnificationController
- .getMagnifiedRegionBounds();
- Rect touchableRegion = info.touchableRegion;
- if (!magnifiedRegionBounds.intersect(touchableRegion)) {
- ensureRectangleInMagnifiedRegionBounds(
- magnifiedRegionBounds, touchableRegion);
- }
- } break;
- } break;
- }
- }
- } finally {
- if (info != null) {
- info.recycle();
- }
- }
- }
-
- private void handleOnRectangleOnScreenRequested(Rect rectangle, boolean immediate) {
- if (!mMagnificationController.isMagnifying()) {
- return;
- }
- Rect magnifiedRegionBounds = mMagnificationController.getMagnifiedRegionBounds();
- if (magnifiedRegionBounds.contains(rectangle)) {
- return;
- }
- ensureRectangleInMagnifiedRegionBounds(magnifiedRegionBounds, rectangle);
- }
-
- private void ensureRectangleInMagnifiedRegionBounds(Rect magnifiedRegionBounds,
- Rect rectangle) {
- if (!Rect.intersects(rectangle, mViewport.getBounds())) {
- return;
- }
- final float scrollX;
- final float scrollY;
- if (rectangle.width() > magnifiedRegionBounds.width()) {
- final int direction = TextUtils.getLayoutDirectionFromLocale(Locale.getDefault());
- if (direction == View.LAYOUT_DIRECTION_LTR) {
- scrollX = rectangle.left - magnifiedRegionBounds.left;
- } else {
- scrollX = rectangle.right - magnifiedRegionBounds.right;
- }
- } else if (rectangle.left < magnifiedRegionBounds.left) {
- scrollX = rectangle.left - magnifiedRegionBounds.left;
- } else if (rectangle.right > magnifiedRegionBounds.right) {
- scrollX = rectangle.right - magnifiedRegionBounds.right;
- } else {
- scrollX = 0;
- }
- if (rectangle.height() > magnifiedRegionBounds.height()) {
- scrollY = rectangle.top - magnifiedRegionBounds.top;
- } else if (rectangle.top < magnifiedRegionBounds.top) {
- scrollY = rectangle.top - magnifiedRegionBounds.top;
- } else if (rectangle.bottom > magnifiedRegionBounds.bottom) {
- scrollY = rectangle.bottom - magnifiedRegionBounds.bottom;
- } else {
- scrollY = 0;
- }
- final float viewportCenterX = mMagnificationController.getMagnifiedRegionCenterX()
- + scrollX;
- final float viewportCenterY = mMagnificationController.getMagnifiedRegionCenterY()
- + scrollY;
- mMagnificationController.setMagnifiedRegionCenter(viewportCenterX, viewportCenterY,
- true);
- }
-
- private void resetMagnificationIfNeeded() {
- if (mMagnificationController.isMagnifying()
- && isScreenMagnificationAutoUpdateEnabled(mContext)) {
- mMagnificationController.reset(true);
- mViewport.setFrameShown(false, true);
- }
- }
-
- private String windowTransitionToString(int transition) {
- switch (transition) {
- case WindowManagerPolicy.TRANSIT_UNSET: {
- return "TRANSIT_UNSET";
- }
- case WindowManagerPolicy.TRANSIT_NONE: {
- return "TRANSIT_NONE";
- }
- case WindowManagerPolicy.TRANSIT_ENTER: {
- return "TRANSIT_ENTER";
- }
- case WindowManagerPolicy.TRANSIT_EXIT: {
- return "TRANSIT_EXIT";
- }
- case WindowManagerPolicy.TRANSIT_SHOW: {
- return "TRANSIT_SHOW";
- }
- case WindowManagerPolicy.TRANSIT_EXIT_MASK: {
- return "TRANSIT_EXIT_MASK";
- }
- case WindowManagerPolicy.TRANSIT_PREVIEW_DONE: {
- return "TRANSIT_PREVIEW_DONE";
- }
- case WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN: {
- return "TRANSIT_ACTIVITY_OPEN";
- }
- case WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE: {
- return "TRANSIT_ACTIVITY_CLOSE";
- }
- case WindowManagerPolicy.TRANSIT_TASK_OPEN: {
- return "TRANSIT_TASK_OPEN";
- }
- case WindowManagerPolicy.TRANSIT_TASK_CLOSE: {
- return "TRANSIT_TASK_CLOSE";
- }
- case WindowManagerPolicy.TRANSIT_TASK_TO_FRONT: {
- return "TRANSIT_TASK_TO_FRONT";
- }
- case WindowManagerPolicy.TRANSIT_TASK_TO_BACK: {
- return "TRANSIT_TASK_TO_BACK";
- }
- case WindowManagerPolicy.TRANSIT_WALLPAPER_CLOSE: {
- return "TRANSIT_WALLPAPER_CLOSE";
- }
- case WindowManagerPolicy.TRANSIT_WALLPAPER_OPEN: {
- return "TRANSIT_WALLPAPER_OPEN";
- }
- case WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_OPEN: {
- return "TRANSIT_WALLPAPER_INTRA_OPEN";
- }
- case WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_CLOSE: {
- return "TRANSIT_WALLPAPER_INTRA_CLOSE";
- }
- default: {
- return "<UNKNOWN>";
- }
- }
- }
-
- private String rotationToString(int rotation) {
- switch (rotation) {
- case Surface.ROTATION_0: {
- return "ROTATION_0";
- }
- case Surface.ROTATION_90: {
- return "ROATATION_90";
- }
- case Surface.ROTATION_180: {
- return "ROATATION_180";
- }
- case Surface.ROTATION_270: {
- return "ROATATION_270";
- }
- default: {
- throw new IllegalArgumentException("Invalid rotation: "
- + rotation);
- }
- }
- }
-
- private final class MyHandler extends Handler {
- @Override
- public void handleMessage(Message message) {
- final int action = message.what;
- switch (action) {
- case MESSAGE_SHOW_VIEWPORT_FRAME: {
- mViewport.setFrameShown(true, true);
- } break;
- case MESSAGE_ON_RECTANGLE_ON_SCREEN_REQUESTED: {
- SomeArgs args = (SomeArgs) message.obj;
- try {
- mTempRect.set(args.argi1, args.argi2, args.argi3, args.argi4);
- final boolean immediate = (message.arg1 == 1);
- handleOnRectangleOnScreenRequested(mTempRect, immediate);
- } finally {
- args.recycle();
- }
- } break;
- case MESSAGE_ON_WINDOW_TRANSITION: {
- final int transition = message.arg1;
- WindowInfo info = (WindowInfo) message.obj;
- handleOnWindowTransition(transition, info);
- } break;
- case MESSAGE_ON_ROTATION_CHANGED: {
- final int rotation = message.arg1;
- handleOnRotationChanged(rotation);
- } break;
- case MESSAGE_ON_WINDOW_LAYERS_CHANGED: {
- mViewport.recomputeBounds(mMagnificationController.isMagnifying());
- } break;
- default: {
- throw new IllegalArgumentException("Unknown message: " + action);
- }
- }
- }
- }
- }
-
private final class MagnificationController {
- private static final String PROPERTY_NAME_ACCESSIBILITY_TRANSFORMATION =
- "accessibilityTransformation";
+ private static final String PROPERTY_NAME_MAGNIFICATION_SPEC =
+ "magnificationSpec";
- private final MagnificationSpec mSentMagnificationSpec = new MagnificationSpec();
+ private final MagnificationSpec mSentMagnificationSpec = MagnificationSpec.obtain();
- private final MagnificationSpec mCurrentMagnificationSpec = new MagnificationSpec();
+ private final MagnificationSpec mCurrentMagnificationSpec = MagnificationSpec.obtain();
private final Rect mTempRect = new Rect();
private final ValueAnimator mTransformationAnimator;
- public MagnificationController(int animationDuration) {
+ public MagnificationController(long animationDuration) {
Property<MagnificationController, MagnificationSpec> property =
Property.of(MagnificationController.class, MagnificationSpec.class,
- PROPERTY_NAME_ACCESSIBILITY_TRANSFORMATION);
+ PROPERTY_NAME_MAGNIFICATION_SPEC);
TypeEvaluator<MagnificationSpec> evaluator = new TypeEvaluator<MagnificationSpec>() {
- private final MagnificationSpec mTempTransformationSpec = new MagnificationSpec();
+ private final MagnificationSpec mTempTransformationSpec =
+ MagnificationSpec.obtain();
@Override
public MagnificationSpec evaluate(float fraction, MagnificationSpec fromSpec,
MagnificationSpec toSpec) {
MagnificationSpec result = mTempTransformationSpec;
- result.mScale = fromSpec.mScale
- + (toSpec.mScale - fromSpec.mScale) * fraction;
- result.mMagnifiedRegionCenterX = fromSpec.mMagnifiedRegionCenterX
- + (toSpec.mMagnifiedRegionCenterX - fromSpec.mMagnifiedRegionCenterX)
- * fraction;
- result.mMagnifiedRegionCenterY = fromSpec.mMagnifiedRegionCenterY
- + (toSpec.mMagnifiedRegionCenterY - fromSpec.mMagnifiedRegionCenterY)
- * fraction;
- result.mScaledOffsetX = fromSpec.mScaledOffsetX
- + (toSpec.mScaledOffsetX - fromSpec.mScaledOffsetX)
+ result.scale = fromSpec.scale
+ + (toSpec.scale - fromSpec.scale) * fraction;
+ result.offsetX = fromSpec.offsetX + (toSpec.offsetX - fromSpec.offsetX)
* fraction;
- result.mScaledOffsetY = fromSpec.mScaledOffsetY
- + (toSpec.mScaledOffsetY - fromSpec.mScaledOffsetY)
+ result.offsetY = fromSpec.offsetY + (toSpec.offsetY - fromSpec.offsetY)
* fraction;
return result;
}
@@ -1281,61 +1007,48 @@ public final class ScreenMagnifier implements EventStreamTransformation {
mTransformationAnimator = ObjectAnimator.ofObject(this, property,
evaluator, mSentMagnificationSpec, mCurrentMagnificationSpec);
mTransformationAnimator.setDuration((long) (animationDuration));
- mTransformationAnimator.setInterpolator(mInterpolator);
+ mTransformationAnimator.setInterpolator(new DecelerateInterpolator(2.5f));
}
public boolean isMagnifying() {
- return mCurrentMagnificationSpec.mScale > 1.0f;
+ return mCurrentMagnificationSpec.scale > 1.0f;
}
public void reset(boolean animate) {
if (mTransformationAnimator.isRunning()) {
mTransformationAnimator.cancel();
}
- mCurrentMagnificationSpec.reset();
+ mCurrentMagnificationSpec.clear();
if (animate) {
- animateAccessibilityTranformation(mSentMagnificationSpec,
+ animateMangificationSpec(mSentMagnificationSpec,
mCurrentMagnificationSpec);
} else {
- setAccessibilityTransformation(mCurrentMagnificationSpec);
+ setMagnificationSpec(mCurrentMagnificationSpec);
}
- }
-
- public Rect getMagnifiedRegionBounds() {
- mTempRect.set(mViewport.getBounds());
- mTempRect.offset((int) -mCurrentMagnificationSpec.mScaledOffsetX,
- (int) -mCurrentMagnificationSpec.mScaledOffsetY);
- mTempRect.scale(1.0f / mCurrentMagnificationSpec.mScale);
- return mTempRect;
+ Rect bounds = mTempRect;
+ bounds.setEmpty();
+ mAms.onMagnificationStateChanged();
}
public float getScale() {
- return mCurrentMagnificationSpec.mScale;
- }
-
- public float getMagnifiedRegionCenterX() {
- return mCurrentMagnificationSpec.mMagnifiedRegionCenterX;
- }
-
- public float getMagnifiedRegionCenterY() {
- return mCurrentMagnificationSpec.mMagnifiedRegionCenterY;
+ return mCurrentMagnificationSpec.scale;
}
- public float getScaledOffsetX() {
- return mCurrentMagnificationSpec.mScaledOffsetX;
+ public float getOffsetX() {
+ return mCurrentMagnificationSpec.offsetX;
}
- public float getScaledOffsetY() {
- return mCurrentMagnificationSpec.mScaledOffsetY;
+ public float getOffsetY() {
+ return mCurrentMagnificationSpec.offsetY;
}
public void setScale(float scale, float pivotX, float pivotY, boolean animate) {
MagnificationSpec spec = mCurrentMagnificationSpec;
- final float oldScale = spec.mScale;
- final float oldCenterX = spec.mMagnifiedRegionCenterX;
- final float oldCenterY = spec.mMagnifiedRegionCenterY;
- final float normPivotX = (-spec.mScaledOffsetX + pivotX) / oldScale;
- final float normPivotY = (-spec.mScaledOffsetY + pivotY) / oldScale;
+ final float oldScale = spec.scale;
+ final float oldCenterX = (-spec.offsetX + mMagnifiedFrame.width() / 2) / oldScale;
+ final float oldCenterY = (-spec.offsetY + mMagnifiedFrame.height() / 2) / oldScale;
+ final float normPivotX = (-spec.offsetX + pivotX) / oldScale;
+ final float normPivotY = (-spec.offsetY + pivotY) / oldScale;
final float offsetX = (oldCenterX - normPivotX) * (oldScale / scale);
final float offsetY = (oldCenterY - normPivotY) * (oldScale / scale);
final float centerX = normPivotX + offsetX;
@@ -1344,16 +1057,26 @@ public final class ScreenMagnifier implements EventStreamTransformation {
}
public void setMagnifiedRegionCenter(float centerX, float centerY, boolean animate) {
- setScaleAndMagnifiedRegionCenter(mCurrentMagnificationSpec.mScale, centerX, centerY,
+ setScaleAndMagnifiedRegionCenter(mCurrentMagnificationSpec.scale, centerX, centerY,
animate);
}
+ public void offsetMagnifiedRegionCenter(float offsetX, float offsetY) {
+ final float nonNormOffsetX = mCurrentMagnificationSpec.offsetX - offsetX;
+ mCurrentMagnificationSpec.offsetX = Math.min(Math.max(nonNormOffsetX,
+ getMinOffsetX()), 0);
+ final float nonNormOffsetY = mCurrentMagnificationSpec.offsetY - offsetY;
+ mCurrentMagnificationSpec.offsetY = Math.min(Math.max(nonNormOffsetY,
+ getMinOffsetY()), 0);
+ setMagnificationSpec(mCurrentMagnificationSpec);
+ }
+
public void setScaleAndMagnifiedRegionCenter(float scale, float centerX, float centerY,
boolean animate) {
- if (Float.compare(mCurrentMagnificationSpec.mScale, scale) == 0
- && Float.compare(mCurrentMagnificationSpec.mMagnifiedRegionCenterX,
+ if (Float.compare(mCurrentMagnificationSpec.scale, scale) == 0
+ && Float.compare(mCurrentMagnificationSpec.offsetX,
centerX) == 0
- && Float.compare(mCurrentMagnificationSpec.mMagnifiedRegionCenterY,
+ && Float.compare(mCurrentMagnificationSpec.offsetY,
centerY) == 0) {
return;
}
@@ -1361,149 +1084,192 @@ public final class ScreenMagnifier implements EventStreamTransformation {
mTransformationAnimator.cancel();
}
if (DEBUG_MAGNIFICATION_CONTROLLER) {
- Slog.i(LOG_TAG, "scale: " + scale + " centerX: " + centerX
- + " centerY: " + centerY);
+ Slog.i(LOG_TAG, "scale: " + scale + " offsetX: " + centerX
+ + " offsetY: " + centerY);
}
- mCurrentMagnificationSpec.initialize(scale, centerX, centerY);
+ updateMagnificationSpec(scale, centerX, centerY);
if (animate) {
- animateAccessibilityTranformation(mSentMagnificationSpec,
+ animateMangificationSpec(mSentMagnificationSpec,
mCurrentMagnificationSpec);
} else {
- setAccessibilityTransformation(mCurrentMagnificationSpec);
+ setMagnificationSpec(mCurrentMagnificationSpec);
}
+ mAms.onMagnificationStateChanged();
+ }
+
+ public void updateMagnificationSpec(float scale, float magnifiedCenterX,
+ float magnifiedCenterY) {
+ mCurrentMagnificationSpec.scale = scale;
+ final int viewportWidth = mMagnifiedFrame.width();
+ final float nonNormOffsetX = viewportWidth / 2 - magnifiedCenterX * scale;
+ mCurrentMagnificationSpec.offsetX = Math.min(Math.max(nonNormOffsetX,
+ getMinOffsetX()), 0);
+ final int viewportHeight = mMagnifiedFrame.height();
+ final float nonNormOffsetY = viewportHeight / 2 - magnifiedCenterY * scale;
+ mCurrentMagnificationSpec.offsetY = Math.min(Math.max(nonNormOffsetY,
+ getMinOffsetY()), 0);
+ }
+
+ private float getMinOffsetX() {
+ final float viewportWidth = mMagnifiedFrame.width();
+ return viewportWidth - viewportWidth * mCurrentMagnificationSpec.scale;
}
- private void animateAccessibilityTranformation(MagnificationSpec fromSpec,
+ private float getMinOffsetY() {
+ final float viewportHeight = mMagnifiedFrame.height();
+ return viewportHeight - viewportHeight * mCurrentMagnificationSpec.scale;
+ }
+
+ private void animateMangificationSpec(MagnificationSpec fromSpec,
MagnificationSpec toSpec) {
mTransformationAnimator.setObjectValues(fromSpec, toSpec);
mTransformationAnimator.start();
}
- @SuppressWarnings("unused")
- // Called from an animator.
- public MagnificationSpec getAccessibilityTransformation() {
+ public MagnificationSpec getMagnificationSpec() {
return mSentMagnificationSpec;
}
- public void setAccessibilityTransformation(MagnificationSpec transformation) {
- if (DEBUG_TRANSFORMATION) {
- Slog.i(LOG_TAG, "Transformation scale: " + transformation.mScale
- + " offsetX: " + transformation.mScaledOffsetX
- + " offsetY: " + transformation.mScaledOffsetY);
+ public void setMagnificationSpec(MagnificationSpec spec) {
+ if (DEBUG_SET_MAGNIFICATION_SPEC) {
+ Slog.i(LOG_TAG, "Sending: " + spec);
}
try {
- mSentMagnificationSpec.updateFrom(transformation);
- mWindowManagerService.magnifyDisplay(mDisplayProvider.getDisplay().getDisplayId(),
- transformation.mScale, transformation.mScaledOffsetX,
- transformation.mScaledOffsetY);
+ mSentMagnificationSpec.scale = spec.scale;
+ mSentMagnificationSpec.offsetX = spec.offsetX;
+ mSentMagnificationSpec.offsetY = spec.offsetY;
+ mDisplayMagnifier.setMagnificationSpec(ScreenMagnifier.this,
+ MagnificationSpec.obtain(spec));
} catch (RemoteException re) {
/* ignore */
}
}
+ }
- private class MagnificationSpec {
-
- private static final float DEFAULT_SCALE = 1.0f;
-
- public float mScale = DEFAULT_SCALE;
-
- public float mMagnifiedRegionCenterX;
-
- public float mMagnifiedRegionCenterY;
-
- public float mScaledOffsetX;
-
- public float mScaledOffsetY;
+ private static final class ScreenStateObserver extends BroadcastReceiver {
+ private static final int MESSAGE_ON_SCREEN_STATE_CHANGE = 1;
- public void initialize(float scale, float magnifiedRegionCenterX,
- float magnifiedRegionCenterY) {
- mScale = scale;
+ private final Context mContext;
+ private final MagnificationController mMagnificationController;
+ private final ViewportWindow mViewportWindow;
- final int viewportWidth = mViewport.getBounds().width();
- final int viewportHeight = mViewport.getBounds().height();
- final float minMagnifiedRegionCenterX = (viewportWidth / 2) / scale;
- final float minMagnifiedRegionCenterY = (viewportHeight / 2) / scale;
- final float maxMagnifiedRegionCenterX = viewportWidth - minMagnifiedRegionCenterX;
- final float maxMagnifiedRegionCenterY = viewportHeight - minMagnifiedRegionCenterY;
+ private final Handler mHandler = new Handler() {
+ @Override
+ public void handleMessage(Message message) {
+ switch (message.what) {
+ case MESSAGE_ON_SCREEN_STATE_CHANGE: {
+ String action = (String) message.obj;
+ handleOnScreenStateChange(action);
+ } break;
+ }
+ }
+ };
- mMagnifiedRegionCenterX = Math.min(Math.max(magnifiedRegionCenterX,
- minMagnifiedRegionCenterX), maxMagnifiedRegionCenterX);
- mMagnifiedRegionCenterY = Math.min(Math.max(magnifiedRegionCenterY,
- minMagnifiedRegionCenterY), maxMagnifiedRegionCenterY);
+ public ScreenStateObserver(Context context,
+ MagnificationController magnificationController, ViewportWindow viewportWindow) {
+ mContext = context;
+ mMagnificationController = magnificationController;
+ mViewportWindow = viewportWindow;
+ mContext.registerReceiver(this, new IntentFilter(Intent.ACTION_SCREEN_OFF));
+ }
- mScaledOffsetX = -(mMagnifiedRegionCenterX * scale - viewportWidth / 2);
- mScaledOffsetY = -(mMagnifiedRegionCenterY * scale - viewportHeight / 2);
- }
+ public void destroy() {
+ mContext.unregisterReceiver(this);
+ }
- public void updateFrom(MagnificationSpec other) {
- mScale = other.mScale;
- mMagnifiedRegionCenterX = other.mMagnifiedRegionCenterX;
- mMagnifiedRegionCenterY = other.mMagnifiedRegionCenterY;
- mScaledOffsetX = other.mScaledOffsetX;
- mScaledOffsetY = other.mScaledOffsetY;
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ mHandler.obtainMessage(MESSAGE_ON_SCREEN_STATE_CHANGE,
+ intent.getAction()).sendToTarget();
}
- public void reset() {
- mScale = DEFAULT_SCALE;
- mMagnifiedRegionCenterX = 0;
- mMagnifiedRegionCenterY = 0;
- mScaledOffsetX = 0;
- mScaledOffsetY = 0;
+ private void handleOnScreenStateChange(String action) {
+ if (mMagnificationController.isMagnifying()
+ && isScreenMagnificationAutoUpdateEnabled(mContext)) {
+ mMagnificationController.reset(false);
+ mViewportWindow.setShown(false, false);
}
}
}
- private static final class Viewport {
+ private static final class ViewportWindow implements DisplayListener {
+ private static final String WINDOW_TITLE = "Magnification Overlay";
private static final String PROPERTY_NAME_ALPHA = "alpha";
-
private static final String PROPERTY_NAME_BOUNDS = "bounds";
private static final int MIN_ALPHA = 0;
-
private static final int MAX_ALPHA = 255;
- private final ArrayList<WindowInfo> mTempWindowInfoList = new ArrayList<WindowInfo>();
+ private final Rect mBounds = new Rect();
+
+ private final ValueAnimator mResizeFrameAnimator;
+ private final ValueAnimator mShowHideFrameAnimator;
- private final Rect mTempRect1 = new Rect();
- private final Rect mTempRect2 = new Rect();
- private final Rect mTempRect3 = new Rect();
+ private final WindowManager mWindowManager;
+ private final DisplayManager mDisplayManager;
+ private final Display mDisplay;
+ private final DisplayInfo mDisplayInfo = new DisplayInfo();
+ private final int mDisplayId;
- private final IWindowManager mWindowManagerService;
- private final DisplayProvider mDisplayProvider;
+ private final ContentView mWindowContent;
+ private final WindowManager.LayoutParams mWindowParams;
- private final ViewportWindow mViewportFrame;
+ private boolean mShown;
+ private int mAlpha;
- private final ValueAnimator mResizeFrameAnimator;
+ public ViewportWindow(Context context, int displayId) {
+ mWindowManager = (WindowManager) context.getSystemService(Service.WINDOW_SERVICE);
- private final ValueAnimator mShowHideFrameAnimator;
+ mDisplayId = displayId;
+ mDisplayManager = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
+ mDisplay = mDisplayManager.getDisplay(displayId);
+ mDisplayManager.registerDisplayListener(this, null);
+ updateDisplayInfo();
- public Viewport(Context context, WindowManager windowManager,
- IWindowManager windowManagerService, DisplayProvider displayInfoProvider,
- Interpolator animationInterpolator, long animationDuration) {
- mWindowManagerService = windowManagerService;
- mDisplayProvider = displayInfoProvider;
- mViewportFrame = new ViewportWindow(context, windowManager, displayInfoProvider);
-
- mShowHideFrameAnimator = ObjectAnimator.ofInt(mViewportFrame, PROPERTY_NAME_ALPHA,
- MIN_ALPHA, MAX_ALPHA);
- mShowHideFrameAnimator.setInterpolator(animationInterpolator);
- mShowHideFrameAnimator.setDuration(animationDuration);
+ ViewGroup.LayoutParams contentParams = new ViewGroup.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
+ mWindowContent = new ContentView(context);
+ mWindowContent.setLayoutParams(contentParams);
+ mWindowContent.setBackgroundColor(R.color.transparent);
+
+ mWindowParams = new WindowManager.LayoutParams(
+ WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY);
+ mWindowParams.flags |= WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
+ | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+ | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
+ mWindowParams.setTitle(WINDOW_TITLE);
+ mWindowParams.gravity = Gravity.CENTER;
+ mWindowParams.width = mDisplayInfo.logicalWidth;
+ mWindowParams.height = mDisplayInfo.logicalHeight;
+ mWindowParams.format = PixelFormat.TRANSLUCENT;
+
+ Interpolator interpolator = new DecelerateInterpolator(2.5f);
+ final long longAnimationDuration = context.getResources().getInteger(
+ com.android.internal.R.integer.config_longAnimTime);
+
+ mShowHideFrameAnimator = ObjectAnimator.ofInt(this, PROPERTY_NAME_ALPHA,
+ MIN_ALPHA, MAX_ALPHA);
+ mShowHideFrameAnimator.setInterpolator(interpolator);
+ mShowHideFrameAnimator.setDuration(longAnimationDuration);
mShowHideFrameAnimator.addListener(new AnimatorListener() {
@Override
public void onAnimationEnd(Animator animation) {
if (mShowHideFrameAnimator.getAnimatedValue().equals(MIN_ALPHA)) {
- mViewportFrame.hide();
+ hide();
}
}
+
@Override
public void onAnimationStart(Animator animation) {
/* do nothing - stub */
}
+
@Override
public void onAnimationCancel(Animator animation) {
/* do nothing - stub */
}
+
@Override
public void onAnimationRepeat(Animator animation) {
/* do nothing - stub */
@@ -1514,6 +1280,7 @@ public final class ScreenMagnifier implements EventStreamTransformation {
Rect.class, PROPERTY_NAME_BOUNDS);
TypeEvaluator<Rect> evaluator = new TypeEvaluator<Rect>() {
private final Rect mReusableResultRect = new Rect();
+
@Override
public Rect evaluate(float fraction, Rect fromFrame, Rect toFrame) {
Rect result = mReusableResultRect;
@@ -1528,103 +1295,18 @@ public final class ScreenMagnifier implements EventStreamTransformation {
return result;
}
};
- mResizeFrameAnimator = ObjectAnimator.ofObject(mViewportFrame, property,
- evaluator, mViewportFrame.mBounds, mViewportFrame.mBounds);
- mResizeFrameAnimator.setDuration((long) (animationDuration));
- mResizeFrameAnimator.setInterpolator(animationInterpolator);
-
- recomputeBounds(false);
+ mResizeFrameAnimator = ObjectAnimator.ofObject(this, property,
+ evaluator, mBounds, mBounds);
+ mResizeFrameAnimator.setDuration(longAnimationDuration);
+ mResizeFrameAnimator.setInterpolator(interpolator);
}
- private final Comparator<WindowInfo> mWindowInfoInverseComparator =
- new Comparator<WindowInfo>() {
- @Override
- public int compare(WindowInfo lhs, WindowInfo rhs) {
- if (lhs.layer != rhs.layer) {
- return rhs.layer - lhs.layer;
- }
- if (lhs.touchableRegion.top != rhs.touchableRegion.top) {
- return rhs.touchableRegion.top - lhs.touchableRegion.top;
- }
- if (lhs.touchableRegion.left != rhs.touchableRegion.left) {
- return rhs.touchableRegion.left - lhs.touchableRegion.left;
- }
- if (lhs.touchableRegion.right != rhs.touchableRegion.right) {
- return rhs.touchableRegion.right - lhs.touchableRegion.right;
- }
- if (lhs.touchableRegion.bottom != rhs.touchableRegion.bottom) {
- return rhs.touchableRegion.bottom - lhs.touchableRegion.bottom;
- }
- return 0;
- }
- };
-
- public void recomputeBounds(boolean animate) {
- Rect magnifiedFrame = mTempRect1;
- magnifiedFrame.set(0, 0, 0, 0);
-
- DisplayInfo displayInfo = mDisplayProvider.getDisplayInfo();
-
- Rect availableFrame = mTempRect2;
- availableFrame.set(0, 0, displayInfo.logicalWidth, displayInfo.logicalHeight);
-
- ArrayList<WindowInfo> infos = mTempWindowInfoList;
- infos.clear();
- int windowCount = 0;
- try {
- mWindowManagerService.getVisibleWindowsForDisplay(
- mDisplayProvider.getDisplay().getDisplayId(), infos);
- Collections.sort(infos, mWindowInfoInverseComparator);
- windowCount = infos.size();
- for (int i = 0; i < windowCount; i++) {
- WindowInfo info = infos.get(i);
- if (info.type == WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY) {
- continue;
- }
- Rect windowFrame = mTempRect3;
- windowFrame.set(info.touchableRegion);
- if (isWindowMagnified(info.type)) {
- magnifiedFrame.union(windowFrame);
- magnifiedFrame.intersect(availableFrame);
- } else {
- subtract(windowFrame, magnifiedFrame);
- subtract(availableFrame, windowFrame);
- }
- if (availableFrame.equals(magnifiedFrame)) {
- break;
- }
- }
- } catch (RemoteException re) {
- /* ignore */
- } finally {
- for (int i = windowCount - 1; i >= 0; i--) {
- infos.remove(i).recycle();
- }
- }
-
- final int displayWidth = mDisplayProvider.getDisplayInfo().logicalWidth;
- final int displayHeight = mDisplayProvider.getDisplayInfo().logicalHeight;
- magnifiedFrame.intersect(0, 0, displayWidth, displayHeight);
-
- resize(magnifiedFrame, animate);
+ public boolean isShown() {
+ return mShown;
}
- private boolean isWindowMagnified(int type) {
- return (type != WindowManager.LayoutParams.TYPE_NAVIGATION_BAR
- && type != WindowManager.LayoutParams.TYPE_INPUT_METHOD
- && type != WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG);
- }
-
- public void rotationChanged() {
- mViewportFrame.rotationChanged();
- }
-
- public Rect getBounds() {
- return mViewportFrame.getBounds();
- }
-
- public void setFrameShown(boolean shown, boolean animate) {
- if (mViewportFrame.isShown() == shown) {
+ public void setShown(boolean shown, boolean animate) {
+ if (isShown() == shown) {
return;
}
if (animate) {
@@ -1632,7 +1314,7 @@ public final class ScreenMagnifier implements EventStreamTransformation {
mShowHideFrameAnimator.reverse();
} else {
if (shown) {
- mViewportFrame.show();
+ show();
mShowHideFrameAnimator.start();
} else {
mShowHideFrameAnimator.reverse();
@@ -1641,221 +1323,140 @@ public final class ScreenMagnifier implements EventStreamTransformation {
} else {
mShowHideFrameAnimator.cancel();
if (shown) {
- mViewportFrame.show();
+ show();
} else {
- mViewportFrame.hide();
+ hide();
}
}
}
- private void resize(Rect bounds, boolean animate) {
- if (mViewportFrame.getBounds().equals(bounds)) {
+ private void show() {
+ if (mShown) {
+ return;
+ }
+ mShown = true;
+ mWindowManager.addView(mWindowContent, mWindowParams);
+ if (DEBUG_VIEWPORT_WINDOW) {
+ Slog.i(LOG_TAG, "ViewportWindow shown.");
+ }
+ }
+
+ public void setBounds(Rect bounds, boolean animate) {
+ if (getBounds().equals(bounds)) {
return;
}
if (animate) {
if (mResizeFrameAnimator.isRunning()) {
mResizeFrameAnimator.cancel();
}
- mResizeFrameAnimator.setObjectValues(mViewportFrame.mBounds, bounds);
+ mResizeFrameAnimator.setObjectValues(getBounds(), bounds);
mResizeFrameAnimator.start();
} else {
- mViewportFrame.setBounds(bounds);
+ setBounds(bounds);
}
}
- private boolean subtract(Rect lhs, Rect rhs) {
- if (lhs.right < rhs.left || lhs.left > rhs.right
- || lhs.bottom < rhs.top || lhs.top > rhs.bottom) {
- return false;
- }
- if (lhs.left < rhs.left) {
- lhs.right = rhs.left;
- }
- if (lhs.top < rhs.top) {
- lhs.bottom = rhs.top;
- }
- if (lhs.right > rhs.right) {
- lhs.left = rhs.right;
+ private void hide() {
+ if (!mShown) {
+ return;
}
- if (lhs.bottom > rhs.bottom) {
- lhs.top = rhs.bottom;
+ mShown = false;
+ mWindowManager.removeView(mWindowContent);
+ if (DEBUG_VIEWPORT_WINDOW) {
+ Slog.i(LOG_TAG, "ViewportWindow hidden.");
}
- return true;
}
- private static final class ViewportWindow {
- private static final String WINDOW_TITLE = "Magnification Overlay";
-
- private final WindowManager mWindowManager;
- private final DisplayProvider mDisplayProvider;
-
- private final ContentView mWindowContent;
- private final WindowManager.LayoutParams mWindowParams;
-
- private final Rect mBounds = new Rect();
- private boolean mShown;
- private int mAlpha;
-
- public ViewportWindow(Context context, WindowManager windowManager,
- DisplayProvider displayProvider) {
- mWindowManager = windowManager;
- mDisplayProvider = displayProvider;
-
- ViewGroup.LayoutParams contentParams = new ViewGroup.LayoutParams(
- ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
- mWindowContent = new ContentView(context);
- mWindowContent.setLayoutParams(contentParams);
- mWindowContent.setBackgroundColor(R.color.transparent);
-
- mWindowParams = new WindowManager.LayoutParams(
- WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY);
- mWindowParams.flags |= WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
- | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
- | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
- mWindowParams.setTitle(WINDOW_TITLE);
- mWindowParams.gravity = Gravity.CENTER;
- mWindowParams.width = displayProvider.getDisplayInfo().logicalWidth;
- mWindowParams.height = displayProvider.getDisplayInfo().logicalHeight;
- mWindowParams.format = PixelFormat.TRANSLUCENT;
- }
-
- public boolean isShown() {
- return mShown;
- }
+ @SuppressWarnings("unused")
+ // Called reflectively from an animator.
+ public int getAlpha() {
+ return mAlpha;
+ }
- public void show() {
- if (mShown) {
- return;
- }
- mShown = true;
- mWindowManager.addView(mWindowContent, mWindowParams);
- if (DEBUG_VIEWPORT_WINDOW) {
- Slog.i(LOG_TAG, "ViewportWindow shown.");
- }
+ @SuppressWarnings("unused")
+ // Called reflectively from an animator.
+ public void setAlpha(int alpha) {
+ if (mAlpha == alpha) {
+ return;
}
-
- public void hide() {
- if (!mShown) {
- return;
- }
- mShown = false;
- mWindowManager.removeView(mWindowContent);
- if (DEBUG_VIEWPORT_WINDOW) {
- Slog.i(LOG_TAG, "ViewportWindow hidden.");
- }
+ mAlpha = alpha;
+ if (mShown) {
+ mWindowContent.invalidate();
}
-
- @SuppressWarnings("unused")
- // Called reflectively from an animator.
- public int getAlpha() {
- return mAlpha;
+ if (DEBUG_VIEWPORT_WINDOW) {
+ Slog.i(LOG_TAG, "ViewportFrame set alpha: " + alpha);
}
+ }
- @SuppressWarnings("unused")
- // Called reflectively from an animator.
- public void setAlpha(int alpha) {
- if (mAlpha == alpha) {
- return;
- }
- mAlpha = alpha;
- if (mShown) {
- mWindowContent.invalidate();
- }
- if (DEBUG_VIEWPORT_WINDOW) {
- Slog.i(LOG_TAG, "ViewportFrame set alpha: " + alpha);
- }
- }
+ public Rect getBounds() {
+ return mBounds;
+ }
- public Rect getBounds() {
- return mBounds;
+ public void setBounds(Rect bounds) {
+ if (mBounds.equals(bounds)) {
+ return;
}
-
- public void rotationChanged() {
- mWindowParams.width = mDisplayProvider.getDisplayInfo().logicalWidth;
- mWindowParams.height = mDisplayProvider.getDisplayInfo().logicalHeight;
- if (mShown) {
- mWindowManager.updateViewLayout(mWindowContent, mWindowParams);
- }
+ mBounds.set(bounds);
+ if (mShown) {
+ mWindowContent.invalidate();
}
-
- public void setBounds(Rect bounds) {
- if (mBounds.equals(bounds)) {
- return;
- }
- mBounds.set(bounds);
- if (mShown) {
- mWindowContent.invalidate();
- }
- if (DEBUG_VIEWPORT_WINDOW) {
- Slog.i(LOG_TAG, "ViewportFrame set bounds: " + bounds);
- }
+ if (DEBUG_VIEWPORT_WINDOW) {
+ Slog.i(LOG_TAG, "ViewportFrame set bounds: " + bounds);
}
+ }
- private final class ContentView extends View {
- private final Drawable mHighlightFrame;
-
- public ContentView(Context context) {
- super(context);
- mHighlightFrame = context.getResources().getDrawable(
- R.drawable.magnified_region_frame);
- }
-
- @Override
- public void onDraw(Canvas canvas) {
- canvas.drawColor(Color.TRANSPARENT, Mode.CLEAR);
- mHighlightFrame.setBounds(mBounds);
- mHighlightFrame.setAlpha(mAlpha);
- mHighlightFrame.draw(canvas);
- }
+ public void rotationChanged() {
+ mWindowParams.width = mDisplayInfo.logicalWidth;
+ mWindowParams.height = mDisplayInfo.logicalHeight;
+ if (mShown) {
+ mWindowManager.updateViewLayout(mWindowContent, mWindowParams);
}
}
- }
-
- private static class DisplayProvider implements DisplayListener {
- private final WindowManager mWindowManager;
- private final DisplayManager mDisplayManager;
- private final Display mDefaultDisplay;
- private final DisplayInfo mDefaultDisplayInfo = new DisplayInfo();
- public DisplayProvider(Context context, WindowManager windowManager) {
- mWindowManager = windowManager;
- mDisplayManager = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
- mDefaultDisplay = mWindowManager.getDefaultDisplay();
- mDisplayManager.registerDisplayListener(this, null);
- updateDisplayInfo();
- }
+ private final class ContentView extends View {
+ private final Drawable mHighlightFrame;
- public DisplayInfo getDisplayInfo() {
- return mDefaultDisplayInfo;
- }
+ public ContentView(Context context) {
+ super(context);
+ mHighlightFrame = context.getResources().getDrawable(
+ R.drawable.magnified_region_frame);
+ }
- public Display getDisplay() {
- return mDefaultDisplay;
+ @Override
+ public void onDraw(Canvas canvas) {
+ canvas.drawColor(Color.TRANSPARENT, Mode.CLEAR);
+ mHighlightFrame.setBounds(mBounds);
+ mHighlightFrame.setAlpha(mAlpha);
+ mHighlightFrame.draw(canvas);
+ }
}
private void updateDisplayInfo() {
- if (!mDefaultDisplay.getDisplayInfo(mDefaultDisplayInfo)) {
- Slog.e(LOG_TAG, "Default display is not valid.");
+ if (!mDisplay.getDisplayInfo(mDisplayInfo)) {
+ Slog.e(LOG_TAG, "Display is not valid.");
}
}
public void destroy() {
+ setShown(false, true);
mDisplayManager.unregisterDisplayListener(this);
}
@Override
- public void onDisplayAdded(int displayId) {
- /* do noting */
+ public void onDisplayChanged(int displayId) {
+ if (mDisplayId == displayId) {
+ updateDisplayInfo();
+ }
}
@Override
- public void onDisplayRemoved(int displayId) {
- // Having no default display
+ public void onDisplayAdded(int displayId) {
+ /* do nothing */
}
@Override
- public void onDisplayChanged(int displayId) {
- updateDisplayInfo();
+ public void onDisplayRemoved(int displayId) {
+ /* do nothing */
}
}
}
diff --git a/services/java/com/android/server/wm/DisplayContent.java b/services/java/com/android/server/wm/DisplayContent.java
index 68cdbfc..59e4b0e 100644
--- a/services/java/com/android/server/wm/DisplayContent.java
+++ b/services/java/com/android/server/wm/DisplayContent.java
@@ -16,10 +16,8 @@
package com.android.server.wm;
-import android.os.RemoteCallbackList;
import android.view.Display;
import android.view.DisplayInfo;
-import android.view.IDisplayContentChangeListener;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -43,12 +41,6 @@ class DisplayContent {
* from mDisplayWindows; */
private WindowList mWindows = new WindowList();
- // Specification for magnifying the display content.
- MagnificationSpec mMagnificationSpec;
-
- // Callback for observing content changes on a display.
- RemoteCallbackList<IDisplayContentChangeListener> mDisplayContentChangeListeners;
-
// This protects the following display size properties, so that
// getDisplaySize() doesn't need to acquire the global lock. This is
// needed because the window manager sometimes needs to use ActivityThread
@@ -128,9 +120,6 @@ class DisplayContent {
pw.print("-"); pw.print(mDisplayInfo.largestNominalAppWidth);
pw.print("x"); pw.println(mDisplayInfo.largestNominalAppHeight);
pw.print(subPrefix); pw.print("layoutNeeded="); pw.print(layoutNeeded);
- if (mMagnificationSpec != null) {
- pw.print(" mMagnificationSpec="); pw.print(mMagnificationSpec);
- }
pw.println();
}
}
diff --git a/services/java/com/android/server/wm/DisplayMagnificationMediator.java b/services/java/com/android/server/wm/DisplayMagnificationMediator.java
new file mode 100644
index 0000000..8621c5c
--- /dev/null
+++ b/services/java/com/android/server/wm/DisplayMagnificationMediator.java
@@ -0,0 +1,616 @@
+package com.android.server.wm;
+
+import android.Manifest;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.graphics.Rect;
+import android.graphics.Region;
+import android.hardware.display.DisplayManager;
+import android.hardware.display.DisplayManager.DisplayListener;
+import android.os.Binder;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.Process;
+import android.os.RemoteException;
+import android.util.Slog;
+import android.util.SparseArray;
+import android.util.Pools.SynchronizedPool;
+import android.view.DisplayInfo;
+import android.view.IDisplayMagnificationController;
+import android.view.IDisplayMagnificationMediator;
+import android.view.MagnificationSpec;
+import android.view.Surface;
+import android.view.WindowManager;
+import android.view.WindowManagerPolicy;
+
+import com.android.internal.os.SomeArgs;
+import com.android.internal.policy.impl.PhoneWindowManager;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+
+final class DisplayMagnificationMediator extends IDisplayMagnificationMediator.Stub
+ implements DisplayListener {
+ private static final String LOG_TAG = DisplayMagnificationMediator.class.getSimpleName();
+
+ private static final boolean DEBUG_WINDOW_TRANSITIONS = false;
+ private static final boolean DEBUG_ROTATION = false;
+ private static final boolean DEBUG_LAYERS = false;
+ private static final boolean DEBUG_RECTANGLE_REQUESTED = false;
+
+ private static final int MESSAGE_NOTIFY_MAGNIFIED_FRAME_CHANGED = 1;
+ private static final int MESSAGE_NOTIFY_RECTANGLE_ON_SCREEN_REQUESTED = 2;
+ private static final int MESSAGE_NOTIFY_USER_CONTEXT_CHANGED = 3;
+ private static final int MESSAGE_NOTIFY_ROTATION_CHANGED = 4;
+
+ private static final String METHOD_SIGNATURE_ADD_CONTROLLER =
+ "addController(int, IDisplayMagnificationController)";
+ private static final String METHOD_SIGNATURE_REMOVE_CONTROLLER =
+ "removeController(IDisplayMagnificationController, int)";
+ private static final String METHOD_SIGNATURE_SET_MAGNIFICATION_SPEC =
+ "setMagnificationSpec(IDisplayMagnificationController, MagnificationSpec)";
+
+ private final Rect mTempRect = new Rect();
+ private final Rect mTempRect1 = new Rect();
+ private final Region mTempRegion = new Region();
+
+ private final SparseArray<DisplayState> mDisplayStates =
+ new SparseArray<DisplayMagnificationMediator.DisplayState>();
+
+ private final Context mContext;
+ private final WindowManagerService mWindowManagerService;
+
+ private final Handler mHandler = new Handler() {
+ @Override
+ public void handleMessage(Message message) {
+ switch (message.what) {
+ case MESSAGE_NOTIFY_MAGNIFIED_FRAME_CHANGED: {
+ SomeArgs args = (SomeArgs) message.obj;
+ IDisplayMagnificationController client =
+ (IDisplayMagnificationController) args.arg1;
+ final int left = args.argi1;
+ final int top = args.argi2;
+ final int right = args.argi3;
+ final int bottom = args.argi4;
+ try {
+ client.onMagnifedFrameChanged(left, top, right, bottom);
+ } catch (RemoteException re) {
+ /* ignore */
+ } finally {
+ args.recycle();
+ }
+ } break;
+ case MESSAGE_NOTIFY_RECTANGLE_ON_SCREEN_REQUESTED: {
+ SomeArgs args = (SomeArgs) message.obj;
+ IDisplayMagnificationController client =
+ (IDisplayMagnificationController) args.arg1;
+ final int left = args.argi1;
+ final int top = args.argi2;
+ final int right = args.argi3;
+ final int bottom = args.argi4;
+ try {
+ client.onRectangleOnScreenRequested(left, top, right, bottom);
+ } catch (RemoteException re) {
+ /* ignore */
+ } finally {
+ args.recycle();
+ }
+ } break;
+ case MESSAGE_NOTIFY_USER_CONTEXT_CHANGED: {
+ IDisplayMagnificationController client =
+ (IDisplayMagnificationController) message.obj;
+ try {
+ client.onUserContextChanged();
+ } catch (RemoteException re) {
+ /* ignore */
+ }
+ } break;
+ case MESSAGE_NOTIFY_ROTATION_CHANGED: {
+ IDisplayMagnificationController client =
+ (IDisplayMagnificationController) message.obj;
+ final int rotation = message.arg1;
+ try {
+ client.onRotationChanged(rotation);
+ } catch (RemoteException re) {
+ /* ignore */
+ }
+ } break;
+ }
+ }
+ };
+
+ public DisplayMagnificationMediator(WindowManagerService windowManagerService) {
+ mContext = windowManagerService.mContext;
+ mWindowManagerService = windowManagerService;
+ DisplayManager displayManager = (DisplayManager)
+ mContext.getSystemService(Context.DISPLAY_SERVICE);
+ displayManager.registerDisplayListener(this, mHandler);
+ }
+
+ @Override
+ public void addController(int displayId, IDisplayMagnificationController controller) {
+ enforceCallingPermission(Manifest.permission.MAGNIFY_DISPLAY,
+ METHOD_SIGNATURE_ADD_CONTROLLER);
+ synchronized (mWindowManagerService.mWindowMap) {
+ DisplayState displayState = mDisplayStates.get(displayId);
+ if (displayState != null) {
+ displayState.clearLw();
+ }
+ mDisplayStates.remove(displayId);
+ mDisplayStates.put(displayId, new DisplayState(displayId, controller));
+ }
+ }
+
+ @Override
+ public void removeController(IDisplayMagnificationController controller) {
+ enforceCallingPermission(Manifest.permission.MAGNIFY_DISPLAY,
+ METHOD_SIGNATURE_REMOVE_CONTROLLER);
+ synchronized (mWindowManagerService.mWindowMap) {
+ final int displayStateCount = mDisplayStates.size();
+ for (int i = 0; i < displayStateCount; i++) {
+ DisplayState displayState = mDisplayStates.valueAt(i);
+ if (displayState.mClient.asBinder() == controller.asBinder()) {
+ displayState.clearLw();
+ mDisplayStates.removeAt(i);
+ return;
+ }
+ }
+ }
+ }
+
+ @Override
+ public void setMagnificationSpec(IDisplayMagnificationController controller,
+ MagnificationSpec spec) {
+ enforceCallingPermission(Manifest.permission.MAGNIFY_DISPLAY,
+ METHOD_SIGNATURE_SET_MAGNIFICATION_SPEC);
+ synchronized (mWindowManagerService.mWindowMap) {
+ DisplayState displayState = null;
+ final int displayStateCount = mDisplayStates.size();
+ for (int i = 0; i < displayStateCount; i++) {
+ DisplayState candidate = mDisplayStates.valueAt(i);
+ if (candidate.mClient.asBinder() == controller.asBinder()) {
+ displayState = candidate;
+ break;
+ }
+ }
+ if (displayState == null) {
+ Slog.e(LOG_TAG, "Setting magnification spec for unregistered controller "
+ + controller);
+ return;
+ }
+ displayState.mMagnificationSpec.initialize(spec.scale, spec.offsetX,
+ spec.offsetY);
+ spec.recycle();
+ }
+ synchronized (mWindowManagerService.mLayoutToAnim) {
+ mWindowManagerService.scheduleAnimationLocked();
+ }
+ }
+
+ @Override
+ public MagnificationSpec getCompatibleMagnificationSpec(IBinder windowToken) {
+ synchronized (mWindowManagerService.mWindowMap) {
+ WindowState windowState = mWindowManagerService.mWindowMap.get(windowToken);
+ if (windowState == null) {
+ return null;
+ }
+ MagnificationSpec spec = getMagnificationSpecLw(windowState);
+ if ((spec == null || spec.isNop()) && windowState.mGlobalScale == 1.0f) {
+ return null;
+ }
+ if (spec == null) {
+ spec = MagnificationSpec.obtain();
+ } else {
+ spec = MagnificationSpec.obtain(spec);
+ }
+ spec.scale *= windowState.mGlobalScale;
+ return spec;
+ }
+ }
+
+ @Override
+ public void onDisplayAdded(int displayId) {
+ /* do nothing */
+ }
+
+ @Override
+ public void onDisplayRemoved(int displayId) {
+ synchronized (mWindowManagerService.mWindowMap) {
+ DisplayState displayState = mDisplayStates.get(displayId);
+ if (displayState != null) {
+ displayState.clearLw();
+ mDisplayStates.remove(displayId);
+ }
+ }
+ }
+
+ @Override
+ public void onDisplayChanged(int displayId) {
+ /* do nothing */
+ }
+
+ public void onRectangleOnScreenRequestedLw(WindowState windowState, Rect rectangle,
+ boolean immediate) {
+ DisplayState displayState = mDisplayStates.get(windowState.getDisplayId());
+ if (displayState == null) {
+ return;
+ }
+ if (DEBUG_RECTANGLE_REQUESTED) {
+ Slog.i(LOG_TAG, "Rectangle on screen requested: " + rectangle
+ + " displayId: " + windowState.getDisplayId());
+ }
+ if (!displayState.isMagnifyingLw()) {
+ return;
+ }
+ Rect magnifiedRegionBounds = mTempRect1;
+ displayState.getMagnifiedFrameInContentCoordsLw(magnifiedRegionBounds);
+ if (magnifiedRegionBounds.contains(rectangle)) {
+ return;
+ }
+ SomeArgs args = SomeArgs.obtain();
+ args.arg1 = displayState.mClient;
+ args.argi1 = rectangle.left;
+ args.argi2 = rectangle.top;
+ args.argi3 = rectangle.right;
+ args.argi4 = rectangle.bottom;
+ mHandler.obtainMessage(MESSAGE_NOTIFY_RECTANGLE_ON_SCREEN_REQUESTED,
+ args).sendToTarget();
+ }
+
+ public void onWindowLayersChangedLw(int displayId) {
+ DisplayState displayState = mDisplayStates.get(displayId);
+ if (displayState == null) {
+ return;
+ }
+ if (DEBUG_LAYERS) {
+ Slog.i(LOG_TAG, "Layers changed displayId: " + displayId);
+ }
+ displayState.mViewport.recomputeBoundsLw();
+ }
+
+ public void onRotationChangedLw(int displayId, int rotation) {
+ DisplayState displayState = mDisplayStates.get(displayId);
+ if (displayState == null) {
+ return;
+ }
+ if (DEBUG_ROTATION) {
+ Slog.i(LOG_TAG, "Rotaton: " + Surface.rotationToString(rotation)
+ + " displayId: " + displayId);
+ }
+ displayState.mViewport.recomputeBoundsLw();
+ mHandler.obtainMessage(MESSAGE_NOTIFY_ROTATION_CHANGED, rotation, 0,
+ displayState.mClient).sendToTarget();
+ }
+
+ public void onWindowTransitionLw(WindowState windowState, int transition) {
+ DisplayState displayState = mDisplayStates.get(windowState.getDisplayId());
+ if (displayState == null) {
+ return;
+ }
+ if (DEBUG_WINDOW_TRANSITIONS) {
+ Slog.i(LOG_TAG, "Window transition: "
+ + PhoneWindowManager.windowTransitionToString(transition)
+ + " displayId: " + windowState.getDisplayId());
+ }
+ final boolean magnifying = displayState.isMagnifyingLw();
+ if (magnifying) {
+ switch (transition) {
+ case WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN:
+ case WindowManagerPolicy.TRANSIT_TASK_OPEN:
+ case WindowManagerPolicy.TRANSIT_TASK_TO_FRONT:
+ case WindowManagerPolicy.TRANSIT_WALLPAPER_OPEN:
+ case WindowManagerPolicy.TRANSIT_WALLPAPER_CLOSE:
+ case WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_OPEN: {
+ mHandler.obtainMessage(MESSAGE_NOTIFY_USER_CONTEXT_CHANGED,
+ displayState.mClient).sendToTarget();
+ }
+ }
+ }
+ final int type = windowState.mAttrs.type;
+ if (type == WindowManager.LayoutParams.TYPE_NAVIGATION_BAR
+ || type == WindowManager.LayoutParams.TYPE_INPUT_METHOD
+ || type == WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG
+ || type == WindowManager.LayoutParams.TYPE_KEYGUARD
+ || type == WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG) {
+ switch (transition) {
+ case WindowManagerPolicy.TRANSIT_ENTER:
+ case WindowManagerPolicy.TRANSIT_SHOW:
+ case WindowManagerPolicy.TRANSIT_EXIT:
+ case WindowManagerPolicy.TRANSIT_HIDE: {
+ displayState.mViewport.recomputeBoundsLw();
+ } break;
+ }
+ }
+ switch (transition) {
+ case WindowManagerPolicy.TRANSIT_ENTER:
+ case WindowManagerPolicy.TRANSIT_SHOW: {
+ if (!magnifying) {
+ break;
+ }
+ switch (type) {
+ case WindowManager.LayoutParams.TYPE_APPLICATION:
+ case WindowManager.LayoutParams.TYPE_APPLICATION_PANEL:
+ case WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA:
+ case WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL:
+ case WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG:
+ case WindowManager.LayoutParams.TYPE_SEARCH_BAR:
+ case WindowManager.LayoutParams.TYPE_PHONE:
+ case WindowManager.LayoutParams.TYPE_SYSTEM_ALERT:
+ case WindowManager.LayoutParams.TYPE_TOAST:
+ case WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY:
+ case WindowManager.LayoutParams.TYPE_PRIORITY_PHONE:
+ case WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG:
+ case WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG:
+ case WindowManager.LayoutParams.TYPE_SYSTEM_ERROR:
+ case WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY:
+ case WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL:
+ case WindowManager.LayoutParams.TYPE_RECENTS_OVERLAY: {
+ Rect magnifiedRegionBounds = mTempRect1;
+ displayState.getMagnifiedFrameInContentCoordsLw(magnifiedRegionBounds);
+ Rect touchableRegionBounds = mTempRect;
+ windowState.getTouchableRegion(mTempRegion);
+ mTempRegion.getBounds(touchableRegionBounds);
+ if (!magnifiedRegionBounds.intersect(touchableRegionBounds)) {
+ SomeArgs args = SomeArgs.obtain();
+ args.arg1 = displayState.mClient;
+ args.argi1 = touchableRegionBounds.left;
+ args.argi2 = touchableRegionBounds.top;
+ args.argi3 = touchableRegionBounds.right;
+ args.argi4 = touchableRegionBounds.bottom;
+ mHandler.obtainMessage(MESSAGE_NOTIFY_RECTANGLE_ON_SCREEN_REQUESTED,
+ args).sendToTarget();
+ }
+ } break;
+ } break;
+ }
+ }
+ }
+
+ public MagnificationSpec getMagnificationSpecLw(WindowState windowState) {
+ DisplayState displayState = mDisplayStates.get(windowState.getDisplayId());
+ if (displayState == null) {
+ return null;
+ }
+ MagnificationSpec spec = displayState.mMagnificationSpec;
+ if (spec != null && !spec.isNop()) {
+ if (windowState.mAttachedWindow != null) {
+ if (!canMagnifyWindow(windowState.mAttachedWindow.mAttrs.type)) {
+ return null;
+ }
+ }
+ if (!canMagnifyWindow(windowState.mAttrs.type)) {
+ return null;
+ }
+ }
+ return spec;
+ }
+
+ private void enforceCallingPermission(String permission, String function) {
+ if (Process.myPid() == Binder.getCallingPid()) {
+ return;
+ }
+ if (mContext.checkCallingPermission(permission) != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("The caller does not have " + permission
+ + " required to call " + function);
+ }
+ }
+
+ private static boolean canMagnifyWindow(int type) {
+ switch (type) {
+ case WindowManager.LayoutParams.TYPE_INPUT_METHOD:
+ case WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG:
+ case WindowManager.LayoutParams.TYPE_NAVIGATION_BAR:
+ case WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY: {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private static final class Viewport {
+
+ private final ArrayList<WindowStateInfo> mTempWindowStateInfoList =
+ new ArrayList<WindowStateInfo>();
+
+ private final Rect mTempRect1 = new Rect();
+ private final Rect mTempRect2 = new Rect();
+ private final Rect mTempRect3 = new Rect();
+
+ private final Rect mBounds = new Rect();
+ private final Handler mHandler;
+ private final IDisplayMagnificationController mClient;
+ private final WindowManagerService mWindowManagerService;
+ private final DisplayInfo mDisplayInfo;
+
+ private final int mDisplayId;
+
+ public Viewport(Context context, int displayId, Handler handler,
+ IDisplayMagnificationController client, WindowManagerService windowManagerService) {
+ mDisplayId = displayId;
+ mHandler = handler;
+ mWindowManagerService = windowManagerService;
+ mDisplayInfo = mWindowManagerService.getDisplayContentLocked(displayId)
+ .getDisplayInfo();
+ mClient = client;
+ recomputeBoundsLw();
+ }
+
+ private final Comparator<WindowStateInfo> mWindowInfoInverseComparator =
+ new Comparator<WindowStateInfo>() {
+ @Override
+ public int compare(WindowStateInfo lhs, WindowStateInfo rhs) {
+ if (lhs.mWindowState.mLayer != rhs.mWindowState.mLayer) {
+ return rhs.mWindowState.mLayer - lhs.mWindowState.mLayer;
+ }
+ if (lhs.mTouchableRegion.top != rhs.mTouchableRegion.top) {
+ return rhs.mTouchableRegion.top - lhs.mTouchableRegion.top;
+ }
+ if (lhs.mTouchableRegion.left != rhs.mTouchableRegion.left) {
+ return rhs.mTouchableRegion.left - lhs.mTouchableRegion.left;
+ }
+ if (lhs.mTouchableRegion.right != rhs.mTouchableRegion.right) {
+ return rhs.mTouchableRegion.right - lhs.mTouchableRegion.right;
+ }
+ if (lhs.mTouchableRegion.bottom != rhs.mTouchableRegion.bottom) {
+ return rhs.mTouchableRegion.bottom - lhs.mTouchableRegion.bottom;
+ }
+ return 0;
+ }
+ };
+
+ public void recomputeBoundsLw() {
+ Rect magnifiedFrame = mBounds;
+ magnifiedFrame.set(0, 0, 0, 0);
+
+ Rect oldmagnifiedFrame = mTempRect3;
+ oldmagnifiedFrame.set(magnifiedFrame);
+
+ Rect availableFrame = mTempRect1;
+ availableFrame.set(0, 0, mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight);
+
+ ArrayList<WindowStateInfo> visibleWindows = mTempWindowStateInfoList;
+ visibleWindows.clear();
+ getVisibleWindowsLw(visibleWindows);
+
+ Collections.sort(visibleWindows, mWindowInfoInverseComparator);
+
+ final int visibleWindowCount = visibleWindows.size();
+ for (int i = 0; i < visibleWindowCount; i++) {
+ WindowStateInfo info = visibleWindows.get(i);
+ if (info.mWindowState.mAttrs.type == WindowManager
+ .LayoutParams.TYPE_MAGNIFICATION_OVERLAY) {
+ continue;
+ }
+ Rect windowFrame = mTempRect2;
+ windowFrame.set(info.mTouchableRegion);
+ if (canMagnifyWindow(info.mWindowState.mAttrs.type)) {
+ magnifiedFrame.union(windowFrame);
+ magnifiedFrame.intersect(availableFrame);
+ } else {
+ subtract(windowFrame, magnifiedFrame);
+ subtract(availableFrame, windowFrame);
+ }
+ if (availableFrame.equals(magnifiedFrame)) {
+ break;
+ }
+ }
+ for (int i = visibleWindowCount - 1; i >= 0; i--) {
+ visibleWindows.remove(i).recycle();
+ }
+
+ final int displayWidth = mDisplayInfo.logicalWidth;
+ final int displayHeight = mDisplayInfo.logicalHeight;
+ magnifiedFrame.intersect(0, 0, displayWidth, displayHeight);
+
+ if (!oldmagnifiedFrame.equals(magnifiedFrame)) {
+ SomeArgs args = SomeArgs.obtain();
+ args.arg1 = mClient;
+ args.argi1 = magnifiedFrame.left;
+ args.argi2 = magnifiedFrame.top;
+ args.argi3 = magnifiedFrame.right;
+ args.argi4 = magnifiedFrame.bottom;
+ mHandler.obtainMessage(MESSAGE_NOTIFY_MAGNIFIED_FRAME_CHANGED, args)
+ .sendToTarget();
+ }
+ }
+
+ private void getVisibleWindowsLw(ArrayList<WindowStateInfo> outWindowStates) {
+ DisplayContent displayContent = mWindowManagerService.getDisplayContentLocked(
+ mDisplayId);
+ WindowList windowList = displayContent.getWindowList();
+ final int windowCount = windowList.size();
+ for (int i = 0; i < windowCount; i++) {
+ WindowState windowState = windowList.get(i);
+ if (windowState.isVisibleLw() || windowState.mAttrs.type == WindowManager
+ .LayoutParams.TYPE_UNIVERSE_BACKGROUND) {
+ outWindowStates.add(WindowStateInfo.obtain(windowState));
+ }
+ }
+ }
+
+ public Rect getBoundsLw() {
+ return mBounds;
+ }
+
+ private static boolean subtract(Rect lhs, Rect rhs) {
+ if (lhs.right < rhs.left || lhs.left > rhs.right
+ || lhs.bottom < rhs.top || lhs.top > rhs.bottom) {
+ return false;
+ }
+ if (lhs.left < rhs.left) {
+ lhs.right = rhs.left;
+ }
+ if (lhs.top < rhs.top) {
+ lhs.bottom = rhs.top;
+ }
+ if (lhs.right > rhs.right) {
+ lhs.left = rhs.right;
+ }
+ if (lhs.bottom > rhs.bottom) {
+ lhs.top = rhs.bottom;
+ }
+ return true;
+ }
+
+ private static final class WindowStateInfo {
+ private static final int MAX_POOL_SIZE = 30;
+
+ private static final SynchronizedPool<WindowStateInfo> sPool =
+ new SynchronizedPool<WindowStateInfo>(MAX_POOL_SIZE);
+
+ private static final Region mTempRegion = new Region();
+
+ public WindowState mWindowState;
+ public final Rect mTouchableRegion = new Rect();
+
+ public static WindowStateInfo obtain(WindowState windowState) {
+ WindowStateInfo info = sPool.acquire();
+ if (info == null) {
+ info = new WindowStateInfo();
+ }
+ info.mWindowState = windowState;
+ windowState.getTouchableRegion(mTempRegion);
+ mTempRegion.getBounds(info.mTouchableRegion);
+ return info;
+ }
+
+ public void recycle() {
+ mWindowState = null;
+ mTouchableRegion.setEmpty();
+ sPool.release(this);
+ }
+ }
+ }
+
+ private final class DisplayState {
+ final int mDisplayId;
+ final MagnificationSpec mMagnificationSpec;
+ final Viewport mViewport;
+ final IDisplayMagnificationController mClient;
+
+ DisplayState(int displayId, IDisplayMagnificationController client) {
+ mDisplayId = displayId;
+ mClient = client;
+ mMagnificationSpec = MagnificationSpec.obtain();
+ mViewport = new Viewport(mContext, mDisplayId, mHandler,
+ mClient, mWindowManagerService);
+ }
+
+ public boolean isMagnifyingLw() {
+ return mMagnificationSpec.scale > 1.0f;
+ }
+
+ private void getMagnifiedFrameInContentCoordsLw(Rect rect) {
+ MagnificationSpec spec = mMagnificationSpec;
+ rect.set(mViewport.getBoundsLw());
+ rect.offset((int) -spec.offsetX, (int) -spec.offsetY);
+ rect.scale(1.0f / spec.scale);
+ }
+
+ public void clearLw() {
+ mMagnificationSpec.recycle();
+ }
+ }
+}
diff --git a/services/java/com/android/server/wm/MagnificationSpec.java b/services/java/com/android/server/wm/MagnificationSpec.java
deleted file mode 100644
index 31aae66..0000000
--- a/services/java/com/android/server/wm/MagnificationSpec.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2012 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.
- */
-
-package com.android.server.wm;
-
-public class MagnificationSpec {
- public float mScale = 1.0f;
- public float mOffsetX;
- public float mOffsetY;
-
- public void initialize(float scale, float offsetX, float offsetY) {
- mScale = scale;
- mOffsetX = offsetX;
- mOffsetY = offsetY;
- }
-
- public boolean isNop() {
- return mScale == 1.0f && mOffsetX == 0 && mOffsetY == 0;
- }
-
- @Override
- public String toString() {
- StringBuilder builder = new StringBuilder();
- builder.append("<scale:");
- builder.append(mScale);
- builder.append(",offsetX:");
- builder.append(mOffsetX);
- builder.append(",offsetY:");
- builder.append(mOffsetY);
- builder.append(">");
- return builder.toString();
- }
-}
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 69964e4..dc1121b 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -91,7 +91,6 @@ import android.os.Parcel;
import android.os.ParcelFileDescriptor;
import android.os.PowerManager;
import android.os.Process;
-import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.StrictMode;
@@ -114,7 +113,7 @@ import android.view.Display;
import android.view.DisplayInfo;
import android.view.Gravity;
import android.view.IApplicationToken;
-import android.view.IDisplayContentChangeListener;
+import android.view.IDisplayMagnificationMediator;
import android.view.IInputFilter;
import android.view.IOnKeyguardExitResult;
import android.view.IRotationWatcher;
@@ -126,12 +125,12 @@ import android.view.InputDevice;
import android.view.InputEvent;
import android.view.InputEventReceiver;
import android.view.KeyEvent;
+import android.view.MagnificationSpec;
import android.view.MotionEvent;
import android.view.Surface;
import android.view.SurfaceSession;
import android.view.View;
import android.view.ViewTreeObserver;
-import android.view.WindowInfo;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
import android.view.WindowManagerPolicy;
@@ -424,6 +423,8 @@ public class WindowManagerService extends IWindowManager.Stub
IInputMethodManager mInputMethodManager;
+ DisplayMagnificationMediator mMagnificationMediator;
+
final SurfaceSession mFxSession;
Watermark mWatermark;
StrictModeFlash mStrictModeFlash;
@@ -2374,7 +2375,9 @@ public class WindowManagerService extends IWindowManager.Stub
if (win.mWinAnimator.applyAnimationLocked(transit, false)) {
win.mExiting = true;
}
- scheduleNotifyWindowTranstionIfNeededLocked(win, transit);
+ if (mMagnificationMediator != null) {
+ mMagnificationMediator.onWindowTransitionLw(win, transit);
+ }
}
if (win.mExiting || win.mWinAnimator.isAnimating()) {
// The exit animation is running... wait for it!
@@ -2666,49 +2669,13 @@ public class WindowManagerService extends IWindowManager.Stub
public void onRectangleOnScreenRequested(IBinder token, Rect rectangle, boolean immediate) {
synchronized (mWindowMap) {
- WindowState window = mWindowMap.get(token);
- if (window != null) {
- scheduleNotifyRectangleOnScreenRequestedIfNeededLocked(window, rectangle,
- immediate);
- }
- }
- }
-
- private void scheduleNotifyRectangleOnScreenRequestedIfNeededLocked(WindowState window,
- Rect rectangle, boolean immediate) {
- DisplayContent displayContent = window.mDisplayContent;
- if (displayContent.mDisplayContentChangeListeners != null
- && displayContent.mDisplayContentChangeListeners.getRegisteredCallbackCount() > 0) {
- mH.obtainMessage(H.NOTIFY_RECTANGLE_ON_SCREEN_REQUESTED, displayContent.getDisplayId(),
- immediate? 1 : 0, new Rect(rectangle)).sendToTarget();
- }
- }
-
- private void handleNotifyRectangleOnScreenRequested(int displayId, Rect rectangle,
- boolean immediate) {
- RemoteCallbackList<IDisplayContentChangeListener> callbacks = null;
- synchronized (mWindowMap) {
- DisplayContent displayContent = getDisplayContentLocked(displayId);
- if (displayContent == null) {
- return;
- }
- callbacks = displayContent.mDisplayContentChangeListeners;
- if (callbacks == null) {
- return;
- }
- }
- final int callbackCount = callbacks.beginBroadcast();
- try {
- for (int i = 0; i < callbackCount; i++) {
- try {
- callbacks.getBroadcastItem(i).onRectangleOnScreenRequested(displayId,
- rectangle, immediate);
- } catch (RemoteException re) {
- /* ignore */
+ if (mMagnificationMediator != null) {
+ WindowState window = mWindowMap.get(token);
+ if (window != null) {
+ mMagnificationMediator.onRectangleOnScreenRequestedLw(window, rectangle,
+ immediate);
}
}
- } finally {
- callbacks.finishBroadcast();
}
}
@@ -2933,7 +2900,9 @@ public class WindowManagerService extends IWindowManager.Stub
}
winAnimator.destroySurfaceLocked(false);
}
- scheduleNotifyWindowTranstionIfNeededLocked(win, transit);
+ if (mMagnificationMediator != null) {
+ mMagnificationMediator.onWindowTransitionLw(win, transit);
+ }
}
}
@@ -3072,106 +3041,31 @@ public class WindowManagerService extends IWindowManager.Stub
}
@Override
- public float getWindowCompatibilityScale(IBinder windowToken) {
- if (!checkCallingPermission(android.Manifest.permission.RETRIEVE_WINDOW_INFO,
- "getWindowCompatibilityScale()")) {
- throw new SecurityException("Requires RETRIEVE_WINDOW_INFO permission.");
- }
- synchronized (mWindowMap) {
- WindowState windowState = mWindowMap.get(windowToken);
- return (windowState != null) ? windowState.mGlobalScale : 1.0f;
- }
- }
-
- @Override
- public WindowInfo getWindowInfo(IBinder token) {
+ public void getWindowFrame(IBinder token, Rect outBounds) {
if (!checkCallingPermission(android.Manifest.permission.RETRIEVE_WINDOW_INFO,
"getWindowInfo()")) {
throw new SecurityException("Requires RETRIEVE_WINDOW_INFO permission.");
}
synchronized (mWindowMap) {
- WindowState window = mWindowMap.get(token);
- if (window != null) {
- return getWindowInfoForWindowStateLocked(window);
+ WindowState windowState = mWindowMap.get(token);
+ if (windowState != null) {
+ outBounds.set(windowState.mFrame);
+ } else {
+ outBounds.setEmpty();
}
- return null;
}
}
@Override
- public void getVisibleWindowsForDisplay(int displayId, List<WindowInfo> outInfos) {
- if (!checkCallingPermission(android.Manifest.permission.RETRIEVE_WINDOW_INFO,
- "getWindowInfos()")) {
+ public IDisplayMagnificationMediator getDisplayMagnificationMediator() {
+ if (!checkCallingPermission(android.Manifest.permission.MAGNIFY_DISPLAY,
+ "getDisplayMagnificationMediator()")) {
throw new SecurityException("Requires RETRIEVE_WINDOW_INFO permission.");
}
- synchronized (mWindowMap) {
- DisplayContent displayContent = getDisplayContentLocked(displayId);
- if (displayContent == null) {
- return;
- }
- WindowList windows = displayContent.getWindowList();
- final int windowCount = windows.size();
- for (int i = 0; i < windowCount; i++) {
- WindowState window = windows.get(i);
- if (window.isVisibleLw() || window.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) {
- WindowInfo info = getWindowInfoForWindowStateLocked(window);
- outInfos.add(info);
- }
- }
- }
- }
-
- @Override
- public void magnifyDisplay(int displayId, float scale, float offsetX, float offsetY) {
- if (!checkCallingPermission(
- android.Manifest.permission.MAGNIFY_DISPLAY, "magnifyDisplay()")) {
- throw new SecurityException("Requires MAGNIFY_DISPLAY permission");
+ if (mMagnificationMediator == null) {
+ mMagnificationMediator = new DisplayMagnificationMediator(this);
}
- synchronized (mWindowMap) {
- MagnificationSpec spec = getDisplayMagnificationSpecLocked(displayId);
- if (spec != null) {
- final boolean scaleChanged = spec.mScale != scale;
- final boolean offsetChanged = spec.mOffsetX != offsetX || spec.mOffsetY != offsetY;
- if (!scaleChanged && !offsetChanged) {
- return;
- }
- spec.initialize(scale, offsetX, offsetY);
- // If the offset has changed we need to re-add the input windows
- // since the offsets have to be propagated to the input system.
- if (offsetChanged) {
- // TODO(multidisplay): Input only occurs on the default display.
- if (displayId == Display.DEFAULT_DISPLAY) {
- mInputMonitor.updateInputWindowsLw(true);
- }
- }
- scheduleAnimationLocked();
- }
- }
- }
-
- MagnificationSpec getDisplayMagnificationSpecLocked(int displayId) {
- DisplayContent displayContent = getDisplayContentLocked(displayId);
- if (displayContent != null) {
- if (displayContent.mMagnificationSpec == null) {
- displayContent.mMagnificationSpec = new MagnificationSpec();
- }
- return displayContent.mMagnificationSpec;
- }
- return null;
- }
-
- private WindowInfo getWindowInfoForWindowStateLocked(WindowState window) {
- WindowInfo info = WindowInfo.obtain();
- info.token = window.mToken.token;
- info.frame.set(window.mFrame);
- info.type = window.mAttrs.type;
- info.displayId = window.getDisplayId();
- info.compatibilityScale = window.mGlobalScale;
- info.visible = window.isVisibleLw() || info.type == TYPE_UNIVERSE_BACKGROUND;
- info.layer = window.mLayer;
- window.getTouchableRegion(mTempRegion);
- mTempRegion.getBounds(info.touchableRegion);
- return info;
+ return mMagnificationMediator;
}
private boolean applyAnimationLocked(AppWindowToken atoken,
@@ -3315,8 +3209,10 @@ public class WindowManagerService extends IWindowManager.Stub
if (win.isVisibleNow()) {
win.mWinAnimator.applyAnimationLocked(WindowManagerPolicy.TRANSIT_EXIT,
false);
- scheduleNotifyWindowTranstionIfNeededLocked(win,
- WindowManagerPolicy.TRANSIT_EXIT);
+ if (mMagnificationMediator != null) {
+ mMagnificationMediator.onWindowTransitionLw(win,
+ WindowManagerPolicy.TRANSIT_EXIT);
+ }
changed = true;
win.mDisplayContent.layoutNeeded = true;
}
@@ -4071,8 +3967,8 @@ public class WindowManagerService extends IWindowManager.Stub
delayed = runningAppAnimation = true;
}
WindowState window = wtoken.findMainWindow();
- if (window != null) {
- scheduleNotifyWindowTranstionIfNeededLocked(window, transit);
+ if (window != null && mMagnificationMediator != null) {
+ mMagnificationMediator.onWindowTransitionLw(window, transit);
}
changed = true;
}
@@ -4091,8 +3987,10 @@ public class WindowManagerService extends IWindowManager.Stub
if (!runningAppAnimation) {
win.mWinAnimator.applyAnimationLocked(
WindowManagerPolicy.TRANSIT_ENTER, true);
- scheduleNotifyWindowTranstionIfNeededLocked(win,
- WindowManagerPolicy.TRANSIT_ENTER);
+ if (mMagnificationMediator != null) {
+ mMagnificationMediator.onWindowTransitionLw(win,
+ WindowManagerPolicy.TRANSIT_ENTER);
+ }
}
changed = true;
win.mDisplayContent.layoutNeeded = true;
@@ -4101,8 +3999,10 @@ public class WindowManagerService extends IWindowManager.Stub
if (!runningAppAnimation) {
win.mWinAnimator.applyAnimationLocked(
WindowManagerPolicy.TRANSIT_EXIT, false);
- scheduleNotifyWindowTranstionIfNeededLocked(win,
- WindowManagerPolicy.TRANSIT_EXIT);
+ if (mMagnificationMediator != null) {
+ mMagnificationMediator.onWindowTransitionLw(win,
+ WindowManagerPolicy.TRANSIT_EXIT);
+ }
}
changed = true;
win.mDisplayContent.layoutNeeded = true;
@@ -5727,7 +5627,9 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
- scheduleNotifyRotationChangedIfNeededLocked(displayContent, rotation);
+ if (mMagnificationMediator != null) {
+ mMagnificationMediator.onRotationChangedLw(Display.DEFAULT_DISPLAY, rotation);
+ }
return true;
}
@@ -6109,146 +6011,6 @@ public class WindowManagerService extends IWindowManager.Stub
return success;
}
- @Override
- public void addDisplayContentChangeListener(int displayId,
- IDisplayContentChangeListener listener) {
- if (!checkCallingPermission(android.Manifest.permission.RETRIEVE_WINDOW_INFO,
- "addDisplayContentChangeListener()")) {
- throw new SecurityException("Requires RETRIEVE_WINDOW_INFO permission");
- }
- synchronized(mWindowMap) {
- DisplayContent displayContent = getDisplayContentLocked(displayId);
- if (displayContent != null) {
- if (displayContent.mDisplayContentChangeListeners == null) {
- displayContent.mDisplayContentChangeListeners =
- new RemoteCallbackList<IDisplayContentChangeListener>();
- displayContent.mDisplayContentChangeListeners.register(listener);
- }
- }
- }
- }
-
- @Override
- public void removeDisplayContentChangeListener(int displayId,
- IDisplayContentChangeListener listener) {
- if (!checkCallingPermission(android.Manifest.permission.RETRIEVE_WINDOW_INFO,
- "removeDisplayContentChangeListener()")) {
- throw new SecurityException("Requires RETRIEVE_WINDOW_INFO permission");
- }
- synchronized(mWindowMap) {
- DisplayContent displayContent = getDisplayContentLocked(displayId);
- if (displayContent != null) {
- if (displayContent.mDisplayContentChangeListeners != null) {
- displayContent.mDisplayContentChangeListeners.unregister(listener);
- if (displayContent.mDisplayContentChangeListeners
- .getRegisteredCallbackCount() == 0) {
- displayContent.mDisplayContentChangeListeners = null;
- }
- }
- }
- }
- }
-
- void scheduleNotifyWindowTranstionIfNeededLocked(WindowState window, int transition) {
- DisplayContent displayContent = window.mDisplayContent;
- if (displayContent.mDisplayContentChangeListeners != null) {
- WindowInfo info = getWindowInfoForWindowStateLocked(window);
- mH.obtainMessage(H.NOTIFY_WINDOW_TRANSITION, transition, 0, info).sendToTarget();
- }
- }
-
- private void handleNotifyWindowTranstion(int transition, WindowInfo info) {
- RemoteCallbackList<IDisplayContentChangeListener> callbacks = null;
- synchronized (mWindowMap) {
- DisplayContent displayContent = getDisplayContentLocked(info.displayId);
- if (displayContent == null) {
- return;
- }
- callbacks = displayContent.mDisplayContentChangeListeners;
- if (callbacks == null) {
- return;
- }
- }
- final int callbackCount = callbacks.beginBroadcast();
- try {
- for (int i = 0; i < callbackCount; i++) {
- try {
- callbacks.getBroadcastItem(i).onWindowTransition(info.displayId,
- transition, info);
- } catch (RemoteException re) {
- /* ignore */
- }
- }
- } finally {
- callbacks.finishBroadcast();
- }
- }
-
- private void scheduleNotifyRotationChangedIfNeededLocked(DisplayContent displayContent,
- int rotation) {
- if (displayContent.mDisplayContentChangeListeners != null
- && displayContent.mDisplayContentChangeListeners.getRegisteredCallbackCount() > 0) {
- mH.obtainMessage(H.NOTIFY_ROTATION_CHANGED, displayContent.getDisplayId(),
- rotation).sendToTarget();
- }
- }
-
- private void handleNotifyRotationChanged(int displayId, int rotation) {
- RemoteCallbackList<IDisplayContentChangeListener> callbacks = null;
- synchronized (mWindowMap) {
- DisplayContent displayContent = getDisplayContentLocked(displayId);
- if (displayContent == null) {
- return;
- }
- callbacks = displayContent.mDisplayContentChangeListeners;
- if (callbacks == null) {
- return;
- }
- }
- try {
- final int watcherCount = callbacks.beginBroadcast();
- for (int i = 0; i < watcherCount; i++) {
- try {
- callbacks.getBroadcastItem(i).onRotationChanged(rotation);
- } catch (RemoteException re) {
- /* ignore */
- }
- }
- } finally {
- callbacks.finishBroadcast();
- }
- }
-
- private void scheduleNotifyWindowLayersChangedIfNeededLocked(DisplayContent displayContent) {
- if (displayContent.mDisplayContentChangeListeners != null
- && displayContent.mDisplayContentChangeListeners.getRegisteredCallbackCount() > 0) {
- mH.obtainMessage(H.NOTIFY_WINDOW_LAYERS_CHANGED, displayContent) .sendToTarget();
- }
- }
-
- private void handleNotifyWindowLayersChanged(DisplayContent displayContent) {
- RemoteCallbackList<IDisplayContentChangeListener> callbacks = null;
- synchronized (mWindowMap) {
- callbacks = displayContent.mDisplayContentChangeListeners;
- if (callbacks == null) {
- return;
- }
- }
- try {
- final int watcherCount = callbacks.beginBroadcast();
- for (int i = 0; i < watcherCount; i++) {
- try {
- callbacks.getBroadcastItem(i).onWindowLayersChanged(
- displayContent.getDisplayId());
- } catch (RemoteException re) {
- /* ignore */
- }
- }
- } finally {
- callbacks.finishBroadcast();
- }
- }
-
public void addWindowChangeListener(WindowChangeListener listener) {
synchronized(mWindowMap) {
mWindowChangeListeners.add(listener);
@@ -6892,16 +6654,12 @@ public class WindowManagerService extends IWindowManager.Stub
public static final int UPDATE_ANIM_PARAMETERS = 25;
public static final int SHOW_STRICT_MODE_VIOLATION = 26;
public static final int DO_ANIMATION_CALLBACK = 27;
- public static final int NOTIFY_ROTATION_CHANGED = 28;
- public static final int NOTIFY_WINDOW_TRANSITION = 29;
- public static final int NOTIFY_RECTANGLE_ON_SCREEN_REQUESTED = 30;
- public static final int NOTIFY_WINDOW_LAYERS_CHANGED = 31;
- public static final int DO_DISPLAY_ADDED = 32;
- public static final int DO_DISPLAY_REMOVED = 33;
- public static final int DO_DISPLAY_CHANGED = 34;
+ public static final int DO_DISPLAY_ADDED = 28;
+ public static final int DO_DISPLAY_REMOVED = 29;
+ public static final int DO_DISPLAY_CHANGED = 30;
- public static final int CLIENT_FREEZE_TIMEOUT = 35;
+ public static final int CLIENT_FREEZE_TIMEOUT = 31;
public static final int ANIMATOR_WHAT_OFFSET = 100000;
public static final int SET_TRANSPARENT_REGION = ANIMATOR_WHAT_OFFSET + 1;
@@ -7351,34 +7109,6 @@ public class WindowManagerService extends IWindowManager.Stub
break;
}
- case NOTIFY_ROTATION_CHANGED: {
- final int displayId = msg.arg1;
- final int rotation = msg.arg2;
- handleNotifyRotationChanged(displayId, rotation);
- break;
- }
-
- case NOTIFY_WINDOW_TRANSITION: {
- final int transition = msg.arg1;
- WindowInfo info = (WindowInfo) msg.obj;
- handleNotifyWindowTranstion(transition, info);
- break;
- }
-
- case NOTIFY_RECTANGLE_ON_SCREEN_REQUESTED: {
- final int displayId = msg.arg1;
- final boolean immediate = (msg.arg2 == 1);
- Rect rectangle = (Rect) msg.obj;
- handleNotifyRectangleOnScreenRequested(displayId, rectangle, immediate);
- break;
- }
-
- case NOTIFY_WINDOW_LAYERS_CHANGED: {
- DisplayContent displayContent = (DisplayContent) msg.obj;
- handleNotifyWindowLayersChanged(displayContent);
- break;
- }
-
case DO_DISPLAY_ADDED:
synchronized (mWindowMap) {
handleDisplayAddedLocked(msg.arg1);
@@ -7823,8 +7553,9 @@ public class WindowManagerService extends IWindowManager.Stub
// "Assigned layer " + curLayer + " to " + w.mClient.asBinder());
}
- if (anyLayerChanged) {
- scheduleNotifyWindowLayersChangedIfNeededLocked(getDefaultDisplayContentLocked());
+ if (mMagnificationMediator != null && anyLayerChanged) {
+ mMagnificationMediator.onWindowLayersChangedLw(
+ windows.get(windows.size() - 1).getDisplayId());
}
}
diff --git a/services/java/com/android/server/wm/WindowState.java b/services/java/com/android/server/wm/WindowState.java
index 3b5b1eb..541e859 100644
--- a/services/java/com/android/server/wm/WindowState.java
+++ b/services/java/com/android/server/wm/WindowState.java
@@ -517,21 +517,6 @@ final class WindowState implements WindowManagerPolicy.WindowState {
}
}
- MagnificationSpec getWindowMagnificationSpecLocked() {
- MagnificationSpec spec = mDisplayContent.mMagnificationSpec;
- if (spec != null && !spec.isNop()) {
- if (mAttachedWindow != null) {
- if (!mPolicy.canMagnifyWindowLw(mAttachedWindow.mAttrs)) {
- return null;
- }
- }
- if (!mPolicy.canMagnifyWindowLw(mAttrs)) {
- return null;
- }
- }
- return spec;
- }
-
@Override
public Rect getFrameLw() {
return mFrame;
diff --git a/services/java/com/android/server/wm/WindowStateAnimator.java b/services/java/com/android/server/wm/WindowStateAnimator.java
index 945c5e3..3c9424a 100644
--- a/services/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/java/com/android/server/wm/WindowStateAnimator.java
@@ -16,6 +16,7 @@ import android.graphics.Region;
import android.os.Debug;
import android.util.Slog;
import android.view.DisplayInfo;
+import android.view.MagnificationSpec;
import android.view.Surface;
import android.view.SurfaceSession;
import android.view.WindowManager;
@@ -918,10 +919,13 @@ class WindowStateAnimator {
if (screenAnimation) {
tmpMatrix.postConcat(screenRotationAnimation.getEnterTransformation().getMatrix());
}
- MagnificationSpec spec = mWin.getWindowMagnificationSpecLocked();
- if (spec != null && !spec.isNop()) {
- tmpMatrix.postScale(spec.mScale, spec.mScale);
- tmpMatrix.postTranslate(spec.mOffsetX, spec.mOffsetY);
+ if (mService.mMagnificationMediator != null) {
+ MagnificationSpec spec = mService.mMagnificationMediator
+ .getMagnificationSpecLw(mWin);
+ if (spec != null && !spec.isNop()) {
+ tmpMatrix.postScale(spec.scale, spec.scale);
+ tmpMatrix.postTranslate(spec.offsetX, spec.offsetY);
+ }
}
// "convert" it into SurfaceFlinger's format
@@ -994,7 +998,8 @@ class WindowStateAnimator {
final boolean applyUniverseTransformation = (mAnimator.mUniverseBackground != null
&& mWin.mAttrs.type != WindowManager.LayoutParams.TYPE_UNIVERSE_BACKGROUND
&& mWin.mBaseLayer < mAnimator.mAboveUniverseLayer);
- MagnificationSpec spec = mWin.getWindowMagnificationSpecLocked();
+ MagnificationSpec spec = (mService.mMagnificationMediator != null)
+ ? mService.mMagnificationMediator.getMagnificationSpecLw(mWin) : null;
if (applyUniverseTransformation || spec != null) {
final Rect frame = mWin.mFrame;
final float tmpFloats[] = mService.mTmpFloats;
@@ -1008,8 +1013,8 @@ class WindowStateAnimator {
}
if (spec != null && !spec.isNop()) {
- tmpMatrix.postScale(spec.mScale, spec.mScale);
- tmpMatrix.postTranslate(spec.mOffsetX, spec.mOffsetY);
+ tmpMatrix.postScale(spec.scale, spec.scale);
+ tmpMatrix.postTranslate(spec.offsetX, spec.offsetY);
}
tmpMatrix.getValues(tmpFloats);
@@ -1494,7 +1499,9 @@ class WindowStateAnimator {
transit = WindowManagerPolicy.TRANSIT_SHOW;
}
applyAnimationLocked(transit, true);
- mService.scheduleNotifyWindowTranstionIfNeededLocked(mWin, transit);
+ if (mService.mMagnificationMediator != null) {
+ mService.mMagnificationMediator.onWindowTransitionLw(mWin, transit);
+ }
}
// TODO(cmautner): Move back to WindowState?
diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
index 3e625f9..141b323 100644
--- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
+++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
@@ -22,6 +22,7 @@ import com.android.internal.view.IInputMethodClient;
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
import android.graphics.Bitmap;
+import android.graphics.Rect;
import android.os.Bundle;
import android.os.IBinder;
import android.os.IRemoteCallback;
@@ -30,13 +31,11 @@ import android.util.DisplayMetrics;
import android.view.Display;
import android.view.Gravity;
import android.view.IApplicationToken;
-import android.view.IDisplayContentChangeListener;
import android.view.IInputFilter;
import android.view.IOnKeyguardExitResult;
import android.view.IRotationWatcher;
import android.view.IWindowManager;
import android.view.IWindowSession;
-import android.view.WindowInfo;
import java.util.List;
@@ -446,7 +445,7 @@ public class IWindowManagerImpl implements IWindowManager {
public void lockNow(Bundle options) {
// TODO Auto-generated method stub
}
-
+
@Override
public boolean isSafeModeEnabled() {
return false;
@@ -464,43 +463,18 @@ public class IWindowManagerImpl implements IWindowManager {
}
@Override
- public float getWindowCompatibilityScale(IBinder windowToken) throws RemoteException {
- // TODO Auto-generated method stub
- return 0;
- }
-
- @Override
public void setInputFilter(IInputFilter filter) throws RemoteException {
// TODO Auto-generated method stub
}
@Override
- public void magnifyDisplay(int dipslayId, float scale, float offsetX, float offsetY)
- throws RemoteException {
- // TODO Auto-generated method stub
- }
-
- @Override
- public void addDisplayContentChangeListener(int displayId,
- IDisplayContentChangeListener listener) throws RemoteException {
- // TODO Auto-generated method stub
- }
-
- @Override
- public void removeDisplayContentChangeListener(int displayId,
- IDisplayContentChangeListener listener) throws RemoteException {
- // TODO Auto-generated method stub
- }
-
- @Override
- public WindowInfo getWindowInfo(IBinder token) throws RemoteException {
+ public IDisplayMagnificationMediator getDisplayMagnificationMediator() {
// TODO Auto-generated method stub
return null;
}
@Override
- public void getVisibleWindowsForDisplay(int displayId, List<WindowInfo> outInfos)
- throws RemoteException {
+ public void getWindowFrame(IBinder token, Rect outFrame) {
// TODO Auto-generated method stub
}
}