diff options
| -rw-r--r-- | core/java/android/view/RemoteAccessibilityController.java | 168 | ||||
| -rw-r--r-- | core/java/android/view/SurfaceView.java | 347 |
2 files changed, 298 insertions, 217 deletions
diff --git a/core/java/android/view/RemoteAccessibilityController.java b/core/java/android/view/RemoteAccessibilityController.java new file mode 100644 index 000000000000..bc0fab1bcf8d --- /dev/null +++ b/core/java/android/view/RemoteAccessibilityController.java @@ -0,0 +1,168 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.view; + +import android.graphics.Matrix; +import android.os.Handler; +import android.os.IBinder; +import android.os.Looper; +import android.os.RemoteException; +import android.util.Log; +import android.view.accessibility.IAccessibilityEmbeddedConnection; + +class RemoteAccessibilityController { + private static final String TAG = "RemoteAccessibilityController"; + private int mHostId; + private RemoteAccessibilityEmbeddedConnection mConnectionWrapper; + private Matrix mScreenMatrixForEmbeddedHierarchy = new Matrix(); + private final float[] mMatrixValues = new float[9]; + private View mHostView; + + RemoteAccessibilityController(View v) { + mHostView = v; + } + + private void runOnUiThread(Runnable runnable) { + final Handler h = mHostView.getHandler(); + if (h != null && h.getLooper() != Looper.myLooper()) { + h.post(runnable); + } else { + runnable.run(); + } + } + + void assosciateHierarchy(IAccessibilityEmbeddedConnection connection, + IBinder leashToken, int hostId) { + mHostId = hostId; + + try { + leashToken = connection.associateEmbeddedHierarchy( + leashToken, mHostId); + setRemoteAccessibilityEmbeddedConnection(connection, leashToken); + } catch (RemoteException e) { + Log.d(TAG, "Error in associateEmbeddedHierarchy " + e); + } + } + + void disassosciateHierarchy() { + setRemoteAccessibilityEmbeddedConnection(null, null); + } + + boolean alreadyAssociated(IAccessibilityEmbeddedConnection connection) { + if (mConnectionWrapper == null) { + return false; + } + return mConnectionWrapper.mConnection.equals(connection); + } + + boolean connected() { + return mConnectionWrapper != null; + } + + IBinder getLeashToken() { + return mConnectionWrapper.getLeashToken(); + } + + /** + * Wrapper of accessibility embedded connection for embedded view hierarchy. + */ + private final class RemoteAccessibilityEmbeddedConnection implements IBinder.DeathRecipient { + private final IAccessibilityEmbeddedConnection mConnection; + private final IBinder mLeashToken; + + RemoteAccessibilityEmbeddedConnection(IAccessibilityEmbeddedConnection connection, + IBinder leashToken) { + mConnection = connection; + mLeashToken = leashToken; + } + + IAccessibilityEmbeddedConnection getConnection() { + return mConnection; + } + + IBinder getLeashToken() { + return mLeashToken; + } + + void linkToDeath() throws RemoteException { + mConnection.asBinder().linkToDeath(this, 0); + } + + void unlinkToDeath() { + mConnection.asBinder().unlinkToDeath(this, 0); + } + + @Override + public void binderDied() { + unlinkToDeath(); + runOnUiThread(() -> { + if (mConnectionWrapper == this) { + mConnectionWrapper = null; + } + }); + } + } + + private void setRemoteAccessibilityEmbeddedConnection( + IAccessibilityEmbeddedConnection connection, IBinder leashToken) { + try { + if (mConnectionWrapper != null) { + mConnectionWrapper.getConnection() + .disassociateEmbeddedHierarchy(); + mConnectionWrapper.unlinkToDeath(); + mConnectionWrapper = null; + } + if (connection != null && leashToken != null) { + mConnectionWrapper = + new RemoteAccessibilityEmbeddedConnection(connection, leashToken); + mConnectionWrapper.linkToDeath(); + } + } catch (RemoteException e) { + Log.d(TAG, "Error while setRemoteEmbeddedConnection " + e); + } + } + + private RemoteAccessibilityEmbeddedConnection getRemoteAccessibilityEmbeddedConnection() { + return mConnectionWrapper; + } + + void setScreenMatrix(Matrix m) { + // If the screen matrix is identity or doesn't change, do nothing. + if (m.isIdentity() || m.equals(mScreenMatrixForEmbeddedHierarchy)) { + return; + } + + try { + final RemoteAccessibilityEmbeddedConnection wrapper = + getRemoteAccessibilityEmbeddedConnection(); + if (wrapper == null) { + return; + } + m.getValues(mMatrixValues); + wrapper.getConnection().setScreenMatrix(mMatrixValues); + mScreenMatrixForEmbeddedHierarchy.set(m); + } catch (RemoteException e) { + Log.d(TAG, "Error while setScreenMatrix " + e); + } + } + + + + + + +} diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java index 33b6b0aab6bf..e3067a664f2e 100644 --- a/core/java/android/view/SurfaceView.java +++ b/core/java/android/view/SurfaceView.java @@ -227,9 +227,9 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall private SurfaceControl.Transaction mTmpTransaction = new SurfaceControl.Transaction(); private int mParentSurfaceGenerationId; - private RemoteAccessibilityEmbeddedConnection mRemoteAccessibilityEmbeddedConnection; + private RemoteAccessibilityController mRemoteAccessibilityController = + new RemoteAccessibilityController(this); - private final Matrix mScreenMatrixForEmbeddedHierarchy = new Matrix(); private final Matrix mTmpMatrix = new Matrix(); private final float[] mMatrixValues = new float[9]; @@ -927,6 +927,104 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall } } + private boolean performSurfaceTransaction(ViewRootImpl viewRoot, Translator translator, + boolean creating, boolean sizeChanged, boolean needBLASTSync) { + boolean realSizeChanged = false; + + mSurfaceLock.lock(); + try { + mDrawingStopped = !mVisible; + + if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " " + + "Cur surface: " + mSurface); + + // If we are creating the surface control or the parent surface has not + // changed, then set relative z. Otherwise allow the parent + // SurfaceChangedCallback to update the relative z. This is needed so that + // we do not change the relative z before the server is ready to swap the + // parent surface. + if (creating || (mParentSurfaceGenerationId + == viewRoot.mSurface.getGenerationId())) { + updateRelativeZ(mTmpTransaction); + } + mParentSurfaceGenerationId = viewRoot.mSurface.getGenerationId(); + + if (mViewVisibility) { + mTmpTransaction.show(mSurfaceControl); + } else { + mTmpTransaction.hide(mSurfaceControl); + } + + if (mSurfacePackage != null) { + reparentSurfacePackage(mTmpTransaction, mSurfacePackage); + } + + updateBackgroundVisibility(mTmpTransaction); + updateBackgroundColor(mTmpTransaction); + if (mUseAlpha) { + float alpha = getFixedAlpha(); + mTmpTransaction.setAlpha(mSurfaceControl, alpha); + mSurfaceAlpha = alpha; + } + + // While creating the surface, we will set it's initial + // geometry. Outside of that though, we should generally + // leave it to the RenderThread. + // + // There is one more case when the buffer size changes we aren't yet + // prepared to sync (as even following the transaction applying + // we still need to latch a buffer). + // b/28866173 + if (sizeChanged || creating || !mRtHandlingPositionUpdates) { + onSetSurfacePositionAndScaleRT(mTmpTransaction, mSurfaceControl, + mScreenRect.left, /*positionLeft*/ + mScreenRect.top /*positionTop*/ , + mScreenRect.width() / (float) mSurfaceWidth /*postScaleX*/, + mScreenRect.height() / (float) mSurfaceHeight /*postScaleY*/); + + // Set a window crop when creating the surface or changing its size to + // crop the buffer to the surface size since the buffer producer may + // use SCALING_MODE_SCALE and submit a larger size than the surface + // size. + if (mClipSurfaceToBounds && mClipBounds != null) { + mTmpTransaction.setWindowCrop(mSurfaceControl, mClipBounds); + } else { + mTmpTransaction.setWindowCrop(mSurfaceControl, mSurfaceWidth, + mSurfaceHeight); + } + } else if (needBLASTSync) { + viewRoot.setUseBLASTSyncTransaction(); + } + mTmpTransaction.setCornerRadius(mSurfaceControl, mCornerRadius); + if (sizeChanged && !creating) { + setBufferSize(mTmpTransaction); + } + + mTmpTransaction.apply(); + updateEmbeddedAccessibilityMatrix(); + + mSurfaceFrame.left = 0; + mSurfaceFrame.top = 0; + if (translator == null) { + mSurfaceFrame.right = mSurfaceWidth; + mSurfaceFrame.bottom = mSurfaceHeight; + } else { + float appInvertedScale = translator.applicationInvertedScale; + mSurfaceFrame.right = (int) (mSurfaceWidth * appInvertedScale + 0.5f); + mSurfaceFrame.bottom = (int) (mSurfaceHeight * appInvertedScale + 0.5f); + } + final int surfaceWidth = mSurfaceFrame.right; + final int surfaceHeight = mSurfaceFrame.bottom; + realSizeChanged = mLastSurfaceWidth != surfaceWidth + || mLastSurfaceHeight != surfaceHeight; + mLastSurfaceWidth = surfaceWidth; + mLastSurfaceHeight = surfaceHeight; + } finally { + mSurfaceLock.unlock(); + } + return realSizeChanged; + } + /** @hide */ protected void updateSurface() { if (!mHaveFrame) { @@ -965,7 +1063,6 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall && mRequestedVisible; final boolean sizeChanged = mSurfaceWidth != myWidth || mSurfaceHeight != myHeight; final boolean windowVisibleChanged = mWindowVisibility != mLastWindowVisibility; - boolean redrawNeeded = false; getLocationInSurface(mLocation); final boolean positionChanged = mWindowSpaceLeft != mLocation[0] || mWindowSpaceTop != mLocation[1]; @@ -988,7 +1085,7 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall + " top=" + (mWindowSpaceTop != mLocation[1])); try { - final boolean visible = mVisible = mRequestedVisible; + mVisible = mRequestedVisible; mWindowSpaceLeft = mLocation[0]; mWindowSpaceTop = mLocation[1]; mSurfaceWidth = myWidth; @@ -1014,119 +1111,26 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall return; } - boolean realSizeChanged = false; + final boolean needBLASTSync = + (layoutSizeChanged || positionChanged || visibleChanged) && + viewRoot.useBLAST(); + final boolean realSizeChanged = performSurfaceTransaction(viewRoot, + translator, creating, sizeChanged, needBLASTSync); + final boolean redrawNeeded = sizeChanged || creating || + (mVisible && !mDrawFinished); - mSurfaceLock.lock(); try { - mDrawingStopped = !visible; - - if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " " - + "Cur surface: " + mSurface); - - // If we are creating the surface control or the parent surface has not - // changed, then set relative z. Otherwise allow the parent - // SurfaceChangedCallback to update the relative z. This is needed so that - // we do not change the relative z before the server is ready to swap the - // parent surface. - if (creating || (mParentSurfaceGenerationId - == viewRoot.mSurface.getGenerationId())) { - updateRelativeZ(mTmpTransaction); - } - mParentSurfaceGenerationId = viewRoot.mSurface.getGenerationId(); - - if (mViewVisibility) { - mTmpTransaction.show(mSurfaceControl); - } else { - mTmpTransaction.hide(mSurfaceControl); - } - - if (mSurfacePackage != null) { - reparentSurfacePackage(mTmpTransaction, mSurfacePackage); - } - - updateBackgroundVisibility(mTmpTransaction); - updateBackgroundColor(mTmpTransaction); - if (mUseAlpha) { - mTmpTransaction.setAlpha(mSurfaceControl, alpha); - mSurfaceAlpha = alpha; - } - - // While creating the surface, we will set it's initial - // geometry. Outside of that though, we should generally - // leave it to the RenderThread. - // - // There is one more case when the buffer size changes we aren't yet - // prepared to sync (as even following the transaction applying - // we still need to latch a buffer). - // b/28866173 - if (sizeChanged || creating || !mRtHandlingPositionUpdates) { - onSetSurfacePositionAndScaleRT(mTmpTransaction, mSurfaceControl, - mScreenRect.left, /*positionLeft*/ - mScreenRect.top /*positionTop*/ , - mScreenRect.width() / (float) mSurfaceWidth /*postScaleX*/, - mScreenRect.height() / (float) mSurfaceHeight /*postScaleY*/); - - // Set a window crop when creating the surface or changing its size to - // crop the buffer to the surface size since the buffer producer may - // use SCALING_MODE_SCALE and submit a larger size than the surface - // size. - if (mClipSurfaceToBounds && mClipBounds != null) { - mTmpTransaction.setWindowCrop(mSurfaceControl, mClipBounds); - } else { - mTmpTransaction.setWindowCrop(mSurfaceControl, mSurfaceWidth, - mSurfaceHeight); - } - } else if ((layoutSizeChanged || positionChanged || visibleChanged) && - viewRoot.useBLAST()) { - viewRoot.setUseBLASTSyncTransaction(); - } - mTmpTransaction.setCornerRadius(mSurfaceControl, mCornerRadius); - if (sizeChanged && !creating) { - setBufferSize(mTmpTransaction); - } - - mTmpTransaction.apply(); - updateScreenMatrixForEmbeddedHierarchy(); - - if (sizeChanged || creating) { - redrawNeeded = true; - } - - mSurfaceFrame.left = 0; - mSurfaceFrame.top = 0; - if (translator == null) { - mSurfaceFrame.right = mSurfaceWidth; - mSurfaceFrame.bottom = mSurfaceHeight; - } else { - float appInvertedScale = translator.applicationInvertedScale; - mSurfaceFrame.right = (int) (mSurfaceWidth * appInvertedScale + 0.5f); - mSurfaceFrame.bottom = (int) (mSurfaceHeight * appInvertedScale + 0.5f); - } - - final int surfaceWidth = mSurfaceFrame.right; - final int surfaceHeight = mSurfaceFrame.bottom; - realSizeChanged = mLastSurfaceWidth != surfaceWidth - || mLastSurfaceHeight != surfaceHeight; - mLastSurfaceWidth = surfaceWidth; - mLastSurfaceHeight = surfaceHeight; - } finally { - mSurfaceLock.unlock(); - } - - try { - redrawNeeded |= visible && !mDrawFinished; - SurfaceHolder.Callback[] callbacks = null; final boolean surfaceChanged = creating; - if (mSurfaceCreated && (surfaceChanged || (!visible && visibleChanged))) { + if (mSurfaceCreated && (surfaceChanged || (!mVisible && visibleChanged))) { mSurfaceCreated = false; notifySurfaceDestroyed(); } copySurface(creating /* surfaceControlCreated */, sizeChanged); - if (visible && mSurface.isValid()) { + if (mVisible && mSurface.isValid()) { if (!mSurfaceCreated && (surfaceChanged || visibleChanged)) { mSurfaceCreated = true; mIsCreating = true; @@ -1754,7 +1758,7 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall @Override public void surfaceDestroyed() { setWindowStopped(true); - setRemoteAccessibilityEmbeddedConnection(null, null); + mRemoteAccessibilityController.disassosciateHierarchy(); } /** @@ -1834,14 +1838,12 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall @Override public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfoInternal(info); - final RemoteAccessibilityEmbeddedConnection wrapper = - getRemoteAccessibilityEmbeddedConnection(); - if (wrapper == null) { + if (!mRemoteAccessibilityController.connected()) { return; } // Add a leashed child when this SurfaceView embeds another view hierarchy. Getting this // leashed child would return the root node in the embedded hierarchy - info.addChild(wrapper.getLeashToken()); + info.addChild(mRemoteAccessibilityController.getLeashToken()); } @Override @@ -1850,7 +1852,7 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall // If developers explicitly set the important mode for it, don't change the mode. // Only change the mode to important when this SurfaceView isn't explicitly set and has // an embedded hierarchy. - if (mRemoteAccessibilityEmbeddedConnection == null + if (!mRemoteAccessibilityController.connected() || mode != IMPORTANT_FOR_ACCESSIBILITY_AUTO) { return mode; } @@ -1859,74 +1861,13 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall private void initEmbeddedHierarchyForAccessibility(SurfaceControlViewHost.SurfacePackage p) { final IAccessibilityEmbeddedConnection connection = p.getAccessibilityEmbeddedConnection(); - final RemoteAccessibilityEmbeddedConnection wrapper = - getRemoteAccessibilityEmbeddedConnection(); - - // Do nothing if package is embedding the same view hierarchy. - if (wrapper != null && wrapper.getConnection().equals(connection)) { - return; - } - - // If this SurfaceView embeds a different view hierarchy, unlink the previous one first. - setRemoteAccessibilityEmbeddedConnection(null, null); - - try { - final IBinder leashToken = connection.associateEmbeddedHierarchy( - getViewRootImpl().mLeashToken, getAccessibilityViewId()); - setRemoteAccessibilityEmbeddedConnection(connection, leashToken); - } catch (RemoteException e) { - Log.d(TAG, "Error while associateEmbeddedHierarchy " + e); - } - updateScreenMatrixForEmbeddedHierarchy(); - } - - private void setRemoteAccessibilityEmbeddedConnection( - IAccessibilityEmbeddedConnection connection, IBinder leashToken) { - try { - if (mRemoteAccessibilityEmbeddedConnection != null) { - mRemoteAccessibilityEmbeddedConnection.getConnection() - .disassociateEmbeddedHierarchy(); - mRemoteAccessibilityEmbeddedConnection.unlinkToDeath(); - mRemoteAccessibilityEmbeddedConnection = null; - } - if (connection != null && leashToken != null) { - mRemoteAccessibilityEmbeddedConnection = - new RemoteAccessibilityEmbeddedConnection(connection, leashToken); - mRemoteAccessibilityEmbeddedConnection.linkToDeath(); - } - } catch (RemoteException e) { - Log.d(TAG, "Error while setRemoteEmbeddedConnection " + e); - } - } - - private RemoteAccessibilityEmbeddedConnection getRemoteAccessibilityEmbeddedConnection() { - return mRemoteAccessibilityEmbeddedConnection; - } - - private void updateScreenMatrixForEmbeddedHierarchy() { - getBoundsOnScreen(mTmpRect); - mTmpMatrix.reset(); - mTmpMatrix.setTranslate(mTmpRect.left, mTmpRect.top); - mTmpMatrix.postScale(mScreenRect.width() / (float) mSurfaceWidth, - mScreenRect.height() / (float) mSurfaceHeight); - - // If the screen matrix is identity or doesn't change, do nothing. - if (mTmpMatrix.isIdentity() || mTmpMatrix.equals(mScreenMatrixForEmbeddedHierarchy)) { + if (mRemoteAccessibilityController.alreadyAssociated(connection)) { return; } + mRemoteAccessibilityController.assosciateHierarchy(connection, + getViewRootImpl().mLeashToken, getAccessibilityViewId()); - try { - final RemoteAccessibilityEmbeddedConnection wrapper = - getRemoteAccessibilityEmbeddedConnection(); - if (wrapper == null) { - return; - } - mTmpMatrix.getValues(mMatrixValues); - wrapper.getConnection().setScreenMatrix(mMatrixValues); - mScreenMatrixForEmbeddedHierarchy.set(mTmpMatrix); - } catch (RemoteException e) { - Log.d(TAG, "Error while setScreenMatrix " + e); - } + updateEmbeddedAccessibilityMatrix(); } private void notifySurfaceDestroyed() { @@ -1954,6 +1895,18 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall } } + void updateEmbeddedAccessibilityMatrix() { + if (!mRemoteAccessibilityController.connected()) { + return; + } + getBoundsOnScreen(mTmpRect); + mTmpMatrix.reset(); + mTmpMatrix.setTranslate(mTmpRect.left, mTmpRect.top); + mTmpMatrix.postScale(mScreenRect.width() / (float) mSurfaceWidth, + mScreenRect.height() / (float) mSurfaceHeight); + mRemoteAccessibilityController.setScreenMatrix(mTmpMatrix); + } + @Override protected void onFocusChanged(boolean gainFocus, @FocusDirection int direction, @Nullable Rect previouslyFocusedRect) { @@ -1970,44 +1923,4 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall + "Exception requesting focus on embedded window", e); } } - - /** - * Wrapper of accessibility embedded connection for embedded view hierarchy. - */ - private final class RemoteAccessibilityEmbeddedConnection implements IBinder.DeathRecipient { - private final IAccessibilityEmbeddedConnection mConnection; - private final IBinder mLeashToken; - - RemoteAccessibilityEmbeddedConnection(IAccessibilityEmbeddedConnection connection, - IBinder leashToken) { - mConnection = connection; - mLeashToken = leashToken; - } - - IAccessibilityEmbeddedConnection getConnection() { - return mConnection; - } - - IBinder getLeashToken() { - return mLeashToken; - } - - void linkToDeath() throws RemoteException { - mConnection.asBinder().linkToDeath(this, 0); - } - - void unlinkToDeath() { - mConnection.asBinder().unlinkToDeath(this, 0); - } - - @Override - public void binderDied() { - unlinkToDeath(); - runOnUiThread(() -> { - if (mRemoteAccessibilityEmbeddedConnection == this) { - mRemoteAccessibilityEmbeddedConnection = null; - } - }); - } - } } |