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

Commit 10ff699b authored by Pawan Wagh's avatar Pawan Wagh
Browse files

Integration tests for 16kb dev option

Adding tests to verify end to end functionality for dev options.
This test verifies
- /data reformatting to ext4
- switching to 16kb kernel
- switching back to 4kb kernel
- Persistent notifications in page-agnostic mode
- Disabling developer option in page-agnostic mode

Test: m Enable16KbTest && atest -c Enable16KbTest
Bug: 341995374
Change-Id: Ieaa149831b5205a15b259982f0349dc94d4fae92
parent cfb1ffb5
Loading
Loading
Loading
Loading
+62 −0
Original line number Diff line number Diff line
// Copyright (C) 2024 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 {
    default_applicable_licenses: ["packages_apps_Settings_license"],
    default_team: "trendy_team_android_kernel",
}

android_test_helper_app {
    name: "test_16kb_app",
    srcs: ["test_16kb_app/src/**/*.java"],
    manifest: "test_16kb_app/test_16kb_app.xml",
    static_libs: [
        "androidx.test.ext.junit",
        "androidx.test.rules",
        "androidx.test.uiautomator_uiautomator",
        "platform-test-annotations",
        "settings-helper",
        "sysui-helper",
        "truth",
        "flag-junit",
    ],
    platform_apis: true,
    certificate: "platform",
    test_suites: ["general-tests"],
    libs: [
        "android.test.runner",
        "android.test.base",
    ],
}

java_test_host {
    name: "Enable16KbTest",
    // Include all test java files
    srcs: ["src/**/*.java"],
    static_libs: [
        "junit",
        "platform-test-annotations",
        "truth",
    ],
    libs: [
        "tradefed",
        "compatibility-host-util",
        "compatibility-tradefed",
    ],
    data: [
        ":test_16kb_app",
    ],
    test_suites: ["general-tests"],
    test_config: "AndroidTest.xml",
}
+45 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!--
  ~ Copyright (C) 2024 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.
  -->

<configuration description="Runs 16K developer option test.">
    <option name="test-suite-tag" value="apct"/>

    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
        <option name="cleanup-apks" value="true" />
        <option name="test-file-name" value="test_16kb_app.apk" />
    </target_preparer>

    <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer">
        <option name="force-root" value="false" />
    </target_preparer>

    <test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
        <option name="jar" value="Enable16KbTest.jar" />
    </test>

    <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
        <!-- Unlock screen -->
        <option name="run-command" value="input keyevent KEYCODE_WAKEUP" />
        <!-- Dismiss keyguard, in case it's set as "Swipe to unlock" -->
        <option name="run-command" value="wm dismiss-keyguard" />
        <!-- Collapse notifications -->
        <option name="run-command" value="cmd statusbar collapse" />
        <!-- dismiss all system dialogs before launch test -->
        <option name="run-command" value="am broadcast -a android.intent.action.CLOSE_SYSTEM_DIALOGS" />
    </target_preparer>

</configuration>
+122 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 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.test;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;

import android.platform.test.annotations.AppModeFull;

import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
import com.android.tradefed.testtype.junit4.DeviceTestRunOptions;
import com.android.tradefed.util.RunUtil;

import org.junit.Test;
import org.junit.runner.RunWith;

import java.io.BufferedReader;
import java.io.StringReader;

@RunWith(DeviceJUnit4ClassRunner.class)
public class Enable16KbTest extends BaseHostJUnit4Test {
    private static final String TEST_APP_NAME = "test_16kb_app.apk";

    private static final String APP_PACKAGE = "com.android.settings.development.test";

    private static final String TEST_NAME = "Enable16KbDeviceTest";

    private static final String SWITCH_TO_EXT4 = "enable16k_switchToExt4";

    private static final String SWITCH_TO_16KB = "enable16k_switchTo16Kb";

    private static final String SWITCH_TO_4KB = "enable16k_switchTo4Kb";
    private static final String DISABLE_DEV_OPTION = "enable16k_disableDeveloperOption";

