1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.accessibility.magnification;
18 
19 import static android.accessibilityservice.AccessibilityTrace.FLAGS_REMOTE_MAGNIFICATION_ANIMATION_CALLBACK;
20 import static android.accessibilityservice.AccessibilityTrace.FLAGS_WINDOW_MAGNIFICATION_CONNECTION;
21 import static android.accessibilityservice.AccessibilityTrace.FLAGS_WINDOW_MAGNIFICATION_CONNECTION_CALLBACK;
22 import static android.os.IBinder.DeathRecipient;
23 
24 import android.annotation.NonNull;
25 import android.annotation.Nullable;
26 import android.os.RemoteException;
27 import android.util.Slog;
28 import android.view.accessibility.IRemoteMagnificationAnimationCallback;
29 import android.view.accessibility.IWindowMagnificationConnection;
30 import android.view.accessibility.IWindowMagnificationConnectionCallback;
31 import android.view.accessibility.MagnificationAnimationCallback;
32 
33 import com.android.server.accessibility.AccessibilityTraceManager;
34 
35 /**
36  * A wrapper of {@link IWindowMagnificationConnection}.
37  */
38 class WindowMagnificationConnectionWrapper {
39 
40     private static final boolean DBG = false;
41     private static final String TAG = "WindowMagnificationConnectionWrapper";
42 
43     private final @NonNull IWindowMagnificationConnection mConnection;
44     private final @NonNull AccessibilityTraceManager mTrace;
45 
WindowMagnificationConnectionWrapper(@onNull IWindowMagnificationConnection connection, @NonNull AccessibilityTraceManager trace)46     WindowMagnificationConnectionWrapper(@NonNull IWindowMagnificationConnection connection,
47             @NonNull AccessibilityTraceManager trace) {
48         mConnection = connection;
49         mTrace = trace;
50     }
51 
52     //Should not use this instance anymore after calling it.
unlinkToDeath(@onNull DeathRecipient deathRecipient)53     void unlinkToDeath(@NonNull DeathRecipient deathRecipient) {
54         mConnection.asBinder().unlinkToDeath(deathRecipient, 0);
55     }
56 
linkToDeath(@onNull DeathRecipient deathRecipient)57     void linkToDeath(@NonNull DeathRecipient deathRecipient) throws RemoteException {
58         mConnection.asBinder().linkToDeath(deathRecipient, 0);
59     }
60 
enableWindowMagnification(int displayId, float scale, float centerX, float centerY, float magnificationFrameOffsetRatioX, float magnificationFrameOffsetRatioY, @Nullable MagnificationAnimationCallback callback)61     boolean enableWindowMagnification(int displayId, float scale, float centerX, float centerY,
62             float magnificationFrameOffsetRatioX, float magnificationFrameOffsetRatioY,
63             @Nullable MagnificationAnimationCallback callback) {
64         if (mTrace.isA11yTracingEnabledForTypes(FLAGS_WINDOW_MAGNIFICATION_CONNECTION)) {
65             mTrace.logTrace(TAG + ".enableWindowMagnification",
66                     FLAGS_WINDOW_MAGNIFICATION_CONNECTION,
67                     "displayId=" + displayId + ";scale=" + scale + ";centerX=" + centerX
68                             + ";centerY=" + centerY + ";magnificationFrameOffsetRatioX="
69                             + magnificationFrameOffsetRatioX + ";magnificationFrameOffsetRatioY="
70                             + magnificationFrameOffsetRatioY + ";callback=" + callback);
71         }
72         try {
73             mConnection.enableWindowMagnification(displayId, scale, centerX, centerY,
74                     magnificationFrameOffsetRatioX, magnificationFrameOffsetRatioY,
75                     transformToRemoteCallback(callback, mTrace));
76         } catch (RemoteException e) {
77             if (DBG) {
78                 Slog.e(TAG, "Error calling enableWindowMagnification()", e);
79             }
80             return false;
81         }
82         return true;
83     }
84 
setScale(int displayId, float scale)85     boolean setScale(int displayId, float scale) {
86         if (mTrace.isA11yTracingEnabledForTypes(FLAGS_WINDOW_MAGNIFICATION_CONNECTION)) {
87             mTrace.logTrace(TAG + ".setScale", FLAGS_WINDOW_MAGNIFICATION_CONNECTION,
88                     "displayId=" + displayId + ";scale=" + scale);
89         }
90         try {
91             mConnection.setScale(displayId, scale);
92         } catch (RemoteException e) {
93             if (DBG) {
94                 Slog.e(TAG, "Error calling setScale()", e);
95             }
96             return false;
97         }
98         return true;
99     }
100 
disableWindowMagnification(int displayId, @Nullable MagnificationAnimationCallback callback)101     boolean disableWindowMagnification(int displayId,
102             @Nullable MagnificationAnimationCallback callback) {
103         if (mTrace.isA11yTracingEnabledForTypes(FLAGS_WINDOW_MAGNIFICATION_CONNECTION)) {
104             mTrace.logTrace(TAG + ".disableWindowMagnification",
105                     FLAGS_WINDOW_MAGNIFICATION_CONNECTION,
106                     "displayId=" + displayId + ";callback=" + callback);
107         }
108         try {
109             mConnection.disableWindowMagnification(displayId,
110                     transformToRemoteCallback(callback, mTrace));
111         } catch (RemoteException e) {
112             if (DBG) {
113                 Slog.e(TAG, "Error calling disableWindowMagnification()", e);
114             }
115             return false;
116         }
117         return true;
118     }
119 
moveWindowMagnifier(int displayId, float offsetX, float offsetY)120     boolean moveWindowMagnifier(int displayId, float offsetX, float offsetY) {
121         if (mTrace.isA11yTracingEnabledForTypes(FLAGS_WINDOW_MAGNIFICATION_CONNECTION)) {
122             mTrace.logTrace(TAG + ".moveWindowMagnifier", FLAGS_WINDOW_MAGNIFICATION_CONNECTION,
123                     "displayId=" + displayId + ";offsetX=" + offsetX + ";offsetY=" + offsetY);
124         }
125         try {
126             mConnection.moveWindowMagnifier(displayId, offsetX, offsetY);
127         } catch (RemoteException e) {
128             if (DBG) {
129                 Slog.e(TAG, "Error calling moveWindowMagnifier()", e);
130             }
131             return false;
132         }
133         return true;
134     }
135 
moveWindowMagnifierToPosition(int displayId, float positionX, float positionY, @Nullable MagnificationAnimationCallback callback)136     boolean moveWindowMagnifierToPosition(int displayId, float positionX, float positionY,
137             @Nullable MagnificationAnimationCallback callback) {
138         if (mTrace.isA11yTracingEnabledForTypes(FLAGS_WINDOW_MAGNIFICATION_CONNECTION)) {
139             mTrace.logTrace(TAG + ".moveWindowMagnifierToPosition",
140                     FLAGS_WINDOW_MAGNIFICATION_CONNECTION, "displayId=" + displayId
141                             + ";positionX=" + positionX + ";positionY=" + positionY);
142         }
143         try {
144             mConnection.moveWindowMagnifierToPosition(displayId, positionX, positionY,
145                     transformToRemoteCallback(callback, mTrace));
146         } catch (RemoteException e) {
147             if (DBG) {
148                 Slog.e(TAG, "Error calling moveWindowMagnifierToPosition()", e);
149             }
150             return false;
151         }
152         return true;
153     }
154 
showMagnificationButton(int displayId, int magnificationMode)155     boolean showMagnificationButton(int displayId, int magnificationMode) {
156         if (mTrace.isA11yTracingEnabledForTypes(FLAGS_WINDOW_MAGNIFICATION_CONNECTION)) {
157             mTrace.logTrace(TAG + ".showMagnificationButton",
158                     FLAGS_WINDOW_MAGNIFICATION_CONNECTION,
159                     "displayId=" + displayId + ";mode=" + magnificationMode);
160         }
161         try {
162             mConnection.showMagnificationButton(displayId, magnificationMode);
163         } catch (RemoteException e) {
164             if (DBG) {
165                 Slog.e(TAG, "Error calling showMagnificationButton()", e);
166             }
167             return false;
168         }
169         return true;
170     }
171 
removeMagnificationButton(int displayId)172     boolean removeMagnificationButton(int displayId) {
173         if (mTrace.isA11yTracingEnabledForTypes(FLAGS_WINDOW_MAGNIFICATION_CONNECTION)) {
174             mTrace.logTrace(TAG + ".removeMagnificationButton",
175                     FLAGS_WINDOW_MAGNIFICATION_CONNECTION, "displayId=" + displayId);
176         }
177         try {
178             mConnection.removeMagnificationButton(displayId);
179         } catch (RemoteException e) {
180             if (DBG) {
181                 Slog.e(TAG, "Error calling removeMagnificationButton()", e);
182             }
183             return false;
184         }
185         return true;
186     }
187 
removeMagnificationSettingsPanel(int displayId)188     boolean removeMagnificationSettingsPanel(int displayId) {
189         if (mTrace.isA11yTracingEnabledForTypes(FLAGS_WINDOW_MAGNIFICATION_CONNECTION)) {
190             mTrace.logTrace(TAG + ".removeMagnificationSettingsPanel",
191                     FLAGS_WINDOW_MAGNIFICATION_CONNECTION, "displayId=" + displayId);
192         }
193         try {
194             mConnection.removeMagnificationSettingsPanel(displayId);
195         } catch (RemoteException e) {
196             if (DBG) {
197                 Slog.e(TAG, "Error calling removeMagnificationSettingsPanel()", e);
198             }
199             return false;
200         }
201         return true;
202     }
203 
onUserMagnificationScaleChanged(int userId, int displayId, float scale)204     boolean onUserMagnificationScaleChanged(int userId, int displayId, float scale) {
205         if (mTrace.isA11yTracingEnabledForTypes(FLAGS_WINDOW_MAGNIFICATION_CONNECTION)) {
206             mTrace.logTrace(TAG + ".onMagnificationScaleUpdated",
207                     FLAGS_WINDOW_MAGNIFICATION_CONNECTION, "displayId=" + displayId);
208         }
209         try {
210             mConnection.onUserMagnificationScaleChanged(userId, displayId, scale);
211         } catch (RemoteException e) {
212             if (DBG) {
213                 Slog.e(TAG, "Error calling onMagnificationScaleUpdated()", e);
214             }
215             return false;
216         }
217         return true;
218     }
219 
setConnectionCallback(IWindowMagnificationConnectionCallback connectionCallback)220     boolean setConnectionCallback(IWindowMagnificationConnectionCallback connectionCallback) {
221         if (mTrace.isA11yTracingEnabledForTypes(
222                 FLAGS_WINDOW_MAGNIFICATION_CONNECTION
223                 | FLAGS_WINDOW_MAGNIFICATION_CONNECTION_CALLBACK)) {
224             mTrace.logTrace(TAG + ".setConnectionCallback",
225                     FLAGS_WINDOW_MAGNIFICATION_CONNECTION
226                     | FLAGS_WINDOW_MAGNIFICATION_CONNECTION_CALLBACK,
227                     "callback=" + connectionCallback);
228         }
229         try {
230             mConnection.setConnectionCallback(connectionCallback);
231         } catch (RemoteException e) {
232             if (DBG) {
233                 Slog.e(TAG, "Error calling setConnectionCallback()", e);
234             }
235             return false;
236         }
237         return true;
238     }
239 
240     private static @Nullable
transformToRemoteCallback( MagnificationAnimationCallback callback, AccessibilityTraceManager trace)241             IRemoteMagnificationAnimationCallback transformToRemoteCallback(
242             MagnificationAnimationCallback callback, AccessibilityTraceManager trace) {
243         if (callback == null) {
244             return null;
245         }
246         return new RemoteAnimationCallback(callback, trace);
247     }
248 
249     private static class RemoteAnimationCallback extends
250             IRemoteMagnificationAnimationCallback.Stub {
251         private final MagnificationAnimationCallback mCallback;
252         private final AccessibilityTraceManager mTrace;
253 
RemoteAnimationCallback(@onNull MagnificationAnimationCallback callback, @NonNull AccessibilityTraceManager trace)254         RemoteAnimationCallback(@NonNull MagnificationAnimationCallback callback,
255                                @NonNull AccessibilityTraceManager trace) {
256             mCallback = callback;
257             mTrace = trace;
258             if (mTrace.isA11yTracingEnabledForTypes(
259                     FLAGS_REMOTE_MAGNIFICATION_ANIMATION_CALLBACK)) {
260                 mTrace.logTrace("RemoteAnimationCallback.constructor",
261                         FLAGS_REMOTE_MAGNIFICATION_ANIMATION_CALLBACK, "callback=" + callback);
262             }
263         }
264 
265         @Override
onResult(boolean success)266         public void onResult(boolean success) throws RemoteException {
267             mCallback.onResult(success);
268             if (mTrace.isA11yTracingEnabledForTypes(
269                     FLAGS_REMOTE_MAGNIFICATION_ANIMATION_CALLBACK)) {
270                 mTrace.logTrace("RemoteAnimationCallback.onResult",
271                         FLAGS_REMOTE_MAGNIFICATION_ANIMATION_CALLBACK, "success=" + success);
272             }
273 
274         }
275     }
276 }
277