summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Android.mk3
-rw-r--r--CleanSpec.mk4
-rw-r--r--api/current.txt1
-rw-r--r--core/java/android/view/IDisplayMagnificationMediator.aidl31
-rw-r--r--core/java/android/view/IMagnificationCallbacks.aidl (renamed from core/java/android/view/IDisplayMagnificationController.aidl)6
-rw-r--r--core/java/android/view/IWindowManager.aidl33
-rw-r--r--core/java/android/view/MagnificationSpec.java3
-rw-r--r--core/java/android/view/Surface.java2
-rw-r--r--core/java/android/view/WindowManagerPolicy.java19
-rw-r--r--graphics/java/android/graphics/Region.java40
-rw-r--r--policy/src/com/android/internal/policy/impl/PhoneWindowManager.java22
-rw-r--r--services/java/com/android/server/accessibility/AccessibilityInputFilter.java117
-rw-r--r--services/java/com/android/server/accessibility/AccessibilityManagerService.java39
-rw-r--r--services/java/com/android/server/accessibility/ScreenMagnifier.java470
-rw-r--r--services/java/com/android/server/wm/DisplayMagnificationMediator.java614
-rw-r--r--services/java/com/android/server/wm/DisplayMagnifier.java732
-rw-r--r--services/java/com/android/server/wm/WindowAnimator.java4
-rw-r--r--services/java/com/android/server/wm/WindowManagerService.java123
-rw-r--r--services/java/com/android/server/wm/WindowStateAnimator.java22
19 files changed, 1194 insertions, 1091 deletions
diff --git a/Android.mk b/Android.mk
index 11c0038..294a2fe 100644
--- a/Android.mk
+++ b/Android.mk
@@ -154,8 +154,7 @@ 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/IDisplayMagnificationMediator.aidl \
- core/java/android/view/IDisplayMagnificationController.aidl \
+ core/java/android/view/IMagnificationCallbacks.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 425794a..06f7c54 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -145,6 +145,10 @@ $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framew
$(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)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/view/IDisplayMagnificationController.java)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/view/IDisplayMagnificationController.P)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/view/IDisplayMagnificationMediator.java)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/view/IDisplayMagnificationMediator.P)
# ************************************************
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
diff --git a/api/current.txt b/api/current.txt
index 57d65ba..8faebfc 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -24753,7 +24753,6 @@ 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/view/IDisplayMagnificationMediator.aidl b/core/java/android/view/IDisplayMagnificationMediator.aidl
deleted file mode 100644
index aa25dac..0000000
--- a/core/java/android/view/IDisplayMagnificationMediator.aidl
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
-** 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/IDisplayMagnificationController.aidl b/core/java/android/view/IMagnificationCallbacks.aidl
index efe2775..032d073 100644
--- a/core/java/android/view/IDisplayMagnificationController.aidl
+++ b/core/java/android/view/IMagnificationCallbacks.aidl
@@ -16,11 +16,13 @@
package android.view;
+import android.graphics.Region;
+
/**
* {@hide}
*/
-oneway interface IDisplayMagnificationController {
- void onMagnifedFrameChanged(int left, int top, int right, int bottom);
+oneway interface IMagnificationCallbacks {
+ void onMagnifedBoundsChanged(in Region bounds);
void onRectangleOnScreenRequested(int left, int top, int right, int bottom);
void onRotationChanged(int rotation);
void onUserContextChanged();
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 17f04e9..1ee2bb3 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -27,7 +27,7 @@ import android.graphics.Rect;
import android.os.Bundle;
import android.os.IRemoteCallback;
import android.view.IApplicationToken;
-import android.view.IDisplayMagnificationMediator;
+import android.view.IMagnificationCallbacks;
import android.view.IOnKeyguardExitResult;
import android.view.IRotationWatcher;
import android.view.IWindowSession;
@@ -226,11 +226,6 @@ interface IWindowManager
void setInputFilter(in IInputFilter filter);
/**
- * Gets the display magnification mediator.
- */
- IDisplayMagnificationMediator getDisplayMagnificationMediator();
-
- /**
* Gets the frame of a window given its token.
*/
void getWindowFrame(IBinder token, out Rect outFrame);
@@ -245,4 +240,30 @@ interface IWindowManager
* credentials.
*/
void showAssistant();
+
+ /**
+ * Sets the display magnification callbacks. These callbacks notify
+ * the client for contextual changes related to display magnification.
+ *
+ * @param callbacks The magnification callbacks.
+ */
+ void setMagnificationCallbacks(IMagnificationCallbacks callbacks);
+
+ /**
+ * Sets the magnification spec to be applied to all windows that can be
+ * magnified.
+ *
+ * @param spec The current magnification spec.
+ */
+ void setMagnificationSpec(in MagnificationSpec spec);
+
+ /**
+ * Gets the magnification spec for a window given its token. If the
+ * window has a compatibility scale it is also folded in the returned
+ * magnification spec.
+ *
+ * @param windowToken The unique window token.
+ * @return The magnification spec if such or null.
+ */
+ MagnificationSpec getCompatibleMagnificationSpecForWindow(in IBinder windowToken);
}
diff --git a/core/java/android/view/MagnificationSpec.java b/core/java/android/view/MagnificationSpec.java
index 7fb5615..0ee6714 100644
--- a/core/java/android/view/MagnificationSpec.java
+++ b/core/java/android/view/MagnificationSpec.java
@@ -39,6 +39,9 @@ public class MagnificationSpec implements Parcelable {
}
public void initialize(float scale, float offsetX, float offsetY) {
+ if (scale < 1) {
+ throw new IllegalArgumentException("Scale must be greater than or equal to one!");
+ }
this.scale = scale;
this.offsetX = offsetX;
this.offsetY = offsetY;
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index f2c5eac..a972b75 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -812,6 +812,8 @@ public class Surface implements Parcelable {
*
* @param rotation The rotation.
* @return The rotation symbolic name.
+ *
+ * @hide
*/
public static String rotationToString(int rotation) {
switch (rotation) {
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index 7bdb44c..47ef638 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -1134,4 +1134,23 @@ public interface WindowManagerPolicy {
* {@link android.content.Intent#ACTION_ASSIST}
*/
public void showAssistant();
+
+ /**
+ * Returns whether a given window type can be magnified.
+ *
+ * @param windowType The window type.
+ * @return True if the window can be magnified.
+ */
+ public boolean canMagnifyWindow(int windowType);
+
+ /**
+ * Returns whether a given window type is considered a top level one.
+ * A top level window does not have a container, i.e. attached window,
+ * or if it has a container it is laid out as a top-level window, not
+ * as a child of its container.
+ *
+ * @param windowType The window type.
+ * @return True if the window is a top level one.
+ */
+ public boolean isTopLevelWindow(int windowType);
}
diff --git a/graphics/java/android/graphics/Region.java b/graphics/java/android/graphics/Region.java
index 27ea0f0..9773039 100644
--- a/graphics/java/android/graphics/Region.java
+++ b/graphics/java/android/graphics/Region.java
@@ -18,8 +18,15 @@ package android.graphics;
import android.os.Parcel;
import android.os.Parcelable;
+import android.util.Pools.SynchronizedPool;
public class Region implements Parcelable {
+
+ private static final int MAX_POOL_SIZE = 10;
+
+ private static final SynchronizedPool<Region> sPool =
+ new SynchronizedPool<Region>(MAX_POOL_SIZE);
+
/**
* @hide
*/
@@ -291,6 +298,39 @@ public class Region implements Parcelable {
return nativeToString(mNativeRegion);
}
+ /**
+ * @return An instance from a pool if such or a new one.
+ *
+ * @hide
+ */
+ public static Region obtain() {
+ Region region = sPool.acquire();
+ return (region != null) ? region : new Region();
+ }
+
+ /**
+ * @return An instance from a pool if such or a new one.
+ *
+ * @param other Region to copy values from for initialization.
+ *
+ * @hide
+ */
+ public static Region obtain(Region other) {
+ Region region = obtain();
+ region.set(other);
+ return region;
+ }
+
+ /**
+ * Recycles an instance.
+ *
+ * @hide
+ */
+ public void recycle() {
+ setEmpty();
+ sPool.release(this);
+ }
+
//////////////////////////////////////////////////////////////////////////
public static final Parcelable.Creator<Region> CREATOR
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 024c247..2601bd0 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -4544,6 +4544,28 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mKeyguardMediator.showAssistant();
}
+ @Override
+ public boolean canMagnifyWindow(int windowType) {
+ switch (windowType) {
+ 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 boolean isTopLevelWindow(int windowType) {
+ if (windowType >= WindowManager.LayoutParams.FIRST_SUB_WINDOW
+ && windowType <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
+ return (windowType == WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG);
+ }
+ return true;
+ }
+
/**
* Returns the human readable name of a window transition.
*
diff --git a/services/java/com/android/server/accessibility/AccessibilityInputFilter.java b/services/java/com/android/server/accessibility/AccessibilityInputFilter.java
index 45da1e1..9eb6834 100644
--- a/services/java/com/android/server/accessibility/AccessibilityInputFilter.java
+++ b/services/java/com/android/server/accessibility/AccessibilityInputFilter.java
@@ -18,7 +18,9 @@ package com.android.server.accessibility;
import android.content.Context;
import android.os.PowerManager;
+import android.util.Pools.SimplePool;
import android.util.Slog;
+import android.view.Choreographer;
import android.view.Display;
import android.view.InputDevice;
import android.view.InputEvent;
@@ -27,6 +29,12 @@ import android.view.MotionEvent;
import android.view.WindowManagerPolicy;
import android.view.accessibility.AccessibilityEvent;
+/**
+ * This class is an input filter for implementing accessibility features such
+ * as display magnification and explore by touch.
+ *
+ * NOTE: This class has to be created and poked only from the main thread.
+ */
class AccessibilityInputFilter extends InputFilter implements EventStreamTransformation {
private static final String TAG = AccessibilityInputFilter.class.getSimpleName();
@@ -49,12 +57,31 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo
*/
static final int FLAG_FEATURE_TOUCH_EXPLORATION = 0x00000002;
+ private final Runnable mProcessBatchedEventsRunnable = new Runnable() {
+ @Override
+ public void run() {
+ final long frameTimeNanos = mChoreographer.getFrameTimeNanos();
+ if (DEBUG) {
+ Slog.i(TAG, "Begin batch processing for frame: " + frameTimeNanos);
+ }
+ processBatchedEvents(frameTimeNanos);
+ if (DEBUG) {
+ Slog.i(TAG, "End batch processing.");
+ }
+ if (mEventQueue != null) {
+ scheduleProcessBatchedEvents();
+ }
+ }
+ };
+
private final Context mContext;
private final PowerManager mPm;
private final AccessibilityManagerService mAms;
+ private final Choreographer mChoreographer;
+
private int mCurrentDeviceId;
private boolean mInstalled;
@@ -65,11 +92,14 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo
private ScreenMagnifier mScreenMagnifier;
private EventStreamTransformation mEventHandler;
+ private MotionEventHolder mEventQueue;
+
AccessibilityInputFilter(Context context, AccessibilityManagerService service) {
super(context.getMainLooper());
mContext = context;
mAms = service;
mPm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
+ mChoreographer = Choreographer.getInstance();
}
@Override
@@ -119,10 +149,61 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo
}
mCurrentDeviceId = deviceId;
}
+ batchMotionEvent((MotionEvent) event, policyFlags);
+ }
+
+ private void scheduleProcessBatchedEvents() {
+ mChoreographer.postCallback(Choreographer.CALLBACK_INPUT,
+ mProcessBatchedEventsRunnable, null);
+ }
+
+ private void batchMotionEvent(MotionEvent event, int policyFlags) {
+ if (DEBUG) {
+ Slog.i(TAG, "Batching event: " + event + ", policyFlags: " + policyFlags);
+ }
+ if (mEventQueue == null) {
+ mEventQueue = MotionEventHolder.obtain(event, policyFlags);
+ scheduleProcessBatchedEvents();
+ return;
+ }
+ if (mEventQueue.event.addBatch(event)) {
+ return;
+ }
+ MotionEventHolder holder = MotionEventHolder.obtain(event, policyFlags);
+ holder.next = mEventQueue;
+ mEventQueue.previous = holder;
+ mEventQueue = holder;
+ }
+
+ private void processBatchedEvents(long frameNanos) {
+ MotionEventHolder current = mEventQueue;
+ while (current.next != null) {
+ current = current.next;
+ }
+ while (true) {
+ if (current == null) {
+ mEventQueue = null;
+ break;
+ }
+ if (current.event.getEventTimeNano() >= frameNanos) {
+ // Finished with this choreographer frame. Do the rest on the next one.
+ current.next = null;
+ break;
+ }
+ handleMotionEvent(current.event, current.policyFlags);
+ MotionEventHolder prior = current;
+ current = current.previous;
+ prior.recycle();
+ }
+ }
+
+ private void handleMotionEvent(MotionEvent event, int policyFlags) {
+ if (DEBUG) {
+ Slog.i(TAG, "Handling batched event: " + event + ", policyFlags: " + policyFlags);
+ }
mPm.userActivity(event.getEventTime(), false);
- MotionEvent rawEvent = (MotionEvent) event;
- MotionEvent transformedEvent = MotionEvent.obtain(rawEvent);
- mEventHandler.onMotionEvent(transformedEvent, rawEvent, policyFlags);
+ MotionEvent transformedEvent = MotionEvent.obtain(event);
+ mEventHandler.onMotionEvent(transformedEvent, event, policyFlags);
transformedEvent.recycle();
}
@@ -203,4 +284,34 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo
public void onDestroy() {
/* ignore */
}
+
+ private static class MotionEventHolder {
+ private static final int MAX_POOL_SIZE = 32;
+ private static final SimplePool<MotionEventHolder> sPool =
+ new SimplePool<MotionEventHolder>(MAX_POOL_SIZE);
+
+ public int policyFlags;
+ public MotionEvent event;
+ public MotionEventHolder next;
+ public MotionEventHolder previous;
+
+ public static MotionEventHolder obtain(MotionEvent event, int policyFlags) {
+ MotionEventHolder holder = sPool.acquire();
+ if (holder == null) {
+ holder = new MotionEventHolder();
+ }
+ holder.event = MotionEvent.obtain(event);
+ holder.policyFlags = policyFlags;
+ return holder;
+ }
+
+ public void recycle() {
+ event.recycle();
+ event = null;
+ policyFlags = 0;
+ next = null;
+ previous = null;
+ sPool.release(this);
+ }
+ }
}
diff --git a/services/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
index 1d0e3a3..3e3e7dc 100644
--- a/services/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -65,7 +65,6 @@ 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;
@@ -159,8 +158,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
private final MainHandler mMainHandler;
- private IDisplayMagnificationMediator mMagnificationMediator;
-
private Service mUiAutomationService;
private Service mQueryBridge;
@@ -539,7 +536,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
accessibilityServiceInfo, true);
mUiAutomationService.onServiceConnected(componentName, serviceClient.asBinder());
- updateInputFilterLocked(userState);
+ scheduleUpdateInputFilter(userState);
scheduleSendStateToClientsLocked(userState);
}
}
@@ -570,7 +567,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
userState.mTouchExplorationGrantedServices.add(service);
// Update the internal state.
performServiceManagementLocked(userState);
- updateInputFilterLocked(userState);
+ scheduleUpdateInputFilter(userState);
scheduleSendStateToClientsLocked(userState);
}
}
@@ -736,7 +733,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
mTempStateChangeForCurrentUserMemento.clear();
// Update the internal state.
performServiceManagementLocked(userState);
- updateInputFilterLocked(userState);
+ scheduleUpdateInputFilter(userState);
scheduleSendStateToClientsLocked(userState);
}
}
@@ -890,7 +887,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
service.linkToOwnDeath();
userState.mServices.add(service);
userState.mComponentNameToServiceMap.put(service.mComponentName, service);
- updateInputFilterLocked(userState);
+ scheduleUpdateInputFilter(userState);
tryEnableTouchExplorationLocked(service);
} catch (RemoteException e) {
/* do nothing */
@@ -912,7 +909,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
userState.mComponentNameToServiceMap.remove(service.mComponentName);
service.unlinkToOwnDeath();
service.dispose();
- updateInputFilterLocked(userState);
+ scheduleUpdateInputFilter(userState);
tryDisableTouchExplorationLocked(service);
return removed;
}
@@ -1090,7 +1087,11 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
}
}
- private void updateInputFilterLocked(UserState userState) {
+ private void scheduleUpdateInputFilter(UserState userState) {
+ mMainHandler.obtainMessage(MainHandler.MSG_UPDATE_INPUT_FILTER, userState).sendToTarget();
+ }
+
+ private void updateInputFilter(UserState userState) {
boolean setInputFilter = false;
AccessibilityInputFilter inputFilter = null;
synchronized (mLock) {
@@ -1200,7 +1201,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
handleAccessibilityEnabledSettingChangedLocked(userState);
performServiceManagementLocked(userState);
- updateInputFilterLocked(userState);
+ scheduleUpdateInputFilter(userState);
scheduleSendStateToClientsLocked(userState);
}
@@ -1355,6 +1356,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
public static final int MSG_SEND_RECREATE_INTERNAL_STATE = 4;
public static final int MSG_UPDATE_ACTIVE_WINDOW = 5;
public static final int MSG_ANNOUNCE_NEW_USER_IF_NEEDED = 6;
+ public static final int MSG_UPDATE_INPUT_FILTER = 7;
public MainHandler(Looper looper) {
super(looper);
@@ -1398,6 +1400,10 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
case MSG_ANNOUNCE_NEW_USER_IF_NEEDED: {
announceNewUserIfNeeded();
} break;
+ case MSG_UPDATE_INPUT_FILTER: {
+ UserState userState = (UserState) msg.obj;
+ updateInputFilter(userState);
+ } break;
}
}
@@ -2220,16 +2226,13 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
private MagnificationSpec getCompatibleMagnificationSpec(int windowId) {
try {
- if (mMagnificationMediator == null) {
- mMagnificationMediator = mWindowManagerService
- .getDisplayMagnificationMediator();
- }
IBinder windowToken = mGlobalWindowTokens.get(windowId);
if (windowToken == null) {
windowToken = getCurrentUserStateLocked().mWindowTokens.get(windowId);
}
if (windowToken != null) {
- return mMagnificationMediator.getCompatibleMagnificationSpec(windowToken);
+ return mWindowManagerService.getCompatibleMagnificationSpecForWindow(
+ windowToken);
}
} catch (RemoteException re) {
/* ignore */
@@ -2581,7 +2584,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
UserState userState = getCurrentUserStateLocked();
handleAccessibilityEnabledSettingChangedLocked(userState);
performServiceManagementLocked(userState);
- updateInputFilterLocked(userState);
+ scheduleUpdateInputFilter(userState);
scheduleSendStateToClientsLocked(userState);
}
}
@@ -2591,7 +2594,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
if (mUiAutomationService == null) {
UserState userState = getCurrentUserStateLocked();
handleTouchExplorationEnabledSettingChangedLocked(userState);
- updateInputFilterLocked(userState);
+ scheduleUpdateInputFilter(userState);
scheduleSendStateToClientsLocked(userState);
}
}
@@ -2601,7 +2604,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
if (mUiAutomationService == null) {
UserState userState = getCurrentUserStateLocked();
handleDisplayMagnificationEnabledSettingChangedLocked(userState);
- updateInputFilterLocked(userState);
+ scheduleUpdateInputFilter(userState);
scheduleSendStateToClientsLocked(userState);
}
}
diff --git a/services/java/com/android/server/accessibility/ScreenMagnifier.java b/services/java/com/android/server/accessibility/ScreenMagnifier.java
index e5f0924..1bf2c42 100644
--- a/services/java/com/android/server/accessibility/ScreenMagnifier.java
+++ b/services/java/com/android/server/accessibility/ScreenMagnifier.java
@@ -16,25 +16,17 @@
package com.android.server.accessibility;
-import android.animation.Animator;
-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;
import android.content.IntentFilter;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.PixelFormat;
-import android.graphics.PorterDuff.Mode;
import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.hardware.display.DisplayManager;
-import android.hardware.display.DisplayManager.DisplayListener;
+import android.graphics.Region;
import android.os.AsyncTask;
+import android.os.Binder;
import android.os.Handler;
import android.os.Message;
import android.os.RemoteException;
@@ -44,13 +36,9 @@ import android.provider.Settings;
import android.text.TextUtils;
import android.util.Property;
import android.util.Slog;
-import android.view.Display;
-import android.view.DisplayInfo;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
-import android.view.Gravity;
-import android.view.IDisplayMagnificationController;
-import android.view.IDisplayMagnificationMediator;
+import android.view.IMagnificationCallbacks;
import android.view.IWindowManager;
import android.view.MagnificationSpec;
import android.view.MotionEvent;
@@ -60,13 +48,9 @@ import android.view.ScaleGestureDetector;
import android.view.ScaleGestureDetector.OnScaleGestureListener;
import android.view.View;
import android.view.ViewConfiguration;
-import android.view.ViewGroup;
-import android.view.WindowManager;
import android.view.accessibility.AccessibilityEvent;
import android.view.animation.DecelerateInterpolator;
-import android.view.animation.Interpolator;
-import com.android.internal.R;
import com.android.internal.os.SomeArgs;
import java.util.Locale;
@@ -110,7 +94,7 @@ import java.util.Locale;
*
* 6. The magnification scale will be persisted in settings and in the cloud.
*/
-public final class ScreenMagnifier extends IDisplayMagnificationController.Stub
+public final class ScreenMagnifier extends IMagnificationCallbacks.Stub
implements EventStreamTransformation {
private static final String LOG_TAG = ScreenMagnifier.class.getSimpleName();
@@ -121,7 +105,6 @@ public final class ScreenMagnifier extends IDisplayMagnificationController.Stub
private static final boolean DEBUG_PANNING = false;
private static final boolean DEBUG_SCALING = false;
private static final boolean DEBUG_MAGNIFICATION_CONTROLLER = false;
- private static final boolean DEBUG_VIEWPORT_WINDOW = false;
private static final int STATE_DELEGATING = 1;
private static final int STATE_DETECTING = 2;
@@ -131,22 +114,22 @@ public final class ScreenMagnifier extends IDisplayMagnificationController.Stub
private static final float DEFAULT_MAGNIFICATION_SCALE = 2.0f;
private static final int MULTI_TAP_TIME_SLOP_ADJUSTMENT = 50;
- private static final int MESSAGE_ON_MAGNIFIED_FRAME_CHANGED = 1;
+ private static final int MESSAGE_ON_MAGNIFIED_BOUNDS_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 static final int DEFAULT_SCREEN_MAGNIFICATION_AUTO_UPDATE = 1;
- private static final float DEFAULT_WINDOW_ANIMATION_SCALE = 1.0f;
+
+ private static final int MY_PID = android.os.Process.myPid();
private final Rect mTempRect = new Rect();
private final Rect mTempRect1 = new Rect();
private final Context mContext;
+ private final IWindowManager mWindowManager;
private final MagnificationController mMagnificationController;
private final ScreenStateObserver mScreenStateObserver;
- private final ViewportWindow mViewportWindow;
private final DetectingStateHandler mDetectingStateHandler;
private final MagnifiedContentInteractonStateHandler mMagnifiedContentInteractonStateHandler;
@@ -161,11 +144,8 @@ public final class ScreenMagnifier extends IDisplayMagnificationController.Stub
private final int mMultiTapDistanceSlop;
private final long mLongAnimationDuration;
- private final float mWindowAnimationScale;
-
- private final Rect mMagnifiedFrame = new Rect();
- private IDisplayMagnificationMediator mDisplayMagnifier;
+ private final Region mMagnifiedBounds = new Region();
private EventStreamTransformation mNext;
@@ -178,18 +158,16 @@ public final class ScreenMagnifier extends IDisplayMagnificationController.Stub
private long mDelegatingStateDownTime;
+ private boolean mUpdateMagnificationSpecOnNextBoundsChange;
+
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();
+ case MESSAGE_ON_MAGNIFIED_BOUNDS_CHANGED: {
+ Region bounds = (Region) message.obj;
+ handleOnMagnifiedBoundsChanged(bounds);
+ bounds.recycle();
} break;
case MESSAGE_ON_RECTANGLE_ON_SCREEN_REQUESTED: {
SomeArgs args = (SomeArgs) message.obj;
@@ -207,23 +185,20 @@ public final class ScreenMagnifier extends IDisplayMagnificationController.Stub
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 = IWindowManager.Stub.asInterface(
+ ServiceManager.getService("window"));
mAms = service;
mLongAnimationDuration = context.getResources().getInteger(
com.android.internal.R.integer.config_longAnimTime);
mTapDistanceSlop = ViewConfiguration.get(context).getScaledTouchSlop();
mMultiTapDistanceSlop = ViewConfiguration.get(context).getScaledDoubleTapSlop();
- mWindowAnimationScale = Settings.Global.getFloat(context.getContentResolver(),
- Settings.Global.WINDOW_ANIMATION_SCALE, DEFAULT_WINDOW_ANIMATION_SCALE);
mDetectingStateHandler = new DetectingStateHandler();
mStateViewportDraggingHandler = new StateViewportDraggingHandler();
@@ -231,15 +206,10 @@ public final class ScreenMagnifier extends IDisplayMagnificationController.Stub
context);
mMagnificationController = new MagnificationController(mLongAnimationDuration);
- mViewportWindow = new ViewportWindow(context, displayId);
- mScreenStateObserver = new ScreenStateObserver(context, mMagnificationController,
- mViewportWindow);
+ mScreenStateObserver = new ScreenStateObserver(context, mMagnificationController);
try {
- IWindowManager windowManagerService = IWindowManager.Stub.asInterface(
- ServiceManager.getService("window"));
- mDisplayMagnifier = windowManagerService.getDisplayMagnificationMediator();
- mDisplayMagnifier.addController(Display.DEFAULT_DISPLAY, this);
+ mWindowManager.setMagnificationCallbacks(this);
} catch (RemoteException re) {
/* ignore */
}
@@ -248,18 +218,30 @@ public final class ScreenMagnifier extends IDisplayMagnificationController.Stub
}
@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();
+ public void onMagnifedBoundsChanged(Region bounds) {
+ Region newBounds = Region.obtain(bounds);
+ mHandler.obtainMessage(MESSAGE_ON_MAGNIFIED_BOUNDS_CHANGED, newBounds).sendToTarget();
+ if (MY_PID != Binder.getCallingPid()) {
+ bounds.recycle();
+ }
}
- private void handleOnMagnifiedFrameChanged(int left, int top, int right, int bottom) {
- mMagnifiedFrame.set(left, top, right, bottom);
- mViewportWindow.setBounds(mMagnifiedFrame, mMagnificationController.isMagnifying());
+ private void handleOnMagnifiedBoundsChanged(Region bounds) {
+ // If there was a rotation we have to update the center of the magnified
+ // region since the old offset X/Y may be out of its acceptable range for
+ // the new display width and height.
+ if (mUpdateMagnificationSpecOnNextBoundsChange) {
+ mUpdateMagnificationSpecOnNextBoundsChange = false;
+ MagnificationSpec spec = mMagnificationController.getMagnificationSpec();
+ Rect magnifiedFrame = mTempRect;
+ mMagnifiedBounds.getBounds(magnifiedFrame);
+ final float scale = spec.scale;
+ final float centerX = (-spec.offsetX + magnifiedFrame.width() / 2) / scale;
+ final float centerY = (-spec.offsetY + magnifiedFrame.height() / 2) / scale;
+ mMagnificationController.setScaleAndMagnifiedRegionCenter(scale, centerX,
+ centerY, false);
+ }
+ mMagnifiedBounds.set(bounds);
mAms.onMagnificationStateChanged();
}
@@ -274,35 +256,35 @@ public final class ScreenMagnifier extends IDisplayMagnificationController.Stub
}
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)) {
+ Rect magnifiedFrame = mTempRect;
+ mMagnifiedBounds.getBounds(magnifiedFrame);
+ if (!magnifiedFrame.intersects(left, top, right, bottom)) {
return;
}
Rect magnifFrameInScreenCoords = mTempRect1;
getMagnifiedFrameInContentCoords(magnifFrameInScreenCoords);
final float scrollX;
final float scrollY;
- if (rectangle.width() > magnifFrameInScreenCoords.width()) {
+ if (right - left > magnifFrameInScreenCoords.width()) {
final int direction = TextUtils.getLayoutDirectionFromLocale(Locale.getDefault());
if (direction == View.LAYOUT_DIRECTION_LTR) {
- scrollX = rectangle.left - magnifFrameInScreenCoords.left;
+ scrollX = left - magnifFrameInScreenCoords.left;
} else {
- scrollX = rectangle.right - magnifFrameInScreenCoords.right;
+ scrollX = 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 if (left < magnifFrameInScreenCoords.left) {
+ scrollX = left - magnifFrameInScreenCoords.left;
+ } else if (right > magnifFrameInScreenCoords.right) {
+ scrollX = 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;
+ if (bottom - top > magnifFrameInScreenCoords.height()) {
+ scrollY = top - magnifFrameInScreenCoords.top;
+ } else if (top < magnifFrameInScreenCoords.top) {
+ scrollY = top - magnifFrameInScreenCoords.top;
+ } else if (bottom > magnifFrameInScreenCoords.bottom) {
+ scrollY = bottom - magnifFrameInScreenCoords.bottom;
} else {
scrollY = 0;
}
@@ -310,13 +292,6 @@ public final class ScreenMagnifier extends IDisplayMagnificationController.Stub
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();
@@ -324,12 +299,8 @@ public final class ScreenMagnifier extends IDisplayMagnificationController.Stub
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);
+ mUpdateMagnificationSpecOnNextBoundsChange = true;
}
}
@@ -342,11 +313,17 @@ public final class ScreenMagnifier extends IDisplayMagnificationController.Stub
resetMagnificationIfNeeded();
}
+ private void getMagnifiedFrameInContentCoords(Rect rect) {
+ MagnificationSpec spec = mMagnificationController.getMagnificationSpec();
+ mMagnifiedBounds.getBounds(rect);
+ rect.offset((int) -spec.offsetX, (int) -spec.offsetY);
+ rect.scale(1.0f / spec.scale);
+ }
+
private void resetMagnificationIfNeeded() {
if (mMagnificationController.isMagnifying()
&& isScreenMagnificationAutoUpdateEnabled(mContext)) {
mMagnificationController.reset(true);
- mViewportWindow.setShown(false, true);
}
}
@@ -401,7 +378,11 @@ public final class ScreenMagnifier extends IDisplayMagnificationController.Stub
@Override
public void onDestroy() {
mScreenStateObserver.destroy();
- mViewportWindow.destroy();
+ try {
+ mWindowManager.setMagnificationCallbacks(null);
+ } catch (RemoteException re) {
+ /* ignore */
+ }
}
private void handleMotionEventStateDelegating(MotionEvent event,
@@ -423,7 +404,7 @@ public final class ScreenMagnifier extends IDisplayMagnificationController.Stub
final float eventX = event.getX();
final float eventY = event.getY();
if (mMagnificationController.isMagnifying()
- && mMagnifiedFrame.contains((int) eventX, (int) eventY)) {
+ && mMagnifiedBounds.contains((int) eventX, (int) eventY)) {
final float scale = mMagnificationController.getScale();
final float scaledOffsetX = mMagnificationController.getOffsetX();
final float scaledOffsetY = mMagnificationController.getOffsetY();
@@ -619,7 +600,7 @@ public final class ScreenMagnifier extends IDisplayMagnificationController.Stub
}
final float eventX = event.getX();
final float eventY = event.getY();
- if (mMagnifiedFrame.contains((int) eventX, (int) eventY)) {
+ if (mMagnifiedBounds.contains((int) eventX, (int) eventY)) {
if (mLastMoveOutsideMagnifiedRegion) {
mLastMoveOutsideMagnifiedRegion = false;
mMagnificationController.setMagnifiedRegionCenter(eventX,
@@ -635,7 +616,6 @@ public final class ScreenMagnifier extends IDisplayMagnificationController.Stub
case MotionEvent.ACTION_UP: {
if (!mTranslationEnabledBeforePan) {
mMagnificationController.reset(true);
- mViewportWindow.setShown(false, true);
}
clear();
transitionToState(STATE_DETECTING);
@@ -693,7 +673,7 @@ public final class ScreenMagnifier extends IDisplayMagnificationController.Stub
switch (action) {
case MotionEvent.ACTION_DOWN: {
mHandler.removeMessages(MESSAGE_TRANSITION_TO_DELEGATING_STATE);
- if (!mMagnifiedFrame.contains((int) event.getX(),
+ if (!mMagnifiedBounds.contains((int) event.getX(),
(int) event.getY())) {
transitionToDelegatingStateAndClear();
return;
@@ -735,7 +715,7 @@ public final class ScreenMagnifier extends IDisplayMagnificationController.Stub
return;
}
mHandler.removeMessages(MESSAGE_ON_ACTION_TAP_AND_HOLD);
- if (!mMagnifiedFrame.contains((int) event.getX(), (int) event.getY())) {
+ if (!mMagnifiedBounds.contains((int) event.getX(), (int) event.getY())) {
transitionToDelegatingStateAndClear();
return;
}
@@ -861,10 +841,8 @@ public final class ScreenMagnifier extends IDisplayMagnificationController.Stub
if (!mMagnificationController.isMagnifying()) {
mMagnificationController.setScaleAndMagnifiedRegionCenter(getPersistedScale(),
up.getX(), up.getY(), true);
- mViewportWindow.setShown(true, true);
} else {
mMagnificationController.reset(true);
- mViewportWindow.setShown(false, true);
}
}
@@ -876,7 +854,6 @@ public final class ScreenMagnifier extends IDisplayMagnificationController.Stub
mTranslationEnabledBeforePan = mMagnificationController.isMagnifying();
mMagnificationController.setScaleAndMagnifiedRegionCenter(getPersistedScale(),
down.getX(), down.getY(), true);
- mViewportWindow.setShown(true, true);
transitionToState(STATE_VIEWPORT_DRAGGING);
}
}
@@ -1043,10 +1020,12 @@ public final class ScreenMagnifier extends IDisplayMagnificationController.Stub
}
public void setScale(float scale, float pivotX, float pivotY, boolean animate) {
+ Rect magnifiedFrame = mTempRect;
+ mMagnifiedBounds.getBounds(magnifiedFrame);
MagnificationSpec spec = mCurrentMagnificationSpec;
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 oldCenterX = (-spec.offsetX + magnifiedFrame.width() / 2) / oldScale;
+ final float oldCenterY = (-spec.offsetY + magnifiedFrame.height() / 2) / oldScale;
final float normPivotX = (-spec.offsetX + pivotX) / oldScale;
final float normPivotY = (-spec.offsetY + pivotY) / oldScale;
final float offsetX = (oldCenterX - normPivotX) * (oldScale / scale);
@@ -1099,24 +1078,30 @@ public final class ScreenMagnifier extends IDisplayMagnificationController.Stub
public void updateMagnificationSpec(float scale, float magnifiedCenterX,
float magnifiedCenterY) {
+ Rect magnifiedFrame = mTempRect;
+ mMagnifiedBounds.getBounds(magnifiedFrame);
mCurrentMagnificationSpec.scale = scale;
- final int viewportWidth = mMagnifiedFrame.width();
+ final int viewportWidth = magnifiedFrame.width();
final float nonNormOffsetX = viewportWidth / 2 - magnifiedCenterX * scale;
mCurrentMagnificationSpec.offsetX = Math.min(Math.max(nonNormOffsetX,
getMinOffsetX()), 0);
- final int viewportHeight = mMagnifiedFrame.height();
+ final int viewportHeight = magnifiedFrame.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();
+ Rect magnifiedFrame = mTempRect;
+ mMagnifiedBounds.getBounds(magnifiedFrame);
+ final float viewportWidth = magnifiedFrame.width();
return viewportWidth - viewportWidth * mCurrentMagnificationSpec.scale;
}
private float getMinOffsetY() {
- final float viewportHeight = mMagnifiedFrame.height();
+ Rect magnifiedFrame = mTempRect;
+ mMagnifiedBounds.getBounds(magnifiedFrame);
+ final float viewportHeight = magnifiedFrame.height();
return viewportHeight - viewportHeight * mCurrentMagnificationSpec.scale;
}
@@ -1138,7 +1123,7 @@ public final class ScreenMagnifier extends IDisplayMagnificationController.Stub
mSentMagnificationSpec.scale = spec.scale;
mSentMagnificationSpec.offsetX = spec.offsetX;
mSentMagnificationSpec.offsetY = spec.offsetY;
- mDisplayMagnifier.setMagnificationSpec(ScreenMagnifier.this,
+ mWindowManager.setMagnificationSpec(
MagnificationSpec.obtain(spec));
} catch (RemoteException re) {
/* ignore */
@@ -1146,12 +1131,11 @@ public final class ScreenMagnifier extends IDisplayMagnificationController.Stub
}
}
- private static final class ScreenStateObserver extends BroadcastReceiver {
+ private final class ScreenStateObserver extends BroadcastReceiver {
private static final int MESSAGE_ON_SCREEN_STATE_CHANGE = 1;
private final Context mContext;
private final MagnificationController mMagnificationController;
- private final ViewportWindow mViewportWindow;
private final Handler mHandler = new Handler() {
@Override
@@ -1166,10 +1150,9 @@ public final class ScreenMagnifier extends IDisplayMagnificationController.Stub
};
public ScreenStateObserver(Context context,
- MagnificationController magnificationController, ViewportWindow viewportWindow) {
+ MagnificationController magnificationController) {
mContext = context;
mMagnificationController = magnificationController;
- mViewportWindow = viewportWindow;
mContext.registerReceiver(this, new IntentFilter(Intent.ACTION_SCREEN_OFF));
}
@@ -1181,282 +1164,13 @@ public final class ScreenMagnifier extends IDisplayMagnificationController.Stub
public void onReceive(Context context, Intent intent) {
mHandler.obtainMessage(MESSAGE_ON_SCREEN_STATE_CHANGE,
intent.getAction()).sendToTarget();
- }
+ }
private void handleOnScreenStateChange(String action) {
if (mMagnificationController.isMagnifying()
&& isScreenMagnificationAutoUpdateEnabled(mContext)) {
mMagnificationController.reset(false);
- mViewportWindow.setShown(false, false);
- }
- }
- }
-
- 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 Rect mBounds = new Rect();
-
- private final ValueAnimator mResizeFrameAnimator;
- private final ValueAnimator mShowHideFrameAnimator;
-
- private final WindowManager mWindowManager;
- private final DisplayManager mDisplayManager;
- private final Display mDisplay;
- private final DisplayInfo mDisplayInfo = new DisplayInfo();
- private final int mDisplayId;
-
- private final ContentView mWindowContent;
- private final WindowManager.LayoutParams mWindowParams;
-
- private boolean mShown;
- private int mAlpha;
-
- public ViewportWindow(Context context, int displayId) {
- mWindowManager = (WindowManager) context.getSystemService(Service.WINDOW_SERVICE);
-
- mDisplayId = displayId;
- mDisplayManager = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
- mDisplay = mDisplayManager.getDisplay(displayId);
- mDisplayManager.registerDisplayListener(this, null);
- updateDisplayInfo();
-
- 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)) {
- 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 */
- }
- });
-
- Property<ViewportWindow, Rect> property = Property.of(ViewportWindow.class,
- 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;
- result.left = (int) (fromFrame.left
- + (toFrame.left - fromFrame.left) * fraction);
- result.top = (int) (fromFrame.top
- + (toFrame.top - fromFrame.top) * fraction);
- result.right = (int) (fromFrame.right
- + (toFrame.right - fromFrame.right) * fraction);
- result.bottom = (int) (fromFrame.bottom
- + (toFrame.bottom - fromFrame.bottom) * fraction);
- return result;
- }
- };
- mResizeFrameAnimator = ObjectAnimator.ofObject(this, property,
- evaluator, mBounds, mBounds);
- mResizeFrameAnimator.setDuration(longAnimationDuration);
- mResizeFrameAnimator.setInterpolator(interpolator);
- }
-
- public boolean isShown() {
- return mShown;
- }
-
- public void setShown(boolean shown, boolean animate) {
- if (isShown() == shown) {
- return;
- }
- if (animate) {
- if (mShowHideFrameAnimator.isRunning()) {
- mShowHideFrameAnimator.reverse();
- } else {
- if (shown) {
- show();
- mShowHideFrameAnimator.start();
- } else {
- mShowHideFrameAnimator.reverse();
- }
- }
- } else {
- mShowHideFrameAnimator.cancel();
- if (shown) {
- show();
- } else {
- hide();
- }
- }
- }
-
- 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(getBounds(), bounds);
- mResizeFrameAnimator.start();
- } else {
- setBounds(bounds);
- }
- }
-
- private void hide() {
- if (!mShown) {
- return;
- }
- mShown = false;
- mWindowManager.removeView(mWindowContent);
- if (DEBUG_VIEWPORT_WINDOW) {
- Slog.i(LOG_TAG, "ViewportWindow hidden.");
- }
- }
-
- @SuppressWarnings("unused")
- // Called reflectively from an animator.
- public int getAlpha() {
- return mAlpha;
- }
-
- @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 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);
- }
- }
-
- public void rotationChanged() {
- mWindowParams.width = mDisplayInfo.logicalWidth;
- mWindowParams.height = mDisplayInfo.logicalHeight;
- if (mShown) {
- mWindowManager.updateViewLayout(mWindowContent, mWindowParams);
- }
- }
-
- 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);
- }
- }
-
- private void updateDisplayInfo() {
- if (!mDisplay.getDisplayInfo(mDisplayInfo)) {
- Slog.e(LOG_TAG, "Display is not valid.");
- }
- }
-
- public void destroy() {
- setShown(false, true);
- mDisplayManager.unregisterDisplayListener(this);
- }
-
- @Override
- public void onDisplayChanged(int displayId) {
- if (mDisplayId == displayId) {
- updateDisplayInfo();
- }
- }
-
- @Override
- public void onDisplayAdded(int displayId) {
- /* do nothing */
- }
-
- @Override
- public void onDisplayRemoved(int displayId) {
- /* do nothing */
}
}
}
diff --git a/services/java/com/android/server/wm/DisplayMagnificationMediator.java b/services/java/com/android/server/wm/DisplayMagnificationMediator.java
deleted file mode 100644
index 0e3a6e1..0000000
--- a/services/java/com/android/server/wm/DisplayMagnificationMediator.java
+++ /dev/null
@@ -1,614 +0,0 @@
-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();
- 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/DisplayMagnifier.java b/services/java/com/android/server/wm/DisplayMagnifier.java
new file mode 100644
index 0000000..cd5ae4b
--- /dev/null
+++ b/services/java/com/android/server/wm/DisplayMagnifier.java
@@ -0,0 +1,732 @@
+/*
+ * 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;
+
+import android.animation.ObjectAnimator;
+import android.animation.ValueAnimator;
+import android.app.Service;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.PixelFormat;
+import android.graphics.Point;
+import android.graphics.PorterDuff.Mode;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.graphics.Region;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.RemoteException;
+import android.util.Pools.SimplePool;
+import android.util.Slog;
+import android.util.SparseArray;
+import android.util.TypedValue;
+import android.view.IMagnificationCallbacks;
+import android.view.MagnificationSpec;
+import android.view.Surface;
+import android.view.Surface.OutOfResourcesException;
+import android.view.WindowManager;
+import android.view.WindowManagerPolicy;
+import android.view.animation.DecelerateInterpolator;
+import android.view.animation.Interpolator;
+
+import com.android.internal.R;
+import com.android.internal.os.SomeArgs;
+import com.android.internal.policy.impl.PhoneWindowManager;
+
+/**
+ * This class is a part of the window manager and encapsulates the
+ * functionality related to display magnification.
+ */
+final class DisplayMagnifier {
+ private static final String LOG_TAG = DisplayMagnifier.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 boolean DEBUG_VIEWPORT_WINDOW = false;
+
+ private final Rect mTempRect1 = new Rect();
+ private final Rect mTempRect2 = new Rect();
+
+ private final Region mTempRegion1 = new Region();
+ private final Region mTempRegion2 = new Region();
+ private final Region mTempRegion3 = new Region();
+ private final Region mTempRegion4 = new Region();
+
+ private final Context mContext;
+ private final WindowManagerService mWindowManagerService;
+ private final MagnifiedViewport mMagnifedViewport;
+ private final Handler mHandler;
+
+ private final IMagnificationCallbacks mCallbacks;
+
+ private final long mLongAnimationDuration;
+
+ public DisplayMagnifier(WindowManagerService windowManagerService,
+ IMagnificationCallbacks callbacks) {
+ mContext = windowManagerService.mContext;
+ mWindowManagerService = windowManagerService;
+ mCallbacks = callbacks;
+ mMagnifedViewport = new MagnifiedViewport();
+ mHandler = new MyHandler(mWindowManagerService.mH.getLooper());
+ mLongAnimationDuration = mContext.getResources().getInteger(
+ com.android.internal.R.integer.config_longAnimTime);
+ }
+
+ public void setMagnificationSpecLocked(MagnificationSpec spec) {
+ mMagnifedViewport.updateMagnificationSpecLocked(spec);
+ mMagnifedViewport.recomputeBoundsLocked();
+ mWindowManagerService.scheduleAnimationLocked();
+ }
+
+ public void onRectangleOnScreenRequestedLocked(Rect rectangle, boolean immediate) {
+ if (DEBUG_RECTANGLE_REQUESTED) {
+ Slog.i(LOG_TAG, "Rectangle on screen requested: " + rectangle);
+ }
+ if (!mMagnifedViewport.isMagnifyingLocked()) {
+ return;
+ }
+ Rect magnifiedRegionBounds = mTempRect2;
+ mMagnifedViewport.getMagnifiedFrameInContentCoordsLocked(magnifiedRegionBounds);
+ if (magnifiedRegionBounds.contains(rectangle)) {
+ return;
+ }
+ SomeArgs args = SomeArgs.obtain();
+ args.argi1 = rectangle.left;
+ args.argi2 = rectangle.top;
+ args.argi3 = rectangle.right;
+ args.argi4 = rectangle.bottom;
+ mHandler.obtainMessage(MyHandler.MESSAGE_NOTIFY_RECTANGLE_ON_SCREEN_REQUESTED,
+ args).sendToTarget();
+ }
+
+ public void onWindowLayersChangedLocked() {
+ if (DEBUG_LAYERS) {
+ Slog.i(LOG_TAG, "Layers changed.");
+ }
+ mMagnifedViewport.recomputeBoundsLocked();
+ mWindowManagerService.scheduleAnimationLocked();
+ }
+
+ public void onRotationChangedLocked(DisplayContent displayContent, int rotation) {
+ if (DEBUG_ROTATION) {
+ Slog.i(LOG_TAG, "Rotaton: " + Surface.rotationToString(rotation)
+ + " displayId: " + displayContent.getDisplayId());
+ }
+ mMagnifedViewport.onRotationChangedLocked();
+ mHandler.sendEmptyMessage(MyHandler.MESSAGE_NOTIFY_ROTATION_CHANGED);
+ }
+
+ public void onWindowTransitionLocked(WindowState windowState, int transition) {
+ if (DEBUG_WINDOW_TRANSITIONS) {
+ Slog.i(LOG_TAG, "Window transition: "
+ + PhoneWindowManager.windowTransitionToString(transition)
+ + " displayId: " + windowState.getDisplayId());
+ }
+ final boolean magnifying = mMagnifedViewport.isMagnifyingLocked();
+ 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.sendEmptyMessage(MyHandler.MESSAGE_NOTIFY_USER_CONTEXT_CHANGED);
+ }
+ }
+ }
+ final int type = windowState.mAttrs.type;
+ 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 = mTempRect2;
+ mMagnifedViewport.getMagnifiedFrameInContentCoordsLocked(
+ magnifiedRegionBounds);
+ Rect touchableRegionBounds = mTempRect1;
+ windowState.getTouchableRegion(mTempRegion1);
+ mTempRegion1.getBounds(touchableRegionBounds);
+ if (!magnifiedRegionBounds.intersect(touchableRegionBounds)) {
+ try {
+ mCallbacks.onRectangleOnScreenRequested(
+ touchableRegionBounds.left,
+ touchableRegionBounds.top,
+ touchableRegionBounds.right,
+ touchableRegionBounds.bottom);
+ } catch (RemoteException re) {
+ /* ignore */
+ }
+ }
+ } break;
+ } break;
+ }
+ }
+ }
+
+ public MagnificationSpec getMagnificationSpecForWindowLocked(WindowState windowState) {
+ MagnificationSpec spec = mMagnifedViewport.getMagnificationSpecLocked();
+ if (spec != null && !spec.isNop()) {
+ WindowManagerPolicy policy = mWindowManagerService.mPolicy;
+ final int windowType = windowState.mAttrs.type;
+ if (!policy.isTopLevelWindow(windowType) && windowState.mAttachedWindow != null
+ && !policy.canMagnifyWindow(windowType)) {
+ return null;
+ }
+ if (!policy.canMagnifyWindow(windowState.mAttrs.type)) {
+ return null;
+ }
+ }
+ return spec;
+ }
+
+ /** NOTE: This has to be called within a surface transaction. */
+ public void drawMagnifiedRegionBorderIfNeededLocked() {
+ mMagnifedViewport.drawWindowIfNeededLocked();
+ }
+
+ private final class MagnifiedViewport {
+
+ private static final int DEFAUTLT_BORDER_WIDTH_DIP = 5;
+
+ private final SparseArray<WindowStateInfo> mTempWindowStateInfos =
+ new SparseArray<WindowStateInfo>();
+
+ private final float[] mTempFloats = new float[9];
+
+ private final RectF mTempRectF = new RectF();
+
+ private final Point mTempPoint = new Point();
+
+ private final Matrix mTempMatrix = new Matrix();
+
+ private final Region mMagnifiedBounds = new Region();
+ private final Region mOldMagnifiedBounds = new Region();
+
+ private final MagnificationSpec mMagnificationSpec = MagnificationSpec.obtain();
+
+ private final WindowManager mWindowManager;
+
+ private final int mBorderWidth;
+ private final int mHalfBorderWidth;
+
+ private ViewportWindow mWindow;
+
+ private boolean mFullRedrawNeeded;
+
+ public MagnifiedViewport() {
+ mWindowManager = (WindowManager) mContext.getSystemService(Service.WINDOW_SERVICE);
+ mBorderWidth = (int) TypedValue.applyDimension(
+ TypedValue.COMPLEX_UNIT_DIP, DEFAUTLT_BORDER_WIDTH_DIP,
+ mContext.getResources().getDisplayMetrics());
+ mHalfBorderWidth = (int) (mBorderWidth + 0.5) / 2;
+ mWindow = new ViewportWindow(mContext);
+ }
+
+ public void updateMagnificationSpecLocked(MagnificationSpec spec) {
+ if (spec != null) {
+ mMagnificationSpec.initialize(spec.scale, spec.offsetX, spec.offsetY);
+ } else {
+ mMagnificationSpec.clear();
+ }
+ // If this message is pending we are in a rotation animation and do not want
+ // to show the border. We will do so when the pending message is handled.
+ if (!mHandler.hasMessages(MyHandler.MESSAGE_SHOW_MAGNIFIED_REGION_BOUNDS_IF_NEEDED)) {
+ setMagnifiedRegionBorderShownLocked(isMagnifyingLocked(), true);
+ }
+ }
+
+ public void recomputeBoundsLocked() {
+ mWindowManager.getDefaultDisplay().getRealSize(mTempPoint);
+ final int screenWidth = mTempPoint.x;
+ final int screenHeight = mTempPoint.y;
+
+ Region magnifiedBounds = mMagnifiedBounds;
+ magnifiedBounds.set(0, 0, 0, 0);
+
+ Region availableBounds = mTempRegion1;
+ availableBounds.set(0, 0, screenWidth, screenHeight);
+
+ Region nonMagnifiedBounds = mTempRegion4;
+ nonMagnifiedBounds.set(0, 0, 0, 0);
+
+ SparseArray<WindowStateInfo> visibleWindows = mTempWindowStateInfos;
+ visibleWindows.clear();
+ getWindowsOnScreenLocked(visibleWindows);
+
+ final int visibleWindowCount = visibleWindows.size();
+ for (int i = visibleWindowCount - 1; i >= 0; i--) {
+ WindowStateInfo info = visibleWindows.valueAt(i);
+ if (info.mWindowState.mAttrs.type == WindowManager
+ .LayoutParams.TYPE_MAGNIFICATION_OVERLAY) {
+ continue;
+ }
+
+ Region windowBounds = mTempRegion2;
+ Matrix matrix = mTempMatrix;
+ populateTransformationMatrix(info.mWindowState, matrix);
+ RectF windowFrame = mTempRectF;
+
+ if (mWindowManagerService.mPolicy.canMagnifyWindow(info.mWindowState.mAttrs.type)) {
+ windowFrame.set(info.mWindowState.mFrame);
+ windowFrame.offset(-windowFrame.left, -windowFrame.top);
+ matrix.mapRect(windowFrame);
+ windowBounds.set((int) windowFrame.left, (int) windowFrame.top,
+ (int) windowFrame.right, (int) windowFrame.bottom);
+ magnifiedBounds.op(windowBounds, Region.Op.UNION);
+ magnifiedBounds.op(availableBounds, Region.Op.INTERSECT);
+ } else {
+ windowFrame.set(info.mTouchableRegion);
+ windowFrame.offset(-info.mWindowState.mFrame.left,
+ -info.mWindowState.mFrame.top);
+ matrix.mapRect(windowFrame);
+ windowBounds.set((int) windowFrame.left, (int) windowFrame.top,
+ (int) windowFrame.right, (int) windowFrame.bottom);
+ nonMagnifiedBounds.op(windowBounds, Region.Op.UNION);
+ windowBounds.op(magnifiedBounds, Region.Op.DIFFERENCE);
+ availableBounds.op(windowBounds, Region.Op.DIFFERENCE);
+ }
+
+ Region accountedBounds = mTempRegion2;
+ accountedBounds.set(magnifiedBounds);
+ accountedBounds.op(nonMagnifiedBounds, Region.Op.UNION);
+ accountedBounds.op(0, 0, screenWidth, screenHeight, Region.Op.INTERSECT);
+
+ if (accountedBounds.isRect()) {
+ Rect accountedFrame = mTempRect1;
+ accountedBounds.getBounds(accountedFrame);
+ if (accountedFrame.width() == screenWidth
+ && accountedFrame.height() == screenHeight) {
+ break;
+ }
+ }
+ }
+
+ for (int i = visibleWindowCount - 1; i >= 0; i--) {
+ WindowStateInfo info = visibleWindows.valueAt(i);
+ info.recycle();
+ visibleWindows.removeAt(i);
+ }
+
+ magnifiedBounds.op(mHalfBorderWidth, mHalfBorderWidth,
+ screenWidth - mHalfBorderWidth, screenHeight - mHalfBorderWidth,
+ Region.Op.INTERSECT);
+
+ if (!mOldMagnifiedBounds.equals(magnifiedBounds)) {
+ Region bounds = Region.obtain();
+ bounds.set(magnifiedBounds);
+ mHandler.obtainMessage(MyHandler.MESSAGE_NOTIFY_MAGNIFIED_BOUNDS_CHANGED,
+ bounds).sendToTarget();
+
+ mWindow.setBounds(magnifiedBounds);
+ Rect dirtyRect = mTempRect1;
+ if (mFullRedrawNeeded) {
+ mFullRedrawNeeded = false;
+ dirtyRect.set(mHalfBorderWidth, mHalfBorderWidth,
+ screenWidth - mHalfBorderWidth, screenHeight - mHalfBorderWidth);
+ mWindow.invalidate(dirtyRect);
+ } else {
+ Region dirtyRegion = mTempRegion3;
+ dirtyRegion.set(magnifiedBounds);
+ dirtyRegion.op(mOldMagnifiedBounds, Region.Op.UNION);
+ dirtyRegion.op(nonMagnifiedBounds, Region.Op.INTERSECT);
+ dirtyRegion.getBounds(dirtyRect);
+ mWindow.invalidate(dirtyRect);
+ }
+
+ mOldMagnifiedBounds.set(magnifiedBounds);
+ }
+ }
+
+ private void populateTransformationMatrix(WindowState windowState, Matrix outMatrix) {
+ mTempFloats[Matrix.MSCALE_X] = windowState.mWinAnimator.mDsDx;
+ mTempFloats[Matrix.MSKEW_Y] = windowState.mWinAnimator.mDtDx;
+ mTempFloats[Matrix.MSKEW_X] = windowState.mWinAnimator.mDsDy;
+ mTempFloats[Matrix.MSCALE_Y] = windowState.mWinAnimator.mDtDy;
+ mTempFloats[Matrix.MTRANS_X] = windowState.mShownFrame.left;
+ mTempFloats[Matrix.MTRANS_Y] = windowState.mShownFrame.top;
+ mTempFloats[Matrix.MPERSP_0] = 0;
+ mTempFloats[Matrix.MPERSP_1] = 0;
+ mTempFloats[Matrix.MPERSP_2] = 1;
+ outMatrix.setValues(mTempFloats);
+ }
+
+ private void getWindowsOnScreenLocked(SparseArray<WindowStateInfo> outWindowStates) {
+ DisplayContent displayContent = mWindowManagerService.getDefaultDisplayContentLocked();
+ WindowList windowList = displayContent.getWindowList();
+ final int windowCount = windowList.size();
+ for (int i = 0; i < windowCount; i++) {
+ WindowState windowState = windowList.get(i);
+ if ((windowState.isOnScreen() || windowState.mAttrs.type == WindowManager
+ .LayoutParams.TYPE_UNIVERSE_BACKGROUND)
+ && !windowState.mWinAnimator.mEnterAnimationPending) {
+ outWindowStates.put(windowState.mLayer, WindowStateInfo.obtain(windowState));
+ }
+ }
+ }
+
+ public void onRotationChangedLocked() {
+ // If we are magnifying, hide the magnified border window immediately so
+ // the user does not see strange artifacts during rotation. The screenshot
+ // used for rotation has already the border. After the rotation is complete
+ // we will show the border.
+ if (isMagnifyingLocked()) {
+ setMagnifiedRegionBorderShownLocked(false, false);
+ final long delay = (long) (mLongAnimationDuration
+ * mWindowManagerService.mWindowAnimationScale);
+ Message message = mHandler.obtainMessage(
+ MyHandler.MESSAGE_SHOW_MAGNIFIED_REGION_BOUNDS_IF_NEEDED);
+ mHandler.sendMessageDelayed(message, delay);
+ }
+ recomputeBoundsLocked();
+ mWindow.updateSize();
+ }
+
+ public void setMagnifiedRegionBorderShownLocked(boolean shown, boolean animate) {
+ if (shown) {
+ mFullRedrawNeeded = true;
+ mOldMagnifiedBounds.set(0, 0, 0, 0);
+ }
+ mWindow.setShown(shown, animate);
+ }
+
+ public void getMagnifiedFrameInContentCoordsLocked(Rect rect) {
+ MagnificationSpec spec = mMagnificationSpec;
+ mMagnifiedBounds.getBounds(rect);
+ rect.offset((int) -spec.offsetX, (int) -spec.offsetY);
+ rect.scale(1.0f / spec.scale);
+ }
+
+ public boolean isMagnifyingLocked() {
+ return mMagnificationSpec.scale > 1.0f;
+ }
+
+ public MagnificationSpec getMagnificationSpecLocked() {
+ return mMagnificationSpec;
+ }
+
+ /** NOTE: This has to be called within a surface transaction. */
+ public void drawWindowIfNeededLocked() {
+ recomputeBoundsLocked();
+ mWindow.drawIfNeeded();
+ }
+
+ private final class ViewportWindow {
+ private static final String SURFACE_TITLE = "Magnification Overlay";
+
+ private static final String PROPERTY_NAME_ALPHA = "alpha";
+
+ private static final int MIN_ALPHA = 0;
+ private static final int MAX_ALPHA = 255;
+
+ private final Point mTempPoint = new Point();
+ private final Region mBounds = new Region();
+ private final Rect mDirtyRect = new Rect();
+ private final Paint mPaint = new Paint();
+
+ private final ValueAnimator mShowHideFrameAnimator;
+ private final Surface mSurface;
+
+ private boolean mShown;
+ private int mAlpha;
+
+ private boolean mInvalidated;
+
+ public ViewportWindow(Context context) {
+ Surface surface = null;
+ try {
+ mWindowManager.getDefaultDisplay().getRealSize(mTempPoint);
+ surface = new Surface(mWindowManagerService.mFxSession, SURFACE_TITLE,
+ mTempPoint.x, mTempPoint.y, PixelFormat.TRANSLUCENT, Surface.HIDDEN);
+ } catch (OutOfResourcesException oore) {
+ /* ignore */
+ }
+ mSurface = surface;
+ mSurface.setLayerStack(mWindowManager.getDefaultDisplay().getLayerStack());
+ mSurface.setLayer(mWindowManagerService.mPolicy.windowTypeToLayerLw(
+ WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY)
+ * WindowManagerService.TYPE_LAYER_MULTIPLIER);
+ mSurface.setPosition(0, 0);
+
+ TypedValue typedValue = new TypedValue();
+ context.getTheme().resolveAttribute(R.attr.colorActivatedHighlight,
+ typedValue, true);
+ final int borderColor = context.getResources().getColor(typedValue.resourceId);
+
+ mPaint.setStyle(Paint.Style.STROKE);
+ mPaint.setStrokeWidth(mBorderWidth);
+ mPaint.setColor(borderColor);
+
+ 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);
+ mInvalidated = true;
+ }
+
+ public void setShown(boolean shown, boolean animate) {
+ synchronized (mWindowManagerService.mWindowMap) {
+ if (mShown == shown) {
+ return;
+ }
+ mShown = shown;
+ if (animate) {
+ if (mShowHideFrameAnimator.isRunning()) {
+ mShowHideFrameAnimator.reverse();
+ } else {
+ if (shown) {
+ mShowHideFrameAnimator.start();
+ } else {
+ mShowHideFrameAnimator.reverse();
+ }
+ }
+ } else {
+ mShowHideFrameAnimator.cancel();
+ if (shown) {
+ setAlpha(MAX_ALPHA);
+ } else {
+ setAlpha(MIN_ALPHA);
+ }
+ }
+ if (DEBUG_VIEWPORT_WINDOW) {
+ Slog.i(LOG_TAG, "ViewportWindow shown: " + mShown);
+ }
+ }
+ }
+
+ @SuppressWarnings("unused")
+ // Called reflectively from an animator.
+ public int getAlpha() {
+ synchronized (mWindowManagerService.mWindowMap) {
+ return mAlpha;
+ }
+ }
+
+ public void setAlpha(int alpha) {
+ synchronized (mWindowManagerService.mWindowMap) {
+ if (mAlpha == alpha) {
+ return;
+ }
+ mAlpha = alpha;
+ invalidate(null);
+ if (DEBUG_VIEWPORT_WINDOW) {
+ Slog.i(LOG_TAG, "ViewportWindow set alpha: " + alpha);
+ }
+ }
+ }
+
+ public void setBounds(Region bounds) {
+ synchronized (mWindowManagerService.mWindowMap) {
+ if (mBounds.equals(bounds)) {
+ return;
+ }
+ mBounds.set(bounds);
+ invalidate(mDirtyRect);
+ if (DEBUG_VIEWPORT_WINDOW) {
+ Slog.i(LOG_TAG, "ViewportWindow set bounds: " + bounds);
+ }
+ }
+ }
+
+ public void updateSize() {
+ synchronized (mWindowManagerService.mWindowMap) {
+ mWindowManager.getDefaultDisplay().getRealSize(mTempPoint);
+ mSurface.setSize(mTempPoint.x, mTempPoint.y);
+ invalidate(mDirtyRect);
+ }
+ }
+
+ public void invalidate(Rect dirtyRect) {
+ if (dirtyRect != null) {
+ mDirtyRect.set(dirtyRect);
+ } else {
+ mDirtyRect.setEmpty();
+ }
+ mInvalidated = true;
+ mWindowManagerService.scheduleAnimationLocked();
+ }
+
+ /** NOTE: This has to be called within a surface transaction. */
+ public void drawIfNeeded() {
+ synchronized (mWindowManagerService.mWindowMap) {
+ if (!mInvalidated) {
+ return;
+ }
+ mInvalidated = false;
+ Canvas canvas = null;
+ try {
+ // Empty dirty rectangle means unspecified.
+ if (mDirtyRect.isEmpty()) {
+ mBounds.getBounds(mDirtyRect);
+ }
+ mDirtyRect.inset(- mHalfBorderWidth, - mHalfBorderWidth);
+ canvas = mSurface.lockCanvas(mDirtyRect);
+ if (DEBUG_VIEWPORT_WINDOW) {
+ Slog.i(LOG_TAG, "Dirty rect: " + mDirtyRect);
+ }
+ } catch (IllegalArgumentException iae) {
+ /* ignore */
+ } catch (OutOfResourcesException oore) {
+ /* ignore */
+ }
+ if (canvas == null) {
+ return;
+ }
+ if (DEBUG_VIEWPORT_WINDOW) {
+ Slog.i(LOG_TAG, "Bounds: " + mBounds);
+ }
+ canvas.drawColor(Color.TRANSPARENT, Mode.CLEAR);
+ mPaint.setAlpha(mAlpha);
+ Path path = mBounds.getBoundaryPath();
+ canvas.drawPath(path, mPaint);
+
+ mSurface.unlockCanvasAndPost(canvas);
+
+ if (mAlpha > 0) {
+ mSurface.show();
+ } else {
+ mSurface.hide();
+ }
+ }
+ }
+ }
+ }
+
+ private static final class WindowStateInfo {
+ private static final int MAX_POOL_SIZE = 30;
+
+ private static final SimplePool<WindowStateInfo> sPool =
+ new SimplePool<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 class MyHandler extends Handler {
+ public static final int MESSAGE_NOTIFY_MAGNIFIED_BOUNDS_CHANGED = 1;
+ public static final int MESSAGE_NOTIFY_RECTANGLE_ON_SCREEN_REQUESTED = 2;
+ public static final int MESSAGE_NOTIFY_USER_CONTEXT_CHANGED = 3;
+ public static final int MESSAGE_NOTIFY_ROTATION_CHANGED = 4;
+ public static final int MESSAGE_SHOW_MAGNIFIED_REGION_BOUNDS_IF_NEEDED = 5;
+
+ public MyHandler(Looper looper) {
+ super(looper);
+ }
+
+ @Override
+ public void handleMessage(Message message) {
+ switch (message.what) {
+ case MESSAGE_NOTIFY_MAGNIFIED_BOUNDS_CHANGED: {
+ Region bounds = (Region) message.obj;
+ try {
+ mCallbacks.onMagnifedBoundsChanged(bounds);
+ } catch (RemoteException re) {
+ /* ignore */
+ } finally {
+ bounds.recycle();
+ }
+ } break;
+ case MESSAGE_NOTIFY_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;
+ try {
+ mCallbacks.onRectangleOnScreenRequested(left, top, right, bottom);
+ } catch (RemoteException re) {
+ /* ignore */
+ } finally {
+ args.recycle();
+ }
+ } break;
+ case MESSAGE_NOTIFY_USER_CONTEXT_CHANGED: {
+ try {
+ mCallbacks.onUserContextChanged();
+ } catch (RemoteException re) {
+ /* ignore */
+ }
+ } break;
+ case MESSAGE_NOTIFY_ROTATION_CHANGED: {
+ final int rotation = message.arg1;
+ try {
+ mCallbacks.onRotationChanged(rotation);
+ } catch (RemoteException re) {
+ /* ignore */
+ }
+ } break;
+ case MESSAGE_SHOW_MAGNIFIED_REGION_BOUNDS_IF_NEEDED : {
+ synchronized (mWindowManagerService.mWindowMap) {
+ if (mMagnifedViewport.isMagnifyingLocked()) {
+ mMagnifedViewport.setMagnifiedRegionBorderShownLocked(true, true);
+ mWindowManagerService.scheduleAnimationLocked();
+ }
+ }
+ } break;
+ }
+ }
+ }
+}
diff --git a/services/java/com/android/server/wm/WindowAnimator.java b/services/java/com/android/server/wm/WindowAnimator.java
index 74f51d7..a9f3c0f 100644
--- a/services/java/com/android/server/wm/WindowAnimator.java
+++ b/services/java/com/android/server/wm/WindowAnimator.java
@@ -570,6 +570,10 @@ public class WindowAnimator {
mAnimating |= dimAnimator.updateSurface(isDimmingLocked(displayId),
mCurrentTime, !mService.okToDisplay());
}
+ //TODO (multidisplay): Magnification is supported only for the default display.
+ if (mService.mDisplayMagnifier != null && displayId == Display.DEFAULT_DISPLAY) {
+ mService.mDisplayMagnifier.drawMagnifiedRegionBorderIfNeededLocked();
+ }
}
if (mService.mWatermark != null) {
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 653f075..1640cac 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -115,8 +115,8 @@ import android.view.Display;
import android.view.DisplayInfo;
import android.view.Gravity;
import android.view.IApplicationToken;
-import android.view.IDisplayMagnificationMediator;
import android.view.IInputFilter;
+import android.view.IMagnificationCallbacks;
import android.view.IOnKeyguardExitResult;
import android.view.IRotationWatcher;
import android.view.IWindow;
@@ -127,6 +127,7 @@ 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;
@@ -424,7 +425,7 @@ public class WindowManagerService extends IWindowManager.Stub
IInputMethodManager mInputMethodManager;
- DisplayMagnificationMediator mMagnificationMediator;
+ DisplayMagnifier mDisplayMagnifier;
final SurfaceSession mFxSession;
Watermark mWatermark;
@@ -2323,8 +2324,10 @@ public class WindowManagerService extends IWindowManager.Stub
if (win.mWinAnimator.applyAnimationLocked(transit, false)) {
win.mExiting = true;
}
- if (mMagnificationMediator != null) {
- mMagnificationMediator.onWindowTransitionLw(win, transit);
+ //TODO (multidisplay): Magnification is supported only for the default display.
+ if (mDisplayMagnifier != null
+ && win.getDisplayId() == Display.DEFAULT_DISPLAY) {
+ mDisplayMagnifier.onWindowTransitionLocked(win, transit);
}
}
if (win.mExiting || win.mWinAnimator.isAnimating()) {
@@ -2619,11 +2622,11 @@ public class WindowManagerService extends IWindowManager.Stub
public void onRectangleOnScreenRequested(IBinder token, Rect rectangle, boolean immediate) {
synchronized (mWindowMap) {
- if (mMagnificationMediator != null) {
+ if (mDisplayMagnifier != null) {
WindowState window = mWindowMap.get(token);
- if (window != null) {
- mMagnificationMediator.onRectangleOnScreenRequestedLw(window, rectangle,
- immediate);
+ //TODO (multidisplay): Magnification is supported only for the default display.
+ if (window != null && window.getDisplayId() == Display.DEFAULT_DISPLAY) {
+ mDisplayMagnifier.onRectangleOnScreenRequestedLocked(rectangle, immediate);
}
}
}
@@ -2850,8 +2853,10 @@ public class WindowManagerService extends IWindowManager.Stub
}
winAnimator.destroySurfaceLocked();
}
- if (mMagnificationMediator != null) {
- mMagnificationMediator.onWindowTransitionLw(win, transit);
+ //TODO (multidisplay): Magnification is supported only for the default
+ if (mDisplayMagnifier != null
+ && win.getDisplayId() == Display.DEFAULT_DISPLAY) {
+ mDisplayMagnifier.onWindowTransitionLocked(win, transit);
}
}
}
@@ -3004,15 +3009,64 @@ public class WindowManagerService extends IWindowManager.Stub
}
@Override
- public IDisplayMagnificationMediator getDisplayMagnificationMediator() {
+ public void setMagnificationSpec(MagnificationSpec spec) {
if (!checkCallingPermission(android.Manifest.permission.MAGNIFY_DISPLAY,
- "getDisplayMagnificationMediator()")) {
- throw new SecurityException("Requires RETRIEVE_WINDOW_INFO permission.");
+ "setMagnificationSpec()")) {
+ throw new SecurityException("Requires MAGNIFY_DISPLAY permission.");
+ }
+ synchronized (mWindowMap) {
+ if (mDisplayMagnifier != null) {
+ mDisplayMagnifier.setMagnificationSpecLocked(spec);
+ } else {
+ throw new IllegalStateException("Magnification callbacks not set!");
+ }
+ }
+ if (Binder.getCallingPid() != android.os.Process.myPid()) {
+ spec.recycle();
+ }
+ }
+
+ @Override
+ public MagnificationSpec getCompatibleMagnificationSpecForWindow(IBinder windowToken) {
+ if (!checkCallingPermission(android.Manifest.permission.MAGNIFY_DISPLAY,
+ "getCompatibleMagnificationSpecForWindow()")) {
+ throw new SecurityException("Requires MAGNIFY_DISPLAY permission.");
+ }
+ synchronized (mWindowMap) {
+ WindowState windowState = mWindowMap.get(windowToken);
+ if (windowState == null) {
+ return null;
+ }
+ MagnificationSpec spec = null;
+ if (mDisplayMagnifier != null) {
+ spec = mDisplayMagnifier.getMagnificationSpecForWindowLocked(windowState);
+ }
+ if ((spec == null || spec.isNop()) && windowState.mGlobalScale == 1.0f) {
+ return null;
+ }
+ spec = (spec == null) ? MagnificationSpec.obtain() : MagnificationSpec.obtain(spec);
+ spec.scale *= windowState.mGlobalScale;
+ return spec;
+ }
+ }
+
+ @Override
+ public void setMagnificationCallbacks(IMagnificationCallbacks callbacks) {
+ if (!checkCallingPermission(android.Manifest.permission.MAGNIFY_DISPLAY,
+ "setMagnificationCallbacks()")) {
+ throw new SecurityException("Requires MAGNIFY_DISPLAY permission.");
}
- if (mMagnificationMediator == null) {
- mMagnificationMediator = new DisplayMagnificationMediator(this);
+ synchronized (mWindowMap) {
+ if (mDisplayMagnifier == null) {
+ mDisplayMagnifier = new DisplayMagnifier(this, callbacks);
+ } else {
+ if (callbacks == null) {
+ mDisplayMagnifier = null;
+ } else {
+ throw new IllegalStateException("Magnification callbacks already set!");
+ }
+ }
}
- return mMagnificationMediator;
}
private boolean applyAnimationLocked(AppWindowToken atoken,
@@ -3156,8 +3210,10 @@ public class WindowManagerService extends IWindowManager.Stub
if (win.isVisibleNow()) {
win.mWinAnimator.applyAnimationLocked(WindowManagerPolicy.TRANSIT_EXIT,
false);
- if (mMagnificationMediator != null) {
- mMagnificationMediator.onWindowTransitionLw(win,
+ //TODO (multidisplay): Magnification is supported only for the default
+ if (mDisplayMagnifier != null
+ && win.getDisplayId() == Display.DEFAULT_DISPLAY) {
+ mDisplayMagnifier.onWindowTransitionLocked(win,
WindowManagerPolicy.TRANSIT_EXIT);
}
changed = true;
@@ -3912,8 +3968,10 @@ public class WindowManagerService extends IWindowManager.Stub
delayed = runningAppAnimation = true;
}
WindowState window = wtoken.findMainWindow();
- if (window != null && mMagnificationMediator != null) {
- mMagnificationMediator.onWindowTransitionLw(window, transit);
+ //TODO (multidisplay): Magnification is supported only for the default display.
+ if (window != null && mDisplayMagnifier != null
+ && window.getDisplayId() == Display.DEFAULT_DISPLAY) {
+ mDisplayMagnifier.onWindowTransitionLocked(window, transit);
}
changed = true;
}
@@ -3932,8 +3990,10 @@ public class WindowManagerService extends IWindowManager.Stub
if (!runningAppAnimation) {
win.mWinAnimator.applyAnimationLocked(
WindowManagerPolicy.TRANSIT_ENTER, true);
- if (mMagnificationMediator != null) {
- mMagnificationMediator.onWindowTransitionLw(win,
+ //TODO (multidisplay): Magnification is supported only for the default
+ if (mDisplayMagnifier != null
+ && win.getDisplayId() == Display.DEFAULT_DISPLAY) {
+ mDisplayMagnifier.onWindowTransitionLocked(win,
WindowManagerPolicy.TRANSIT_ENTER);
}
}
@@ -3944,8 +4004,10 @@ public class WindowManagerService extends IWindowManager.Stub
if (!runningAppAnimation) {
win.mWinAnimator.applyAnimationLocked(
WindowManagerPolicy.TRANSIT_EXIT, false);
- if (mMagnificationMediator != null) {
- mMagnificationMediator.onWindowTransitionLw(win,
+ //TODO (multidisplay): Magnification is supported only for the default
+ if (mDisplayMagnifier != null
+ && win.getDisplayId() == Display.DEFAULT_DISPLAY) {
+ mDisplayMagnifier.onWindowTransitionLocked(win,
WindowManagerPolicy.TRANSIT_EXIT);
}
}
@@ -5571,8 +5633,10 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
- if (mMagnificationMediator != null) {
- mMagnificationMediator.onRotationChangedLw(Display.DEFAULT_DISPLAY, rotation);
+ //TODO (multidisplay): Magnification is supported only for the default display.
+ if (mDisplayMagnifier != null
+ && displayContent.getDisplayId() == Display.DEFAULT_DISPLAY) {
+ mDisplayMagnifier.onRotationChangedLocked(getDefaultDisplayContentLocked(), rotation);
}
return true;
@@ -7467,9 +7531,10 @@ public class WindowManagerService extends IWindowManager.Stub
// "Assigned layer " + curLayer + " to " + w.mClient.asBinder());
}
- if (mMagnificationMediator != null && anyLayerChanged) {
- mMagnificationMediator.onWindowLayersChangedLw(
- windows.get(windows.size() - 1).getDisplayId());
+ //TODO (multidisplay): Magnification is supported only for the default display.
+ if (mDisplayMagnifier != null && anyLayerChanged
+ && windows.get(windows.size() - 1).getDisplayId() == Display.DEFAULT_DISPLAY) {
+ mDisplayMagnifier.onWindowLayersChangedLocked();
}
}
diff --git a/services/java/com/android/server/wm/WindowStateAnimator.java b/services/java/com/android/server/wm/WindowStateAnimator.java
index e03e40d..9acdd49 100644
--- a/services/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/java/com/android/server/wm/WindowStateAnimator.java
@@ -15,6 +15,7 @@ import android.graphics.Rect;
import android.graphics.Region;
import android.os.Debug;
import android.util.Slog;
+import android.view.Display;
import android.view.DisplayInfo;
import android.view.MagnificationSpec;
import android.view.Surface;
@@ -919,9 +920,11 @@ class WindowStateAnimator {
if (screenAnimation) {
tmpMatrix.postConcat(screenRotationAnimation.getEnterTransformation().getMatrix());
}
- if (mService.mMagnificationMediator != null) {
- MagnificationSpec spec = mService.mMagnificationMediator
- .getMagnificationSpecLw(mWin);
+ //TODO (multidisplay): Magnification is supported only for the default display.
+ if (mService.mDisplayMagnifier != null
+ && mWin.getDisplayId() == Display.DEFAULT_DISPLAY) {
+ MagnificationSpec spec = mService.mDisplayMagnifier
+ .getMagnificationSpecForWindowLocked(mWin);
if (spec != null && !spec.isNop()) {
tmpMatrix.postScale(spec.scale, spec.scale);
tmpMatrix.postTranslate(spec.offsetX, spec.offsetY);
@@ -997,8 +1000,11 @@ class WindowStateAnimator {
final boolean applyUniverseTransformation = (mAnimator.mUniverseBackground != null
&& mWin.mAttrs.type != WindowManager.LayoutParams.TYPE_UNIVERSE_BACKGROUND
&& mWin.mBaseLayer < mAnimator.mAboveUniverseLayer);
- MagnificationSpec spec = (mService.mMagnificationMediator != null)
- ? mService.mMagnificationMediator.getMagnificationSpecLw(mWin) : null;
+ MagnificationSpec spec = null;
+ //TODO (multidisplay): Magnification is supported only for the default display.
+ if (mService.mDisplayMagnifier != null && mWin.getDisplayId() == Display.DEFAULT_DISPLAY) {
+ spec = mService.mDisplayMagnifier.getMagnificationSpecForWindowLocked(mWin);
+ }
if (applyUniverseTransformation || spec != null) {
final Rect frame = mWin.mFrame;
final float tmpFloats[] = mService.mTmpFloats;
@@ -1498,8 +1504,10 @@ class WindowStateAnimator {
transit = WindowManagerPolicy.TRANSIT_SHOW;
}
applyAnimationLocked(transit, true);
- if (mService.mMagnificationMediator != null) {
- mService.mMagnificationMediator.onWindowTransitionLw(mWin, transit);
+ //TODO (multidisplay): Magnification is supported only for the default display.
+ if (mService.mDisplayMagnifier != null
+ && mWin.getDisplayId() == Display.DEFAULT_DISPLAY) {
+ mService.mDisplayMagnifier.onWindowTransitionLocked(mWin, transit);
}
}