    @Test
    @AppModeFull
    public void enable16KbToggle() throws Exception {
        assertTrue(isPackageInstalled(APP_PACKAGE));

        // Check if developer option is enabled otherwise exit
        getDevice().enableAdbRoot();
        String result = getDevice().getProperty("ro.product.build.16k_page.enabled");
        assumeTrue("true".equals(result));

        // This test can be run on OEM unlocked device only as unlocking bootloader requires
        // manual intervention.
        result = getDevice().getProperty("ro.boot.flash.locked");
        assumeTrue("0".equals(result));

        getDevice().executeShellCommand("am start -a com.android.setupwizard.FOUR_CORNER_EXIT");

        // Enables developer option and switch to ext4
        runTestAndWait(SWITCH_TO_EXT4);

        getDevice().enableAdbRoot();
        getDevice().executeShellCommand("am start -a com.android.setupwizard.FOUR_CORNER_EXIT");
        assertTrue(verifyExt4());

        // Device will wiped. need to install test package again.
        installTestApp();

        // Enable developer option and switch to 16kb kernel and Check page size
        runTestAndWait(SWITCH_TO_16KB);
        result = getDevice().executeShellCommand("getconf PAGE_SIZE");
        assertEquals("16384", result.strip());

        // switch back to 4kb kernel and check page size
        runTestAndWait(SWITCH_TO_4KB);
        result = getDevice().executeShellCommand("getconf PAGE_SIZE");
        assertEquals("4096", result.strip());

        // Verify that developer options can't be turned off
        runDeviceTests(APP_PACKAGE, APP_PACKAGE + "." + TEST_NAME, DISABLE_DEV_OPTION);
    }

    private void installTestApp() throws Exception {
        DeviceTestRunOptions options = new DeviceTestRunOptions(null /* unused */);
        options.setApkFileName(TEST_APP_NAME);
        options.setInstallArgs("-r");
        installPackage(options);
        assertTrue(isPackageInstalled(APP_PACKAGE));
    }

    private void runTestAndWait(String testMethodName) throws Exception {
        runDeviceTests(APP_PACKAGE, APP_PACKAGE + "." + TEST_NAME, testMethodName);
        // Device is either formatting or applying update. It usually takes 3 minutes to boot.
        RunUtil.getDefault().sleep(180000);
        // Wait for 2 mins device to be online againg
        getDevice().waitForDeviceOnline(120000);
    }

    private boolean verifyExt4() throws Exception {
        String result = getDevice().executeShellCommand("cat /proc/mounts");
        BufferedReader br = new BufferedReader(new StringReader(result));
        String line;
        while ((line = br.readLine()) != null) {
            final String[] fields = line.split(" ");
            final String partition = fields[1];
            final String fsType = fields[2];
            if (partition.equals("/data") && fsType.equals("ext4")) {
                return true;
            }
        }
        return false;
    }
}
+170 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 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.test;

import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;

import static org.junit.Assert.assertTrue;

import android.content.Context;
import android.os.RemoteException;
import android.provider.Settings;
import android.system.helpers.SettingsHelper;

import androidx.test.runner.AndroidJUnit4;
import androidx.test.uiautomator.By;
import androidx.test.uiautomator.BySelector;
import androidx.test.uiautomator.Direction;
import androidx.test.uiautomator.UiDevice;
import androidx.test.uiautomator.UiObject2;
import androidx.test.uiautomator.Until;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

@RunWith(AndroidJUnit4.class)
public class Enable16KbDeviceTest {
    private static final long TIMEOUT = 2000;

    private static final String ENABLE_16K_TOGGLE = "Boot with 16KB page size";
    private static final String BUILD_NUMBER = "Build number";
    private static final String USE_DEVELOPER_OPTIONS = "Use developer options";
    private static final String EXT4_CONFIRMATION = "Erase all data";
    private static final String EXT4_TITLE = "Reformat device to ext4? (required for 16KB mode)";
    private static final String TOGGLE_16K_TITLE = "Switch from 4KB mode to 16KB mode";
    private static final String TOGGLE_4K_TITLE = "Switch from 16KB mode to 4KB mode";
    private static final String ANDROID_WIDGET_SCROLLVIEW = "android.widget.ScrollView";
    private static final String OKAY = "OK";
    private static final String NOTIFICATION_TITLE_4K = "Using 4KB page-agnostic mode";
    private static final String NOTIFICATION_TITLE_16K = "Using 16KB page-agnostic mode";

    private Context mContext;
    private UiDevice mDevice;
    private SettingsHelper mHelper;

    @Before
    public void setUp() throws Exception {
        mContext = getInstrumentation().getTargetContext();
        mDevice = UiDevice.getInstance(getInstrumentation());
        mHelper = SettingsHelper.getInstance();
        try {
            mDevice.setOrientationNatural();
        } catch (RemoteException e) {
            throw new RuntimeException("failed to freeze device orientation", e);
        }

        mDevice.executeShellCommand("input keyevent KEYCODE_WAKEUP");
        mDevice.executeShellCommand("wm dismiss-keyguard");
    }

