Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d72bf49d authored by Ryan Lin's avatar Ryan Lin Committed by Android (Google) Code Review
Browse files

Merge "Add method to request window magnification connection"

parents 9f6ee884 ba834b21
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -227,4 +227,12 @@ oneway interface IStatusBar
     * display.
     */
    void suppressAmbientDisplay(boolean suppress);

    /**
     * Requests {@link WindowMagnification} to set window magnification connection through
     * {@link AccessibilityManager#setWindowMagnificationConnection(IWindowMagnificationConnection)}
     *
     * @param connect {@code true} if needs connection, otherwise set the connection to null.
     */
    void requestWindowMagnificationConnection(boolean connect);
}
+43 −6
Original line number Diff line number Diff line
@@ -28,37 +28,50 @@ import android.os.RemoteException;
import android.provider.Settings;
import android.util.Log;
import android.view.Display;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.IWindowMagnificationConnection;
import android.view.accessibility.IWindowMagnificationConnectionCallback;

import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.R;
import com.android.systemui.SystemUI;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.statusbar.CommandQueue;

import javax.inject.Inject;
import javax.inject.Singleton;

/**
 * Class to handle changes to setting window_magnification value.
 * Class to handle the interaction with
 * {@link com.android.server.accessibility.AccessibilityManagerService}. It invokes
 * {@link AccessibilityManager#setWindowMagnificationConnection(IWindowMagnificationConnection)}
 * when {@code IStatusBar#requestWindowMagnificationConnection(boolean)} is called.
 */
@Singleton
public class WindowMagnification extends SystemUI implements WindowMagnifierCallback {
public class WindowMagnification extends SystemUI implements WindowMagnifierCallback,
        CommandQueue.Callbacks {
    private static final String TAG = "WindowMagnification";
    private static final int CONFIG_MASK =
            ActivityInfo.CONFIG_DENSITY | ActivityInfo.CONFIG_ORIENTATION;

    private WindowMagnificationController mWindowMagnificationController;
    @VisibleForTesting
    protected WindowMagnificationController mWindowMagnificationController;
    private final Handler mHandler;
    //TODO:Set it by the request from AccessibilityManager.
    private WindowMagnificationConnectionImpl mWindowMagnificationConnectionImpl;
    private final AccessibilityManager mAccessibilityManager;
    private final CommandQueue mCommandQueue;

    private WindowMagnificationConnectionImpl mWindowMagnificationConnectionImpl;
    private Configuration mLastConfiguration;

    @Inject
    public WindowMagnification(Context context, @Main Handler mainHandler) {
    public WindowMagnification(Context context, @Main Handler mainHandler,
            CommandQueue commandQueue) {
        super(context);
        mHandler = mainHandler;
        mLastConfiguration = new Configuration(context.getResources().getConfiguration());
        mAccessibilityManager = (AccessibilityManager) mContext.getSystemService(
                Context.ACCESSIBILITY_SERVICE);
        mCommandQueue = commandQueue;
    }

    @Override
@@ -75,6 +88,7 @@ public class WindowMagnification extends SystemUI implements WindowMagnifierCall

    @Override
    public void start() {
        mCommandQueue.addCallback(this);
        mContext.getContentResolver().registerContentObserver(
                Settings.Secure.getUriFor(Settings.Secure.WINDOW_MAGNIFICATION),
                true, new ContentObserver(mHandler) {
@@ -150,6 +164,29 @@ public class WindowMagnification extends SystemUI implements WindowMagnifierCall
        }
    }

    @Override
    public void requestWindowMagnificationConnection(boolean connect) {
        if (connect) {
            setWindowMagnificationConnection();
        } else {
            clearWindowMagnificationConnection();
        }
    }

    private void setWindowMagnificationConnection() {
        if (mWindowMagnificationConnectionImpl == null) {
            mWindowMagnificationConnectionImpl = new WindowMagnificationConnectionImpl(this,
                    mHandler);
        }
        mAccessibilityManager.setWindowMagnificationConnection(
                mWindowMagnificationConnectionImpl);
    }

    private void clearWindowMagnificationConnection() {
        mAccessibilityManager.setWindowMagnificationConnection(null);
        //TODO: destroy controllers.
    }

    private static class WindowMagnificationConnectionImpl extends
            IWindowMagnificationConnection.Stub {

+23 −0
Original line number Diff line number Diff line
@@ -126,6 +126,7 @@ public class CommandQueue extends IStatusBar.Stub implements CallbackController<
    private static final int MSG_HIDE_TOAST                        = 54 << MSG_SHIFT;
    private static final int MSG_TRACING_STATE_CHANGED             = 55 << MSG_SHIFT;
    private static final int MSG_SUPPRESS_AMBIENT_DISPLAY          = 56 << MSG_SHIFT;
    private static final int MSG_REQUEST_WINDOW_MAGNIFICATION_CONNECTION = 57 << MSG_SHIFT;

    public static final int FLAG_EXCLUDE_NONE = 0;
    public static final int FLAG_EXCLUDE_SEARCH_PANEL = 1 << 0;
@@ -338,6 +339,15 @@ public class CommandQueue extends IStatusBar.Stub implements CallbackController<
         * @param enabled
         */
        default void onTracingStateChanged(boolean enabled) { }

        /**
         * Requests {@link com.android.systemui.accessibility.WindowMagnification} to invoke
         * {@code android.view.accessibility.AccessibilityManager#
         * setWindowMagnificationConnection(IWindowMagnificationConnection)}
         *
         * @param connect {@code true} if needs connection, otherwise set the connection to null.
         */
        default void requestWindowMagnificationConnection(boolean connect) { }
    }

    public CommandQueue(Context context) {
@@ -885,6 +895,14 @@ public class CommandQueue extends IStatusBar.Stub implements CallbackController<
        }
    }

    @Override
    public void requestWindowMagnificationConnection(boolean connect) {
        synchronized (mLock) {
            mHandler.obtainMessage(MSG_REQUEST_WINDOW_MAGNIFICATION_CONNECTION, connect)
                    .sendToTarget();
        }
    }

    private void handleShowImeButton(int displayId, IBinder token, int vis, int backDisposition,
            boolean showImeSwitcher, boolean isMultiClientImeEnabled) {
        if (displayId == INVALID_DISPLAY) return;
@@ -1302,6 +1320,11 @@ public class CommandQueue extends IStatusBar.Stub implements CallbackController<
                        callbacks.suppressAmbientDisplay((boolean) msg.obj);
                    }
                    break;
                case MSG_REQUEST_WINDOW_MAGNIFICATION_CONNECTION:
                    for (int i = 0; i < mCallbacks.size(); i++) {
                        mCallbacks.get(i).requestWindowMagnificationConnection((Boolean) msg.obj);
                    }
                    break;
            }
        }
    }
