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

Commit 6e3aba53 authored by Yuxin Hu's avatar Yuxin Hu Committed by Android (Google) Code Review
Browse files

Merge "Add AndroidJUnitTest for developer option switch" into udc-dev

parents e7d695f0 715a7060
Loading
Loading
Loading
Loading
+40 −7
Original line number Diff line number Diff line
@@ -48,6 +48,8 @@ public class GraphicsDriverEnableAngleAsSystemDriverController

    private final DevelopmentSettingsDashboardFragment mFragment;

    private final GraphicsDriverSystemPropertiesWrapper mSystemProperties;

    @VisibleForTesting
    static final String PROPERTY_RO_GFX_ANGLE_SUPPORTED = "ro.gfx.angle.supported";

@@ -57,11 +59,34 @@ public class GraphicsDriverEnableAngleAsSystemDriverController
    @VisibleForTesting
    static final String ANGLE_DRIVER_SUFFIX = "angle";

    @VisibleForTesting
    static class Injector {
        public GraphicsDriverSystemPropertiesWrapper createSystemPropertiesWrapper() {
            return new GraphicsDriverSystemPropertiesWrapper() {
                @Override
                public String get(String key, String def) {
                    return SystemProperties.get(key, def);
                }

                @Override
                public void set(String key, String val) {
                    SystemProperties.set(key, val);
                }
            };
        }
    }

    public GraphicsDriverEnableAngleAsSystemDriverController(
            Context context, DevelopmentSettingsDashboardFragment fragment) {
        this(context, fragment, new Injector());
    }

    @VisibleForTesting
    GraphicsDriverEnableAngleAsSystemDriverController(
            Context context, DevelopmentSettingsDashboardFragment fragment, Injector injector) {
        super(context);
        mFragment = fragment;
        mSystemProperties = injector.createSystemPropertiesWrapper();
    }

    @Override
@@ -76,20 +101,27 @@ public class GraphicsDriverEnableAngleAsSystemDriverController
        // set "persist.graphics.egl" to "" if enableAngleAsSystemDriver is false
        GraphicsEnvironment.getInstance().toggleAngleAsSystemDriver(enableAngleAsSystemDriver);
        // pop up a window asking user to reboot to make the new "persist.graphics.egl" take effect
        showRebootDialog();
        return true;
    }

    @VisibleForTesting
    void showRebootDialog() {
        RebootConfirmationDialogFragment.show(
                mFragment, R.string.reboot_dialog_enable_angle_as_system_driver,
                R.string.cancel, this);
        return true;
    }


    @Override
    public void updateState(Preference preference) {
        // set switch on if "persist.graphics.egl" is "angle" and angle is built in /vendor
        // set switch off otherwise.
        final String currentGlesDriver = SystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL);
        final String currentGlesDriver =
                mSystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL, "");
        final boolean isAngle = TextUtils.equals(ANGLE_DRIVER_SUFFIX, currentGlesDriver);
        final boolean isAngleSupported =
                TextUtils.equals(SystemProperties.get(PROPERTY_RO_GFX_ANGLE_SUPPORTED), "true");
        final boolean isAngleSupported = TextUtils
                .equals(mSystemProperties.get(PROPERTY_RO_GFX_ANGLE_SUPPORTED, ""), "true");
        ((SwitchPreference) mPreference).setChecked(isAngle && isAngleSupported);
        ((SwitchPreference) mPreference).setEnabled(isAngleSupported);
    }
@@ -98,8 +130,8 @@ public class GraphicsDriverEnableAngleAsSystemDriverController
    protected void onDeveloperOptionsSwitchEnabled() {
        // only enable the switch if ro.gfx.angle.supported is true
        // we use ro.gfx.angle.supported to indicate if ANGLE libs are installed under /vendor
        final boolean isAngleSupported =
                TextUtils.equals(SystemProperties.get(PROPERTY_RO_GFX_ANGLE_SUPPORTED), "true");
        final boolean isAngleSupported = TextUtils
                .equals(mSystemProperties.get(PROPERTY_RO_GFX_ANGLE_SUPPORTED, ""), "true");
        ((SwitchPreference) mPreference).setEnabled(isAngleSupported);
    }