    private void unlockDeveloperOptions() throws Exception {
        SettingsHelper.launchSettingsPage(mContext, Settings.ACTION_DEVICE_INFO_SETTINGS);
        // Click 7 times on build number to unlock the dev options
        for (int i = 0; i < 7; i++) {
            mHelper.clickSetting(BUILD_NUMBER);
        }
    }

    @Test
    public void enable16k_switchToExt4() throws Exception {
        unlockDeveloperOptions();
        SettingsHelper.launchSettingsPage(
                mContext, Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS);
        clickOnObject(By.text(ENABLE_16K_TOGGLE));

        // Verify that ext4 toggle is visible
        verifyTextOnScreen(EXT4_TITLE);

        mDevice.wait(Until.findObject(By.text(EXT4_CONFIRMATION)), TIMEOUT).click();
    }

    @Test
    public void enable16k_switchTo16Kb() throws Exception {
        // Device will be in 4kb mode
        openPersistentNotification(NOTIFICATION_TITLE_4K);
        unlockDeveloperOptions();
        SettingsHelper.launchSettingsPage(
                mContext, Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS);

        clickOnObject(By.text(ENABLE_16K_TOGGLE));
        // Verify that text is displayed to switch to 16kb
        verifyTextOnScreen(TOGGLE_16K_TITLE);

        mDevice.wait(Until.findObject(By.text(OKAY)), TIMEOUT).click();
    }

    @Test
    public void enable16k_switchTo4Kb() throws Exception {
        // Device will be in 16kb mode
        openPersistentNotification(NOTIFICATION_TITLE_16K);
        SettingsHelper.launchSettingsPage(
                mContext, Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS);

        clickOnObject(By.text(ENABLE_16K_TOGGLE));
        //  Verify that text is displayed to switch to 4kb
        verifyTextOnScreen(TOGGLE_4K_TITLE);

        mDevice.wait(Until.findObject(By.text(OKAY)), TIMEOUT).click();
    }

    private void clickOnObject(BySelector target) {
        mDevice.waitForWindowUpdate(null, TIMEOUT);
        UiObject2 scrollView =
                mDevice.wait(
                        Until.findObject(By.scrollable(true).clazz(ANDROID_WIDGET_SCROLLVIEW)),
                        TIMEOUT);
        UiObject2 targetObject = scrollTo(scrollView, target, Direction.DOWN);
        assertTrue(targetObject != null);
        targetObject.click();
    }

    private UiObject2 scrollTo(UiObject2 scrollable, BySelector target, Direction direction) {
        while (!mDevice.hasObject(target) && scrollable.scroll(direction, 1.0f)) {
            // continue
        }
        if (!mDevice.hasObject(target)) {
            scrollable.scroll(direction, 1.0f);
        }
        return mDevice.findObject(target);
    }

    private void verifyTextOnScreen(String displayedText) {
        UiObject2 targetObject = mDevice.wait(Until.findObject(By.text(displayedText)), TIMEOUT);
        assertTrue(targetObject != null);
    }

    private void openPersistentNotification(String title) {
        mDevice.openNotification();
        verifyTextOnScreen(title);
        mDevice.wait(Until.findObject(By.text(title)), TIMEOUT).click();
        mDevice.waitForWindowUpdate(null, TIMEOUT);
        verifyTextOnScreen(title);
        mDevice.wait(Until.findObject(By.text(OKAY)), TIMEOUT).click();
        mDevice.waitForWindowUpdate(null, TIMEOUT);
    }

    @Test
    public void enable16k_disableDeveloperOption() throws Exception {
        // Device will be in 4KB mode when this test will be run
        SettingsHelper.launchSettingsPage(
                mContext, Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS);
        mDevice.wait(Until.findObject(By.text(USE_DEVELOPER_OPTIONS)), TIMEOUT).click();
        verifyTextOnScreen(NOTIFICATION_TITLE_4K);
        mDevice.wait(Until.findObject(By.text(OKAY)), TIMEOUT).click();
    }
}
+27 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!--
  ~ Copyright (C) 2024 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.
  -->

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.android.settings.development.test"
          android:sharedUserId="android.uid.systemui">
    <application>
        <uses-library android:name="android.test.runner"/>
    </application>
    <instrumentation
        android:name="androidx.test.runner.AndroidJUnitRunner"
        android:targetPackage="com.android.settings.development.test"/>
</manifest>
 No newline at end of file