• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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 android.view;
18 
19 import android.graphics.Matrix;
20 import android.os.Handler;
21 import android.os.IBinder;
22 import android.os.Looper;
23 import android.os.RemoteException;
24 import android.util.Log;
25 import android.view.accessibility.IAccessibilityEmbeddedConnection;
26 
27 import java.lang.ref.WeakReference;
28 
29 class RemoteAccessibilityController {
30     private static final String TAG = "RemoteAccessibilityController";
31     private int mHostId;
32     private RemoteAccessibilityEmbeddedConnection mConnectionWrapper;
33     private Matrix mWindowMatrixForEmbeddedHierarchy = new Matrix();
34     private final float[] mMatrixValues = new float[9];
35     private View mHostView;
36 
RemoteAccessibilityController(View v)37     RemoteAccessibilityController(View v) {
38         mHostView = v;
39     }
40 
runOnUiThread(Runnable runnable)41     private void runOnUiThread(Runnable runnable) {
42         final Handler h = mHostView.getHandler();
43         if (h != null && h.getLooper() != Looper.myLooper()) {
44             h.post(runnable);
45         } else {
46             runnable.run();
47         }
48     }
49 
assosciateHierarchy(IAccessibilityEmbeddedConnection connection, IBinder leashToken, int hostId)50     void assosciateHierarchy(IAccessibilityEmbeddedConnection connection,
51         IBinder leashToken, int hostId) {
52         mHostId = hostId;
53 
54         try {
55             leashToken = connection.associateEmbeddedHierarchy(
56                 leashToken, mHostId);
57             setRemoteAccessibilityEmbeddedConnection(connection, leashToken);
58         } catch (RemoteException e) {
59             Log.d(TAG, "Error in associateEmbeddedHierarchy " + e);
60         }
61     }
62 
disassosciateHierarchy()63     void disassosciateHierarchy() {
64         setRemoteAccessibilityEmbeddedConnection(null, null);
65     }
66 
alreadyAssociated(IAccessibilityEmbeddedConnection connection)67     boolean alreadyAssociated(IAccessibilityEmbeddedConnection connection) {
68         if (mConnectionWrapper == null) {
69             return false;
70         }
71         return mConnectionWrapper.mConnection.equals(connection);
72     }
73 
connected()74     boolean connected() {
75       return mConnectionWrapper != null;
76     }
77 
getLeashToken()78     IBinder getLeashToken() {
79         return mConnectionWrapper.getLeashToken();
80     }
81 
82     /**
83      * Wrapper of accessibility embedded connection for embedded view hierarchy.
84      */
85     private static final class RemoteAccessibilityEmbeddedConnection
86             implements IBinder.DeathRecipient {
87         private final WeakReference<RemoteAccessibilityController> mController;
88         private final IAccessibilityEmbeddedConnection mConnection;
89         private final IBinder mLeashToken;
90 
RemoteAccessibilityEmbeddedConnection( RemoteAccessibilityController controller, IAccessibilityEmbeddedConnection connection, IBinder leashToken)91         RemoteAccessibilityEmbeddedConnection(
92                 RemoteAccessibilityController controller,
93                 IAccessibilityEmbeddedConnection connection,
94                 IBinder leashToken) {
95             mController = new WeakReference<>(controller);
96             mConnection = connection;
97             mLeashToken = leashToken;
98         }
99 
getConnection()100         IAccessibilityEmbeddedConnection getConnection() {
101             return mConnection;
102         }
103 
getLeashToken()104         IBinder getLeashToken() {
105             return mLeashToken;
106         }
107 
linkToDeath()108         void linkToDeath() throws RemoteException {
109             mConnection.asBinder().linkToDeath(this, 0);
110         }
111 
unlinkToDeath()112         void unlinkToDeath() {
113             mConnection.asBinder().unlinkToDeath(this, 0);
114         }
115 
116         @Override
binderDied()117         public void binderDied() {
118             unlinkToDeath();
119             RemoteAccessibilityController controller = mController.get();
120             if (controller == null) {
121                 return;
122             }
123             controller.runOnUiThread(() -> {
124                 if (controller.mConnectionWrapper == this) {
125                     controller.mConnectionWrapper = null;
126                 }
127             });
128         }
129     }
130 
setRemoteAccessibilityEmbeddedConnection( IAccessibilityEmbeddedConnection connection, IBinder leashToken)131     private void setRemoteAccessibilityEmbeddedConnection(
132           IAccessibilityEmbeddedConnection connection, IBinder leashToken) {
133         try {
134             if (mConnectionWrapper != null) {
135                 mConnectionWrapper.getConnection()
136                     .disassociateEmbeddedHierarchy();
137                 mConnectionWrapper.unlinkToDeath();
138                 mConnectionWrapper = null;
139             }
140             if (connection != null && leashToken != null) {
141                 mConnectionWrapper =
142                     new RemoteAccessibilityEmbeddedConnection(this, connection, leashToken);
143                 mConnectionWrapper.linkToDeath();
144             }
145         } catch (RemoteException e) {
146             Log.d(TAG, "Error while setRemoteEmbeddedConnection " + e);
147         }
148     }
149 
getRemoteAccessibilityEmbeddedConnection()150     private RemoteAccessibilityEmbeddedConnection getRemoteAccessibilityEmbeddedConnection() {
151         return mConnectionWrapper;
152     }
153 
setWindowMatrix(Matrix m, boolean force)154     void setWindowMatrix(Matrix m, boolean force) {
155         // If the window matrix doesn't change, do nothing.
156         if (!force && m.equals(mWindowMatrixForEmbeddedHierarchy)) {
157             return;
158         }
159 
160         try {
161             final RemoteAccessibilityEmbeddedConnection wrapper =
162                     getRemoteAccessibilityEmbeddedConnection();
163             if (wrapper == null) {
164                 return;
165             }
166             m.getValues(mMatrixValues);
167             wrapper.getConnection().setWindowMatrix(mMatrixValues);
168             mWindowMatrixForEmbeddedHierarchy.set(m);
169         } catch (RemoteException e) {
170             Log.d(TAG, "Error while setScreenMatrix " + e);
171         }
172     }
173 
174 
175 
176 
177 
178 
179 }
180