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

Commit 2902fa40 authored by Yi Jiang's avatar Yi Jiang Committed by Android (Google) Code Review
Browse files

Merge "Revert "Gets suggested screen rotations from RotationResolverService.""

parents b0049dac 36226d63
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -46,6 +46,7 @@ public abstract class RotationResolverInternal {
     *                 error is captured. {@link RotationResolverCallbackInternal}
     * @param proposedRotation the screen rotation that is proposed by the system.
     * @param currentRotation the current screen rotation.
     * @param packageName the package name of the current activity that is running in foreground.
     * @param timeoutMillis the timeout in millisecond for the query. If the query doesn't get
     *                      fulfilled within this amount of time. It will be discarded and the
     *                      callback will receive a failure result code {@link
@@ -54,7 +55,8 @@ public abstract class RotationResolverInternal {
     */
    public abstract void resolveRotation(@NonNull RotationResolverCallbackInternal callback,
            @Surface.Rotation int proposedRotation, @Surface.Rotation int currentRotation,
            @DurationMillisLong long timeoutMillis, @NonNull CancellationSignal cancellationSignal);
            String packageName, @DurationMillisLong long timeoutMillis,
            @NonNull CancellationSignal cancellationSignal);

    /**
     * Internal interfaces for the rotation resolver callback.
+9 −108
Original line number Diff line number Diff line
@@ -16,34 +16,23 @@

package com.android.server.policy;

import static android.provider.DeviceConfig.NAMESPACE_WINDOW_MANAGER;

import static com.android.server.wm.WindowOrientationListenerProto.ENABLED;
import static com.android.server.wm.WindowOrientationListenerProto.ROTATION;

import android.app.ActivityThread;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.CancellationSignal;
import android.os.Handler;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.provider.DeviceConfig;
import android.rotationresolver.RotationResolverInternal;
import android.util.Slog;
import android.util.proto.ProtoOutputStream;
import android.view.Surface;

import com.android.internal.annotations.VisibleForTesting;
import com.android.server.LocalServices;


import java.io.PrintWriter;
import java.util.List;
import java.util.Set;

/**
 * A special helper class used by the WindowManager
@@ -64,9 +53,6 @@ public abstract class WindowOrientationListener {

    private static final boolean USE_GRAVITY_SENSOR = false;
    private static final int DEFAULT_BATCH_LATENCY = 100000;
    private static final boolean DEFAULT_ROTATION_RESOLVER_ENABLED = false;
    private static final String KEY_ROTATION_RESOLVER_TIMEOUT = "rotation_resolver_timeout_millis";
    private static final long DEFAULT_ROTATION_RESOLVER_TIMEOUT_MILLIS = 700L;

    private Handler mHandler;
    private SensorManager mSensorManager;
@@ -74,13 +60,7 @@ public abstract class WindowOrientationListener {
    private int mRate;
    private String mSensorType;
    private Sensor mSensor;

    @VisibleForTesting
    OrientationJudge mOrientationJudge;

    @VisibleForTesting
    RotationResolverInternal mRotationResolverService;

    private OrientationJudge mOrientationJudge;
    private int mCurrentRotation = -1;
    private final Context mContext;

@@ -267,31 +247,6 @@ public abstract class WindowOrientationListener {
        }
    }

    /**
     * Returns true if the current status of the phone is suitable for using rotation resolver
     * service.
     *
     * To reduce the power consumption of rotation resolver service, rotation query should run less
     * frequently than other low power orientation sensors. This method is used to check whether
     * the current status of the phone is necessary to request a suggested screen rotation from the
     * rotation resolver service. Note that it always returns {@code false} in the base class. It
     * should be overridden in the derived classes.
     */
    public boolean canUseRotationResolver() {
        return false;
    }

    /**
     * Returns true if the rotation resolver is enabled, which means {@link
     * WindowOrientationListener} will ask {@link RotationResolverInternal} for the appropriate
     * screen rotation.
     */
    @VisibleForTesting
    boolean isRotationResolverEnabled() {
        // TODO(b/172857585): read the config from Android Settings.
        return DEFAULT_ROTATION_RESOLVER_ENABLED;
    }

    /**
     * Called when the rotation view of the device has changed.
     *
@@ -1082,30 +1037,6 @@ public abstract class WindowOrientationListener {
        private int mProposedRotation = -1;
        private int mDesiredRotation = -1;
        private boolean mRotationEvaluationScheduled;
        private long mRotationResolverTimeoutMillis;

        OrientationSensorJudge() {
            super();
            setupRotationResolverParameters();
        }

        private void setupRotationResolverParameters() {
            DeviceConfig.addOnPropertiesChangedListener(NAMESPACE_WINDOW_MANAGER,
                    ActivityThread.currentApplication().getMainExecutor(), (properties) -> {
                        final Set<String> keys = properties.getKeyset();
                        if (keys.contains(KEY_ROTATION_RESOLVER_TIMEOUT)) {
                            readRotationResolverParameters();
                        }
                    });
            readRotationResolverParameters();
        }

        private void readRotationResolverParameters() {
            mRotationResolverTimeoutMillis = DeviceConfig.getLong(
                    DeviceConfig.NAMESPACE_WINDOW_MANAGER,
                    KEY_ROTATION_RESOLVER_TIMEOUT,
                    DEFAULT_ROTATION_RESOLVER_TIMEOUT_MILLIS);
        }

        @Override
        public int getProposedRotationLocked() {
@@ -1130,38 +1061,19 @@ public abstract class WindowOrientationListener {

        @Override
        public void onSensorChanged(SensorEvent event) {
            int newRotation;

            int reportedRotation = (int) event.values[0];
            if (reportedRotation < 0 || reportedRotation > 3) {
                return;
            }

            if (isRotationResolverEnabled() && canUseRotationResolver()) {
                if (mRotationResolverService == null) {
                    mRotationResolverService = LocalServices.getService(
                            RotationResolverInternal.class);
                }

                final CancellationSignal cancellationSignal = new CancellationSignal();
                mRotationResolverService.resolveRotation(
                        new RotationResolverInternal.RotationResolverCallbackInternal() {
                            @Override
                            public void onSuccess(int result) {
                                finalizeRotation(result);
            synchronized (mLock) {
                mDesiredRotation = reportedRotation;
                newRotation = evaluateRotationChangeLocked();
            }

                            @Override
                            public void onFailure(int error) {
                                finalizeRotation(reportedRotation);
                            }
                        },
                        reportedRotation,
                        mCurrentRotation,
                        mRotationResolverTimeoutMillis,
                        cancellationSignal);
                getHandler().postDelayed(cancellationSignal::cancel,
                        mRotationResolverTimeoutMillis);
            } else {
                finalizeRotation(reportedRotation);
            if (newRotation >=0) {
                onProposedRotationChanged(newRotation);
            }
        }

@@ -1205,17 +1117,6 @@ public abstract class WindowOrientationListener {
            return -1;
        }

        private void finalizeRotation(int reportedRotation) {
            int newRotation;
            synchronized (mLock) {
                mDesiredRotation = reportedRotation;
                newRotation = evaluateRotationChangeLocked();
            }
            if (newRotation >= 0) {
                onProposedRotationChanged(newRotation);
            }
        }

        private boolean isDesiredRotationAcceptableLocked(long now) {
            if (mTouching) {
                return false;
+2 −3
Original line number Diff line number Diff line
@@ -150,7 +150,7 @@ public class RotationResolverManagerService extends
        @Override
        public void resolveRotation(
                @NonNull RotationResolverCallbackInternal callbackInternal, int proposedRotation,
                int currentRotation, long timeout,
                int currentRotation, String packageName, long timeout,
                @NonNull CancellationSignal cancellationSignalInternal) {
            Objects.requireNonNull(callbackInternal);
            Objects.requireNonNull(cancellationSignalInternal);
@@ -159,8 +159,7 @@ public class RotationResolverManagerService extends
                    final RotationResolverManagerPerUserService service = getServiceForUserLocked(
                            UserHandle.getCallingUserId());
                    service.resolveRotationLocked(callbackInternal, proposedRotation,
                            currentRotation, /* packageName */ "", timeout,
                            cancellationSignalInternal);
                            currentRotation, packageName, timeout, cancellationSignalInternal);
                } else {
                    Slog.w(TAG, "Rotation Resolver service is disabled.");
                    callbackInternal.onFailure(ROTATION_RESULT_FAILURE_CANCELLED);
+0 −15
Original line number Diff line number Diff line
@@ -1499,21 +1499,6 @@ public class DisplayRotation {
            }
        }

        @Override
        public boolean canUseRotationResolver() {
            if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED) return false;

            switch (mCurrentAppOrientation) {
                case ActivityInfo.SCREEN_ORIENTATION_FULL_USER:
                case ActivityInfo.SCREEN_ORIENTATION_USER:
                case ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED:
                case ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE:
                case ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT:
                    return true;
            }
            return false;
        }

        @Override
        public void onProposedRotationChanged(int rotation) {
            ProtoLog.v(WM_DEBUG_ORIENTATION, "onProposedRotationChanged, rotation=%d", rotation);
+0 −148
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 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.policy;


import static com.google.common.truth.Truth.assertThat;

import static org.mockito.Mockito.doReturn;

import android.annotation.DurationMillisLong;
import android.annotation.NonNull;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorManager;
import android.hardware.input.InputSensorInfo;
import android.os.CancellationSignal;
import android.os.Handler;
import android.rotationresolver.RotationResolverInternal;
import android.view.Surface;

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

/**
 * Tests for {@link com.android.server.policy.WindowOrientationListener}
 */
public class WindowOrientationListenerTest {

    @Mock
    private Context mMockContext;
    @Mock
    private Handler mMockHandler;
    @Mock
    private InputSensorInfo mMockInputSensorInfo;
    @Mock
    private SensorManager mMockSensorManager;

    private TestableRotationResolver mFakeRotationResolverInternal;
    private WindowOrientationListener mWindowOrientationListener;
    private int mFinalizedRotation;
    private boolean mRotationResolverEnabled;
    private boolean mCanUseRotationResolver;
    private SensorEvent mFakeSensorEvent;
    private Sensor mFakeSensor;

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
        mRotationResolverEnabled = true;
        mCanUseRotationResolver = true;

        mFakeRotationResolverInternal = new TestableRotationResolver();
        doReturn(mMockSensorManager).when(mMockContext).getSystemService(Context.SENSOR_SERVICE);
        mWindowOrientationListener = new TestableWindowOrientationListener(mMockContext,
                mMockHandler);
        mWindowOrientationListener.mRotationResolverService = mFakeRotationResolverInternal;

        mFakeSensor = new Sensor(mMockInputSensorInfo);
        mFakeSensorEvent = new SensorEvent(mFakeSensor, /* accuracy */ 1, /* timestamp */ 1L,
                new float[]{(float) Surface.ROTATION_90});
    }

    @Test
    public void testOnSensorChanged_rotationResolverDisabled_useSensorResult() {
        mRotationResolverEnabled = false;

        mWindowOrientationListener.mOrientationJudge.onSensorChanged(mFakeSensorEvent);

        assertThat(mFinalizedRotation).isEqualTo(Surface.ROTATION_90);
    }

    @Test
    public void testOnSensorChanged_cannotUseRotationResolver_useSensorResult() {
        mCanUseRotationResolver = false;

        mWindowOrientationListener.mOrientationJudge.onSensorChanged(mFakeSensorEvent);

        assertThat(mFinalizedRotation).isEqualTo(Surface.ROTATION_90);

    }

    @Test
    public void testOnSensorChanged_normalCase() {
        mFakeRotationResolverInternal.mResult = Surface.ROTATION_180;

        mWindowOrientationListener.mOrientationJudge.onSensorChanged(mFakeSensorEvent);

        assertThat(mFinalizedRotation).isEqualTo(Surface.ROTATION_180);
    }

    final class TestableRotationResolver extends RotationResolverInternal {
        @Surface.Rotation
        int mResult;

        @Override
        public boolean isRotationResolverSupported() {
            return true;
        }

        @Override
        public void resolveRotation(@NonNull RotationResolverCallbackInternal callback,
                @Surface.Rotation int proposedRotation, @Surface.Rotation int currentRotation,
                @DurationMillisLong long timeoutMillis,
                @NonNull CancellationSignal cancellationSignal) {
            callback.onSuccess(mResult);
        }
    }

    final class TestableWindowOrientationListener extends WindowOrientationListener {

        TestableWindowOrientationListener(Context context, Handler handler) {
            super(context, handler);
            this.mOrientationJudge = new OrientationSensorJudge();
        }

        @Override
        public void onProposedRotationChanged(int rotation) {
            mFinalizedRotation = rotation;
        }

        @Override
        public boolean canUseRotationResolver() {
            return mCanUseRotationResolver;
        }

        @Override
        public boolean isRotationResolverEnabled() {
            return mRotationResolverEnabled;
        }
    }
}