@@ -116,7 +148,8 @@ public class GraphicsDriverEnableAngleAsSystemDriverController
    @Override
    public void onRebootCancelled() {
        // if user presses button "Cancel", do not reboot the device, and toggles switch back
        final String currentGlesDriver = SystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL);
        final String currentGlesDriver =
                mSystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL, "");
        if (TextUtils.equals(ANGLE_DRIVER_SUFFIX, currentGlesDriver)) {
            // if persist.graphics.egl = "angle", set the property value back to ""
            GraphicsEnvironment.getInstance().toggleAngleAsSystemDriver(false);
+44 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 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.settings.development.graphicsdriver;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.SystemProperties;
/**
 * Wrapper interface to access {@link SystemProperties}.
 *
 * @hide
 */
interface GraphicsDriverSystemPropertiesWrapper {
    /**
     * Get the String value for the given {@code key}.
     *
     * @param key the key to lookup
     * @param def the default value in case the property is not set or empty
     * @return if the {@code key} isn't found, return {@code def} if it isn't null, or an empty
     * string otherwise
     */
    @NonNull
    String get(@NonNull String key, @Nullable String def);
    /**
     * Set the value for the given {@code key} to {@code val}.
     *
     * @throws IllegalArgumentException if the {@code val} exceeds 91 characters
     * @throws RuntimeException if the property cannot be set, for example, if it was blocked by
     * SELinux. libc will log the underlying reason.
     */
    void set(@NonNull String key, @Nullable String val);
}
+9 −13
Original line number Diff line number Diff line
@@ -81,9 +81,10 @@ public class GraphicsDriverEnableAngleAsSystemDriverControllerTest {
        // since GraphicsEnvironment is mocked in Robolectric test environment,
        // we will override the system property persist.graphics.egl as if it is changed by
        // mGraphicsEnvironment.toggleAngleAsSystemDriver(true).
        // TODO: b/270994705 yuxinhu:
        // add test coverage to test mGraphicsEnvironment.toggleAngleAsSystemDriver()
        // works properly on Android devices / emulators.

        // for test that actually verifies mGraphicsEnvironment.toggleAngleAsSystemDriver(true)
        // on a device/emulator, please refer to
        // GraphicsDriverEnableAngleAsSystemDriverControllerJUnitTest
        ShadowSystemProperties.override(PROPERTY_PERSISTENT_GRAPHICS_EGL, ANGLE_DRIVER_SUFFIX);
        mController.onPreferenceChange(mPreference, true);
        final String systemEGLDriver = SystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL);
@@ -97,9 +98,10 @@ public class GraphicsDriverEnableAngleAsSystemDriverControllerTest {
        // since GraphicsEnvironment is mocked in Robolectric test environment,
        // we will override the system property persist.graphics.egl as if it is changed by
        // mGraphicsEnvironment.toggleAngleAsSystemDriver(false).
        // TODO: b/270994705 yuxinhu:
        // add test coverage to test mGraphicsEnvironment.toggleAngleAsSystemDriver()
        // works properly on Android devices / emulators.

        // for test that actually verifies mGraphicsEnvironment.toggleAngleAsSystemDriver(true)
        // on a device/emulator, please refer to
        // GraphicsDriverEnableAngleAsSystemDriverControllerJUnitTest
        ShadowSystemProperties.override(PROPERTY_PERSISTENT_GRAPHICS_EGL, "");
        mController.onPreferenceChange(mPreference, false);
        final String systemEGLDriver = SystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL);
@@ -124,20 +126,14 @@ public class GraphicsDriverEnableAngleAsSystemDriverControllerTest {
    @Test
    public void updateState_angleSupported_angleUsed_preferenceShouldBeChecked() {
        ShadowSystemProperties.override(PROPERTY_RO_GFX_ANGLE_SUPPORTED, "true");
        // TODO: b/270994705 yuxinhu:
        // add test coverage to test mGraphicsEnvironment.toggleAngleAsSystemDriver()
        // works properly on Android devices / emulators.
        ShadowSystemProperties.override(PROPERTY_PERSISTENT_GRAPHICS_EGL, ANGLE_DRIVER_SUFFIX);
        mController.updateState(mPreference);
        verify(mPreference).setChecked(true); //false
        verify(mPreference).setChecked(true);
    }

    @Test
    public void updateState_angleSupported_angleNotUsed_preferenceShouldNotBeChecked() {
        ShadowSystemProperties.override(PROPERTY_RO_GFX_ANGLE_SUPPORTED, "true");
        // TODO: b/270994705 yuxinhu:
        // add test coverage to test mGraphicsEnvironment.toggleAngleAsSystemDriver(false)
        // works properly on Android devices / emulators.
        ShadowSystemProperties.override(PROPERTY_PERSISTENT_GRAPHICS_EGL, "");
        mController.updateState(mPreference);
        verify(mPreference).setChecked(false);
+325 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 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.settings.development.graphicsdriver;

import static com.android.settings.development.graphicsdriver.GraphicsDriverEnableAngleAsSystemDriverController.ANGLE_DRIVER_SUFFIX;
import static com.android.settings.development.graphicsdriver.GraphicsDriverEnableAngleAsSystemDriverController.Injector;
import static com.android.settings.development.graphicsdriver.GraphicsDriverEnableAngleAsSystemDriverController.PROPERTY_PERSISTENT_GRAPHICS_EGL;
import static com.android.settings.development.graphicsdriver.GraphicsDriverEnableAngleAsSystemDriverController.PROPERTY_RO_GFX_ANGLE_SUPPORTED;

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

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.when;

import android.content.Context;
import android.os.Looper;
import android.os.SystemProperties;

import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceScreen;
import androidx.preference.SwitchPreference;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;

import com.android.settings.development.DevelopmentSettingsDashboardFragment;

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

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

@RunWith(AndroidJUnit4.class)
public class GraphicsDriverEnableAngleAsSystemDriverControllerJUnitTest {
    private Context mContext;
    private SwitchPreference mPreference;

    private GraphicsDriverEnableAngleAsSystemDriverController mController;

    @Mock
    private DevelopmentSettingsDashboardFragment mFragment;

    @Mock
    private GraphicsDriverSystemPropertiesWrapper mSystemPropertiesMock;

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
        if (Looper.myLooper() == null) {
            Looper.prepare();
        }

        mContext = ApplicationProvider.getApplicationContext();

        // Construct a GraphicsDriverEnableAngleAsSystemDriverController with two Overrides:
        // 1) Override the mSystemProperties with mSystemPropertiesMock,
        // so we can force the SystemProperties with values we need to run tests.
        // 2) Override the showRebootDialog() to do nothing.
        // We do not need to pop up the reboot dialog in the test.
        mController = new GraphicsDriverEnableAngleAsSystemDriverController(
            mContext, mFragment, new Injector(){
                @Override
                public GraphicsDriverSystemPropertiesWrapper createSystemPropertiesWrapper() {
                    return mSystemPropertiesMock;
                }
            }) {
                @Override
                void showRebootDialog() {
                    // do nothing
                }
        };

        final PreferenceManager preferenceManager = new PreferenceManager(mContext);
        final PreferenceScreen screen = preferenceManager.createPreferenceScreen(mContext);
        mPreference = new SwitchPreference(mContext);
        mPreference.setKey(mController.getPreferenceKey());
        screen.addPreference(mPreference);
        mController.displayPreference(screen);
    }

    @Test
    public void onPreferenceChange_switchOn_shouldEnableAngleAsSystemDriver() {
        // Add a callback when SystemProperty changes.
        // This allows the thread to wait until
        // GpuService::toggleAngleAsSystemDriver() updates the persist.graphics.egl.
        final CountDownLatch countDownLatch = new CountDownLatch(1);
        Runnable countDown = new Runnable() {
            @Override
            public void run() {
                countDownLatch.countDown();
            }
        };
        SystemProperties.addChangeCallback(countDown);

        // Test onPreferenceChange(true) updates the persist.graphics.egl to "angle"
        mController.onPreferenceChange(mPreference, true);
        try {
            countDownLatch.await(100, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            Assert.fail(e.getMessage());
        }
        final String systemEGLDriver = SystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL);
        assertThat(systemEGLDriver).isEqualTo(ANGLE_DRIVER_SUFFIX);

        // Done with the test, remove the callback
        SystemProperties.removeChangeCallback(countDown);
    }

    @Test
    public void onPreferenceChange_switchOff_shouldDisableAngleAsSystemDriver() {
        // Add a callback when SystemProperty changes.
        // This allows the thread to wait until
        // GpuService::toggleAngleAsSystemDriver() updates the persist.graphics.egl.
        final CountDownLatch countDownLatch = new CountDownLatch(1);
        Runnable countDown = new Runnable() {
            @Override
            public void run() {
                countDownLatch.countDown();
            }
        };
        SystemProperties.addChangeCallback(countDown);

        // Test onPreferenceChange(false) updates the persist.graphics.egl to ""
        mController.onPreferenceChange(mPreference, false);
        try {
            countDownLatch.await(100, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            Assert.fail(e.getMessage());
        }
        final String systemEGLDriver = SystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL);
        assertThat(systemEGLDriver).isEqualTo("");

        // Done with the test, remove the callback
        SystemProperties.removeChangeCallback(countDown);
    }

    @Test
    public void updateState_angleNotSupported_PreferenceShouldDisabled() {
        when(mSystemPropertiesMock.get(eq(PROPERTY_RO_GFX_ANGLE_SUPPORTED), any())).thenReturn("");
        mController.updateState(mPreference);
        assertThat(mPreference.isEnabled()).isFalse();
    }

    @Test
    public void updateState_angleNotSupported_PreferenceShouldNotBeChecked() {
        when(mSystemPropertiesMock.get(eq(PROPERTY_RO_GFX_ANGLE_SUPPORTED), any()))
                .thenReturn("");
        mController.updateState(mPreference);
        assertThat(mPreference.isChecked()).isFalse();
    }

    @Test
    public void updateState_angleSupported_PreferenceShouldEnabled() {
        when(mSystemPropertiesMock.get(eq(PROPERTY_RO_GFX_ANGLE_SUPPORTED), any()))
                .thenReturn("true");
        mController.updateState(mPreference);
        assertThat(mPreference.isEnabled()).isTrue();
    }

    @Test
    public void updateState_angleSupported_angleIsSystemGLESDriver_PreferenceShouldBeChecked() {
        when(mSystemPropertiesMock.get(eq(PROPERTY_RO_GFX_ANGLE_SUPPORTED), any()))
                .thenReturn("true");
        when(mSystemPropertiesMock.get(eq(PROPERTY_PERSISTENT_GRAPHICS_EGL), any()))
                .thenReturn(ANGLE_DRIVER_SUFFIX);
        mController.updateState(mPreference);
        assertThat(mPreference.isChecked()).isTrue();
    }

    @Test
    public void
            updateState_angleSupported_angleIsNotSystemGLESDriver_PreferenceShouldNotBeChecked() {
        when(mSystemPropertiesMock.get(eq(PROPERTY_RO_GFX_ANGLE_SUPPORTED), any()))
                .thenReturn("true");
        when(mSystemPropertiesMock.get(eq(PROPERTY_PERSISTENT_GRAPHICS_EGL), any()))
                .thenReturn("");
        mController.updateState(mPreference);
        assertThat(mPreference.isChecked()).isFalse();
    }

    @Test
    public void onDeveloperOptionSwitchEnabled_angleSupported_PreferenceShouldEnabled() {
        when(mSystemPropertiesMock.get(eq(PROPERTY_RO_GFX_ANGLE_SUPPORTED), any()))
                .thenReturn("true");
        mController.onDeveloperOptionsSwitchEnabled();
        assertThat(mPreference.isEnabled()).isTrue();
    }

    @Test
    public void onDeveloperOptionSwitchEnabled_angleNotSupported_PrefenceShouldDisabled() {
        when(mSystemPropertiesMock.get(eq(PROPERTY_RO_GFX_ANGLE_SUPPORTED), any()))
                .thenReturn("false");
        mController.onDeveloperOptionsSwitchEnabled();
        assertThat(mPreference.isEnabled()).isFalse();
    }

    @Test
    public void onDeveloperOptionSwitchDisabled_angleIsNotSystemGLESDriver() {
        // Add a callback when SystemProperty changes.
        // This allows the thread to wait until
        // GpuService::toggleAngleAsSystemDriver() updates the persist.graphics.egl.
        final CountDownLatch countDownLatch = new CountDownLatch(1);
        Runnable countDown = new Runnable() {
            @Override
            public void run() {
                countDownLatch.countDown();
            }
        };
        SystemProperties.addChangeCallback(countDown);

        // Test that onDeveloperOptionSwitchDisabled,
        // persist.graphics.egl updates to ""
        mController.onDeveloperOptionsSwitchDisabled();
        try {
            countDownLatch.await(100, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            Assert.fail(e.getMessage());
        }
        final String systemEGLDriver = SystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL);
        assertThat(systemEGLDriver).isEqualTo("");

        // Done with the test, remove the callback
        SystemProperties.removeChangeCallback(countDown);
    }

    @Test
    public void onDeveloperOptionSwitchDisabled_PreferenceShouldNotBeChecked() {
        mController.onDeveloperOptionsSwitchDisabled();
        assertThat(mPreference.isChecked()).isFalse();
    }

    @Test
    public void onDeveloperOptionSwitchDisabled_PreferenceShouldDisabled() {
        mController.onDeveloperOptionsSwitchDisabled();
        assertThat(mPreference.isEnabled()).isFalse();
    }

    @Test
    public void onRebootCancelled_ToggleSwitchFromOnToOff() {
        // Add a callback when SystemProperty changes.
        // This allows the thread to wait until
        // GpuService::toggleAngleAsSystemDriver() updates the persist.graphics.egl.
        final CountDownLatch countDownLatch = new CountDownLatch(1);
        Runnable countDown = new Runnable() {
            @Override
            public void run() {
                countDownLatch.countDown();
            }
        };
        SystemProperties.addChangeCallback(countDown);

        // Test that if the current persist.graphics.egl is "angle",
        // when reboot is cancelled, persist.graphics.egl is changed back to "",
        // and switch is set to unchecked.
        when(mSystemPropertiesMock.get(eq(PROPERTY_PERSISTENT_GRAPHICS_EGL), any()))
                .thenReturn(ANGLE_DRIVER_SUFFIX);
        mController.onRebootCancelled();
        try {
            countDownLatch.await(100, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            Assert.fail(e.getMessage());
        }

        final String systemEGLDriver = SystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL);
        assertThat(systemEGLDriver).isEqualTo("");
        assertThat(mPreference.isChecked()).isFalse();

        // Done with the test, remove the callback.
        SystemProperties.removeChangeCallback(countDown);
    }

    @Test
    public void onRebootCancelled_ToggleSwitchFromOffToOn() {
        // Add a callback when SystemProperty changes.
        // This allows the thread to wait until
        // GpuService::toggleAngleAsSystemDriver() updates the persist.graphics.egl.
        final CountDownLatch countDownLatch = new CountDownLatch(1);
        Runnable countDown = new Runnable() {
            @Override
            public void run() {
                countDownLatch.countDown();
            }
        };
        SystemProperties.addChangeCallback(countDown);

        // Test that if the current persist.graphics.egl is "",
        // when reboot is cancelled, persist.graphics.egl is changed back to "angle",
        // and switch is set to checked.
        when(mSystemPropertiesMock.get(eq(PROPERTY_PERSISTENT_GRAPHICS_EGL), any()))
                .thenReturn("");
        mController.onRebootCancelled();
        try {
            countDownLatch.await(100, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            Assert.fail(e.getMessage());
        }

        final String systemEGLDriver = SystemProperties.get(PROPERTY_PERSISTENT_GRAPHICS_EGL);
        assertThat(systemEGLDriver).isEqualTo(ANGLE_DRIVER_SUFFIX);
        assertThat(mPreference.isChecked()).isTrue();

        // Done with the test, remove the callback.
        SystemProperties.removeChangeCallback(countDown);
    }

}