+118 −0
Original line number Diff line number Diff line
/*
 * 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 com.android.systemui.accessibility;

import static org.junit.Assert.assertNotNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.verify;

import android.content.Context;
import android.os.RemoteException;
import android.testing.AndroidTestingRunner;
import android.view.Display;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.IWindowMagnificationConnection;
import android.view.accessibility.IWindowMagnificationConnectionCallback;

import androidx.test.filters.SmallTest;

import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.CommandQueue;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

/**
 * Tests for {@link android.view.accessibility.IWindowMagnificationConnection} retrieved from
 * {@link WindowMagnification}
 */
@SmallTest
@RunWith(AndroidTestingRunner.class)
public class IWindowMagnificationConnectionTest extends SysuiTestCase {

    private static final int TEST_DISPLAY = Display.DEFAULT_DISPLAY;
    @Mock
    private AccessibilityManager mAccessibilityManager;
    @Mock
    private CommandQueue mCommandQueue;
    @Mock
    private IWindowMagnificationConnectionCallback mConnectionCallback;
    @Mock
    private WindowMagnificationController mWindowMagnificationController;
    private IWindowMagnificationConnection mIWindowMagnificationConnection;
    private WindowMagnification mWindowMagnification;

    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);
        getContext().addMockSystemService(Context.ACCESSIBILITY_SERVICE, mAccessibilityManager);
        doAnswer(invocation -> {
            mIWindowMagnificationConnection = invocation.getArgument(0);
            return null;
        }).when(mAccessibilityManager).setWindowMagnificationConnection(
                any(IWindowMagnificationConnection.class));
        mWindowMagnification = new WindowMagnification(getContext(),
                getContext().getMainThreadHandler(), mCommandQueue);
        mWindowMagnification.mWindowMagnificationController = mWindowMagnificationController;
        mWindowMagnification.requestWindowMagnificationConnection(true);
        assertNotNull(mIWindowMagnificationConnection);
        mIWindowMagnificationConnection.setConnectionCallback(mConnectionCallback);
    }

    @Test
    public void enableWindowMagnification() throws RemoteException {
        mIWindowMagnificationConnection.enableWindowMagnification(TEST_DISPLAY, 3.0f, Float.NaN,
                Float.NaN);
        waitForIdleSync();

        verify(mWindowMagnificationController).enableWindowMagnification(3.0f, Float.NaN,
                Float.NaN);
    }

    @Test
    public void disableWindowMagnification_deleteWindowMagnification() throws RemoteException {
        mIWindowMagnificationConnection.enableWindowMagnification(TEST_DISPLAY, 3.0f, Float.NaN,
                Float.NaN);
        waitForIdleSync();

        mIWindowMagnificationConnection.disableWindowMagnification(TEST_DISPLAY);
        waitForIdleSync();

        verify(mWindowMagnificationController).deleteWindowMagnification();
    }

    @Test
    public void setScale() throws RemoteException {
        mIWindowMagnificationConnection.setScale(TEST_DISPLAY, 3.0f);
        waitForIdleSync();

        verify(mWindowMagnificationController).setScale(3.0f);
    }

    @Test
    public void moveWindowMagnifier() throws RemoteException {
        mIWindowMagnificationConnection.moveWindowMagnifier(TEST_DISPLAY, 100f, 200f);
        waitForIdleSync();

        verify(mWindowMagnificationController).moveWindowMagnifier(100f, 200f);
    }
}
+97 −0
Original line number Diff line number Diff line
/*
 * 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 com.android.systemui.accessibility;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.verify;

import android.content.Context;
import android.graphics.Rect;
import android.os.RemoteException;
import android.testing.AndroidTestingRunner;
import android.view.Display;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.IWindowMagnificationConnection;
import android.view.accessibility.IWindowMagnificationConnectionCallback;

import androidx.test.filters.SmallTest;

import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.CommandQueue;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;

@SmallTest
@RunWith(AndroidTestingRunner.class)
public class WindowMagnificationTest extends SysuiTestCase {

    @Mock
    private AccessibilityManager mAccessibilityManager;
    private CommandQueue mCommandQueue;
    private WindowMagnification mWindowMagnification;

    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);
        getContext().addMockSystemService(Context.ACCESSIBILITY_SERVICE, mAccessibilityManager);

        mCommandQueue = new CommandQueue(getContext());
        mWindowMagnification = new WindowMagnification(getContext(),
                getContext().getMainThreadHandler(), mCommandQueue);
        mWindowMagnification.start();
    }

    @Test
    public void requestWindowMagnificationConnection_setWindowMagnificationConnection() {
        mCommandQueue.requestWindowMagnificationConnection(true);
        waitForIdleSync();

        verify(mAccessibilityManager).setWindowMagnificationConnection(any(
                IWindowMagnificationConnection.class));

        mCommandQueue.requestWindowMagnificationConnection(false);
        waitForIdleSync();

        verify(mAccessibilityManager).setWindowMagnificationConnection(null);
    }

    @Test
    public void onWindowMagnifierBoundsChanged() throws RemoteException {
        final IWindowMagnificationConnectionCallback connectionCallback = Mockito.mock(
                IWindowMagnificationConnectionCallback.class);
        final Rect testBounds = new Rect(0, 0, 500, 600);
        doAnswer(invocation -> {
            IWindowMagnificationConnection connection = invocation.getArgument(0);
            connection.setConnectionCallback(connectionCallback);
            return null;
        }).when(mAccessibilityManager).setWindowMagnificationConnection(
                any(IWindowMagnificationConnection.class));
        mCommandQueue.requestWindowMagnificationConnection(true);
        waitForIdleSync();

        mWindowMagnification.onWindowMagnifierBoundsChanged(Display.DEFAULT_DISPLAY, testBounds);

        verify(connectionCallback).onWindowMagnifierBoundsChanged(Display.DEFAULT_DISPLAY,
                testBounds);
    }
}
Loading