Loading perf-tests/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ android_test { static_libs: [ "androidx.legacy_legacy-support-v4", "androidx.test.rules", "androidx.test.espresso.core", "mockito-target", "ub-janktesthelper", Loading res/values/styles.xml +6 −0 Original line number Diff line number Diff line Loading @@ -91,8 +91,14 @@ <item name="buttonBarNegativeButtonStyle">@style/DialogTextButton</item> </style> <style name="MaterialAlertDialogStyle" parent="@style/MaterialAlertDialog.MaterialComponents"> <item name="backgroundInsetTop">12dp</item> <item name="backgroundInsetBottom">12dp</item> </style> <style name="MaterialAlertDialogTheme" parent="@style/ThemeOverlay.MaterialComponents.MaterialAlertDialog.Centered"> <item name="android:dialogCornerRadius">@dimen/grid_item_radius</item> <item name="alertDialogStyle">@style/MaterialAlertDialogStyle</item> <item name="buttonBarPositiveButtonStyle">@style/DialogTextButton</item> <item name="buttonBarNegativeButtonStyle">@style/DialogTextButton</item> <item name="materialAlertDialogTitleTextStyle">@style/MaterialAlertDialogTitleStyle</item> Loading src/com/android/documentsui/CreateDirectoryFragment.java +0 −1 Original line number Diff line number Diff line Loading @@ -68,7 +68,6 @@ public class CreateDirectoryFragment extends DialogFragment { @Override public Dialog onCreateDialog(Bundle savedInstanceState) { final Context context = getActivity(); final ContentResolver resolver = context.getContentResolver(); final MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(context); final LayoutInflater dialogInflater = LayoutInflater.from(builder.getContext()); Loading tests/common/com/android/documentsui/DialogFragmentTest.java 0 → 100644 +320 −0 Original line number Diff line number Diff line /* * Copyright (C) 2019 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.documentsui; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import android.app.Activity; import android.app.Instrumentation; import android.app.UiAutomation; import android.content.Intent; import android.content.pm.ActivityInfo; import android.graphics.Paint; import android.os.Build; import android.os.ParcelFileDescriptor; import androidx.fragment.app.FragmentManager; import androidx.test.filters.MediumTest; import androidx.test.platform.app.InstrumentationRegistry; import androidx.test.rule.ActivityTestRule; import androidx.test.runner.AndroidJUnit4; import com.android.documentsui.files.FilesActivity; import com.google.android.material.textfield.TextInputEditText; import org.junit.After; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import java.io.FileInputStream; import java.io.IOException; @MediumTest @RunWith(AndroidJUnit4.class) public class DialogFragmentTest { private static final String CREATE_FRAGEMENT_TAG = "create_directory"; CreateDirectoryFragment mCreateDirectoryFragment; FragmentManager mFragmentManager; ScreenDensitySession mScreenDensitySession; Intent mFileActivityIntent; @Rule public ActivityTestRule<FilesActivity> mActivityTestRule = new ActivityTestRule<>( FilesActivity.class); @Before public void setup() { mFileActivityIntent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE); mFragmentManager = mActivityTestRule.getActivity().getSupportFragmentManager(); mScreenDensitySession = new ScreenDensitySession(); } @After public void tearDown() { mScreenDensitySession.close(); mCreateDirectoryFragment = null; } @Test public void testCreateDialogShows() throws Throwable { mActivityTestRule.runOnUiThread(() -> CreateDirectoryFragment.show(mFragmentManager)); InstrumentationRegistry.getInstrumentation().waitForIdleSync(); mCreateDirectoryFragment = (CreateDirectoryFragment) mFragmentManager.findFragmentByTag(CREATE_FRAGEMENT_TAG); assertNotNull("Dialog was null", mCreateDirectoryFragment.getDialog()); assertTrue("Dialog was not being shown", mCreateDirectoryFragment.getDialog().isShowing()); } @Test public void testCreateDialogShowsDismiss() throws Throwable { mActivityTestRule.runOnUiThread(() -> CreateDirectoryFragment.show(mFragmentManager)); InstrumentationRegistry.getInstrumentation().waitForIdleSync(); mCreateDirectoryFragment = (CreateDirectoryFragment) mFragmentManager.findFragmentByTag(CREATE_FRAGEMENT_TAG); assertNotNull("Dialog was null", mCreateDirectoryFragment.getDialog()); assertTrue("Dialog was not being shown", mCreateDirectoryFragment.getDialog().isShowing()); mActivityTestRule.runOnUiThread(() -> mCreateDirectoryFragment.dismiss()); InstrumentationRegistry.getInstrumentation().waitForIdleSync(); assertNull("Dialog should be null after dismiss()", mCreateDirectoryFragment.getDialog()); } @Test public void testCreateDialogShows_textInputEditText_shouldNotTruncateOnPortrait() throws Throwable { mActivityTestRule.runOnUiThread(() -> CreateDirectoryFragment.show(mFragmentManager)); InstrumentationRegistry.getInstrumentation().waitForIdleSync(); mCreateDirectoryFragment = (CreateDirectoryFragment) mFragmentManager.findFragmentByTag(CREATE_FRAGEMENT_TAG); final TextInputEditText inputView = mCreateDirectoryFragment.getDialog().findViewById(android.R.id.text1); assertTrue(inputView.getHeight() > getInputTextHeight(inputView)); } @Test public void testCreateDialog_textInputEditText_shouldNotTruncateOnLargeDensity() throws Throwable { mScreenDensitySession.setLargeDensity(); mActivityTestRule.finishActivity(); mActivityTestRule.launchActivity(mFileActivityIntent); mFragmentManager = mActivityTestRule.getActivity().getSupportFragmentManager(); mActivityTestRule.runOnUiThread(() -> CreateDirectoryFragment.show(mFragmentManager)); InstrumentationRegistry.getInstrumentation().waitForIdleSync(); mCreateDirectoryFragment = (CreateDirectoryFragment) mFragmentManager.findFragmentByTag(CREATE_FRAGEMENT_TAG); final TextInputEditText inputView = mCreateDirectoryFragment.getDialog().getWindow().findViewById(android.R.id.text1); assertTrue(inputView.getHeight() > getInputTextHeight(inputView)); } @Test public void testCreateDialog_textInputEditText_shouldNotTruncateOnLargerDensity() throws Throwable { mScreenDensitySession.setLargerDensity(); mActivityTestRule.finishActivity(); mActivityTestRule.launchActivity(mFileActivityIntent); mFragmentManager = mActivityTestRule.getActivity().getSupportFragmentManager(); mActivityTestRule.runOnUiThread(() -> CreateDirectoryFragment.show(mFragmentManager)); InstrumentationRegistry.getInstrumentation().waitForIdleSync(); mCreateDirectoryFragment = (CreateDirectoryFragment) mFragmentManager.findFragmentByTag(CREATE_FRAGEMENT_TAG); final TextInputEditText inputView = mCreateDirectoryFragment.getDialog().getWindow().findViewById(android.R.id.text1); assertTrue(inputView.getHeight() > getInputTextHeight(inputView)); } @Test public void testCreateDialog_textInputEditText_shouldNotTruncateOnLargestDensity() throws Throwable { mScreenDensitySession.setLargestDensity(); mActivityTestRule.finishActivity(); mActivityTestRule.launchActivity(mFileActivityIntent); mFragmentManager = mActivityTestRule.getActivity().getSupportFragmentManager(); mActivityTestRule.runOnUiThread(() -> CreateDirectoryFragment.show(mFragmentManager)); InstrumentationRegistry.getInstrumentation().waitForIdleSync(); mCreateDirectoryFragment = (CreateDirectoryFragment) mFragmentManager.findFragmentByTag(CREATE_FRAGEMENT_TAG); final TextInputEditText inputView = mCreateDirectoryFragment.getDialog().getWindow().findViewById(android.R.id.text1); assertTrue(inputView.getHeight() > getInputTextHeight(inputView)); } @Test public void testCreateDirectoryFragmentShows_textInputEditText_shouldNotTruncateOnLandscape() throws Throwable { switchOrientation(mActivityTestRule.getActivity()); mScreenDensitySession.setLargestDensity(); mActivityTestRule.finishActivity(); mActivityTestRule.launchActivity(mFileActivityIntent); mFragmentManager = mActivityTestRule.getActivity().getSupportFragmentManager(); mActivityTestRule.runOnUiThread(() -> CreateDirectoryFragment.show(mFragmentManager)); InstrumentationRegistry.getInstrumentation().waitForIdleSync(); mCreateDirectoryFragment = (CreateDirectoryFragment) mFragmentManager.findFragmentByTag(CREATE_FRAGEMENT_TAG); final TextInputEditText inputView = mCreateDirectoryFragment.getDialog().getWindow().findViewById(android.R.id.text1); Paint paint = inputView.getPaint(); final float textSize = paint.getTextSize(); assertTrue(inputView.getHeight() > Math.round(textSize)); switchOrientation(mActivityTestRule.getActivity()); } private static int getInputTextHeight(TextInputEditText v) { Paint paint = v.getPaint(); final float textSize = paint.getTextSize(); final float textSpace = paint.getFontSpacing(); return Math.round(textSize + textSpace); } private static void switchOrientation(final Activity activity) { final int[] orientations = getOrientations(activity); activity.setRequestedOrientation(orientations[1]); } private static int[] getOrientations(final Activity activity) { final int originalOrientation = activity.getResources().getConfiguration().orientation; final int newOrientation = originalOrientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT ? ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE : ActivityInfo.SCREEN_ORIENTATION_PORTRAIT; return new int[]{originalOrientation, newOrientation}; } private static class ScreenDensitySession implements AutoCloseable { private static final String DENSITY_PROP_DEVICE = "ro.sf.lcd_density"; private static final String DENSITY_PROP_EMULATOR = "qemu.sf.lcd_density"; private static final float DENSITY_DEFAULT = 1f; private static final float DENSITY_LARGE = 1.09f; private static final float DENSITY_LARGER = 1.19f; private static final float DENSITY_LARGEST = 1.29f; void setDefaultDensity() { final int stableDensity = getStableDensity(); final int targetDensity = (int) (stableDensity * DENSITY_DEFAULT); setDensity(targetDensity); } void setLargeDensity() { final int stableDensity = getStableDensity(); final int targetDensity = (int) (stableDensity * DENSITY_LARGE); setDensity(targetDensity); } void setLargerDensity() { final int stableDensity = getStableDensity(); final int targetDensity = (int) (stableDensity * DENSITY_LARGER); setDensity(targetDensity); } void setLargestDensity() { final int stableDensity = getStableDensity(); final int targetDensity = (int) (stableDensity * DENSITY_LARGEST); setDensity(targetDensity); } @Override public void close() { resetDensity(); } private int getStableDensity() { final String densityProp; if (Build.IS_EMULATOR) { densityProp = DENSITY_PROP_EMULATOR; } else { densityProp = DENSITY_PROP_DEVICE; } return Integer.parseInt(executeShellCommand("getprop " + densityProp).trim()); } private void setDensity(int targetDensity) { executeShellCommand("wm density " + targetDensity); // Verify that the density is changed. final String output = executeShellCommand("wm density"); final boolean success = output.contains("Override density: " + targetDensity); assertTrue("Failed to set density to " + targetDensity, success); } private void resetDensity() { executeShellCommand("wm density reset"); } } public static String executeShellCommand(String cmd) { try { return runShellCommand(InstrumentationRegistry.getInstrumentation(), cmd); } catch (IOException e) { fail("Failed reading command output: " + e); return ""; } } public static String runShellCommand(Instrumentation instrumentation, String cmd) throws IOException { return runShellCommand(instrumentation.getUiAutomation(), cmd); } public static String runShellCommand(UiAutomation automation, String cmd) throws IOException { if (cmd.startsWith("pm grant ") || cmd.startsWith("pm revoke ")) { throw new UnsupportedOperationException("Use UiAutomation.grantRuntimePermission() " + "or revokeRuntimePermission() directly, which are more robust."); } ParcelFileDescriptor pfd = automation.executeShellCommand(cmd); byte[] buf = new byte[512]; int bytesRead; FileInputStream fis = new ParcelFileDescriptor.AutoCloseInputStream(pfd); StringBuffer stdout = new StringBuffer(); while ((bytesRead = fis.read(buf)) != -1) { stdout.append(new String(buf, 0, bytesRead)); } fis.close(); return stdout.toString(); } } Loading
perf-tests/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ android_test { static_libs: [ "androidx.legacy_legacy-support-v4", "androidx.test.rules", "androidx.test.espresso.core", "mockito-target", "ub-janktesthelper", Loading
res/values/styles.xml +6 −0 Original line number Diff line number Diff line Loading @@ -91,8 +91,14 @@ <item name="buttonBarNegativeButtonStyle">@style/DialogTextButton</item> </style> <style name="MaterialAlertDialogStyle" parent="@style/MaterialAlertDialog.MaterialComponents"> <item name="backgroundInsetTop">12dp</item> <item name="backgroundInsetBottom">12dp</item> </style> <style name="MaterialAlertDialogTheme" parent="@style/ThemeOverlay.MaterialComponents.MaterialAlertDialog.Centered"> <item name="android:dialogCornerRadius">@dimen/grid_item_radius</item> <item name="alertDialogStyle">@style/MaterialAlertDialogStyle</item> <item name="buttonBarPositiveButtonStyle">@style/DialogTextButton</item> <item name="buttonBarNegativeButtonStyle">@style/DialogTextButton</item> <item name="materialAlertDialogTitleTextStyle">@style/MaterialAlertDialogTitleStyle</item> Loading
src/com/android/documentsui/CreateDirectoryFragment.java +0 −1 Original line number Diff line number Diff line Loading @@ -68,7 +68,6 @@ public class CreateDirectoryFragment extends DialogFragment { @Override public Dialog onCreateDialog(Bundle savedInstanceState) { final Context context = getActivity(); final ContentResolver resolver = context.getContentResolver(); final MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(context); final LayoutInflater dialogInflater = LayoutInflater.from(builder.getContext()); Loading
tests/common/com/android/documentsui/DialogFragmentTest.java 0 → 100644 +320 −0 Original line number Diff line number Diff line /* * Copyright (C) 2019 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.documentsui; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import android.app.Activity; import android.app.Instrumentation; import android.app.UiAutomation; import android.content.Intent; import android.content.pm.ActivityInfo; import android.graphics.Paint; import android.os.Build; import android.os.ParcelFileDescriptor; import androidx.fragment.app.FragmentManager; import androidx.test.filters.MediumTest; import androidx.test.platform.app.InstrumentationRegistry; import androidx.test.rule.ActivityTestRule; import androidx.test.runner.AndroidJUnit4; import com.android.documentsui.files.FilesActivity; import com.google.android.material.textfield.TextInputEditText; import org.junit.After; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import java.io.FileInputStream; import java.io.IOException; @MediumTest @RunWith(AndroidJUnit4.class) public class DialogFragmentTest { private static final String CREATE_FRAGEMENT_TAG = "create_directory"; CreateDirectoryFragment mCreateDirectoryFragment; FragmentManager mFragmentManager; ScreenDensitySession mScreenDensitySession; Intent mFileActivityIntent; @Rule public ActivityTestRule<FilesActivity> mActivityTestRule = new ActivityTestRule<>( FilesActivity.class); @Before public void setup() { mFileActivityIntent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE); mFragmentManager = mActivityTestRule.getActivity().getSupportFragmentManager(); mScreenDensitySession = new ScreenDensitySession(); } @After public void tearDown() { mScreenDensitySession.close(); mCreateDirectoryFragment = null; } @Test public void testCreateDialogShows() throws Throwable { mActivityTestRule.runOnUiThread(() -> CreateDirectoryFragment.show(mFragmentManager)); InstrumentationRegistry.getInstrumentation().waitForIdleSync(); mCreateDirectoryFragment = (CreateDirectoryFragment) mFragmentManager.findFragmentByTag(CREATE_FRAGEMENT_TAG); assertNotNull("Dialog was null", mCreateDirectoryFragment.getDialog()); assertTrue("Dialog was not being shown", mCreateDirectoryFragment.getDialog().isShowing()); } @Test public void testCreateDialogShowsDismiss() throws Throwable { mActivityTestRule.runOnUiThread(() -> CreateDirectoryFragment.show(mFragmentManager)); InstrumentationRegistry.getInstrumentation().waitForIdleSync(); mCreateDirectoryFragment = (CreateDirectoryFragment) mFragmentManager.findFragmentByTag(CREATE_FRAGEMENT_TAG); assertNotNull("Dialog was null", mCreateDirectoryFragment.getDialog()); assertTrue("Dialog was not being shown", mCreateDirectoryFragment.getDialog().isShowing()); mActivityTestRule.runOnUiThread(() -> mCreateDirectoryFragment.dismiss()); InstrumentationRegistry.getInstrumentation().waitForIdleSync(); assertNull("Dialog should be null after dismiss()", mCreateDirectoryFragment.getDialog()); } @Test public void testCreateDialogShows_textInputEditText_shouldNotTruncateOnPortrait() throws Throwable { mActivityTestRule.runOnUiThread(() -> CreateDirectoryFragment.show(mFragmentManager)); InstrumentationRegistry.getInstrumentation().waitForIdleSync(); mCreateDirectoryFragment = (CreateDirectoryFragment) mFragmentManager.findFragmentByTag(CREATE_FRAGEMENT_TAG); final TextInputEditText inputView = mCreateDirectoryFragment.getDialog().findViewById(android.R.id.text1); assertTrue(inputView.getHeight() > getInputTextHeight(inputView)); } @Test public void testCreateDialog_textInputEditText_shouldNotTruncateOnLargeDensity() throws Throwable { mScreenDensitySession.setLargeDensity(); mActivityTestRule.finishActivity(); mActivityTestRule.launchActivity(mFileActivityIntent); mFragmentManager = mActivityTestRule.getActivity().getSupportFragmentManager(); mActivityTestRule.runOnUiThread(() -> CreateDirectoryFragment.show(mFragmentManager)); InstrumentationRegistry.getInstrumentation().waitForIdleSync(); mCreateDirectoryFragment = (CreateDirectoryFragment) mFragmentManager.findFragmentByTag(CREATE_FRAGEMENT_TAG); final TextInputEditText inputView = mCreateDirectoryFragment.getDialog().getWindow().findViewById(android.R.id.text1); assertTrue(inputView.getHeight() > getInputTextHeight(inputView)); } @Test public void testCreateDialog_textInputEditText_shouldNotTruncateOnLargerDensity() throws Throwable { mScreenDensitySession.setLargerDensity(); mActivityTestRule.finishActivity(); mActivityTestRule.launchActivity(mFileActivityIntent); mFragmentManager = mActivityTestRule.getActivity().getSupportFragmentManager(); mActivityTestRule.runOnUiThread(() -> CreateDirectoryFragment.show(mFragmentManager)); InstrumentationRegistry.getInstrumentation().waitForIdleSync(); mCreateDirectoryFragment = (CreateDirectoryFragment) mFragmentManager.findFragmentByTag(CREATE_FRAGEMENT_TAG); final TextInputEditText inputView = mCreateDirectoryFragment.getDialog().getWindow().findViewById(android.R.id.text1); assertTrue(inputView.getHeight() > getInputTextHeight(inputView)); } @Test public void testCreateDialog_textInputEditText_shouldNotTruncateOnLargestDensity() throws Throwable { mScreenDensitySession.setLargestDensity(); mActivityTestRule.finishActivity(); mActivityTestRule.launchActivity(mFileActivityIntent); mFragmentManager = mActivityTestRule.getActivity().getSupportFragmentManager(); mActivityTestRule.runOnUiThread(() -> CreateDirectoryFragment.show(mFragmentManager)); InstrumentationRegistry.getInstrumentation().waitForIdleSync(); mCreateDirectoryFragment = (CreateDirectoryFragment) mFragmentManager.findFragmentByTag(CREATE_FRAGEMENT_TAG); final TextInputEditText inputView = mCreateDirectoryFragment.getDialog().getWindow().findViewById(android.R.id.text1); assertTrue(inputView.getHeight() > getInputTextHeight(inputView)); } @Test public void testCreateDirectoryFragmentShows_textInputEditText_shouldNotTruncateOnLandscape() throws Throwable { switchOrientation(mActivityTestRule.getActivity()); mScreenDensitySession.setLargestDensity(); mActivityTestRule.finishActivity(); mActivityTestRule.launchActivity(mFileActivityIntent); mFragmentManager = mActivityTestRule.getActivity().getSupportFragmentManager(); mActivityTestRule.runOnUiThread(() -> CreateDirectoryFragment.show(mFragmentManager)); InstrumentationRegistry.getInstrumentation().waitForIdleSync(); mCreateDirectoryFragment = (CreateDirectoryFragment) mFragmentManager.findFragmentByTag(CREATE_FRAGEMENT_TAG); final TextInputEditText inputView = mCreateDirectoryFragment.getDialog().getWindow().findViewById(android.R.id.text1); Paint paint = inputView.getPaint(); final float textSize = paint.getTextSize(); assertTrue(inputView.getHeight() > Math.round(textSize)); switchOrientation(mActivityTestRule.getActivity()); } private static int getInputTextHeight(TextInputEditText v) { Paint paint = v.getPaint(); final float textSize = paint.getTextSize(); final float textSpace = paint.getFontSpacing(); return Math.round(textSize + textSpace); } private static void switchOrientation(final Activity activity) { final int[] orientations = getOrientations(activity); activity.setRequestedOrientation(orientations[1]); } private static int[] getOrientations(final Activity activity) { final int originalOrientation = activity.getResources().getConfiguration().orientation; final int newOrientation = originalOrientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT ? ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE : ActivityInfo.SCREEN_ORIENTATION_PORTRAIT; return new int[]{originalOrientation, newOrientation}; } private static class ScreenDensitySession implements AutoCloseable { private static final String DENSITY_PROP_DEVICE = "ro.sf.lcd_density"; private static final String DENSITY_PROP_EMULATOR = "qemu.sf.lcd_density"; private static final float DENSITY_DEFAULT = 1f; private static final float DENSITY_LARGE = 1.09f; private static final float DENSITY_LARGER = 1.19f; private static final float DENSITY_LARGEST = 1.29f; void setDefaultDensity() { final int stableDensity = getStableDensity(); final int targetDensity = (int) (stableDensity * DENSITY_DEFAULT); setDensity(targetDensity); } void setLargeDensity() { final int stableDensity = getStableDensity(); final int targetDensity = (int) (stableDensity * DENSITY_LARGE); setDensity(targetDensity); } void setLargerDensity() { final int stableDensity = getStableDensity(); final int targetDensity = (int) (stableDensity * DENSITY_LARGER); setDensity(targetDensity); } void setLargestDensity() { final int stableDensity = getStableDensity(); final int targetDensity = (int) (stableDensity * DENSITY_LARGEST); setDensity(targetDensity); } @Override public void close() { resetDensity(); } private int getStableDensity() { final String densityProp; if (Build.IS_EMULATOR) { densityProp = DENSITY_PROP_EMULATOR; } else { densityProp = DENSITY_PROP_DEVICE; } return Integer.parseInt(executeShellCommand("getprop " + densityProp).trim()); } private void setDensity(int targetDensity) { executeShellCommand("wm density " + targetDensity); // Verify that the density is changed. final String output = executeShellCommand("wm density"); final boolean success = output.contains("Override density: " + targetDensity); assertTrue("Failed to set density to " + targetDensity, success); } private void resetDensity() { executeShellCommand("wm density reset"); } } public static String executeShellCommand(String cmd) { try { return runShellCommand(InstrumentationRegistry.getInstrumentation(), cmd); } catch (IOException e) { fail("Failed reading command output: " + e); return ""; } } public static String runShellCommand(Instrumentation instrumentation, String cmd) throws IOException { return runShellCommand(instrumentation.getUiAutomation(), cmd); } public static String runShellCommand(UiAutomation automation, String cmd) throws IOException { if (cmd.startsWith("pm grant ") || cmd.startsWith("pm revoke ")) { throw new UnsupportedOperationException("Use UiAutomation.grantRuntimePermission() " + "or revokeRuntimePermission() directly, which are more robust."); } ParcelFileDescriptor pfd = automation.executeShellCommand(cmd); byte[] buf = new byte[512]; int bytesRead; FileInputStream fis = new ParcelFileDescriptor.AutoCloseInputStream(pfd); StringBuffer stdout = new StringBuffer(); while ((bytesRead = fis.read(buf)) != -1) { stdout.append(new String(buf, 0, bytesRead)); } fis.close(); return stdout.toString(); } }