diff options
author | MÃ¥rten Kongstad <marten.kongstad@sonyericsson.com> | 2011-03-17 14:13:41 +0100 |
---|---|---|
committer | Kenneth Andersson <kenneth.andersson@sonyericsson.com> | 2011-04-01 14:12:10 +0200 |
commit | 57f4b77c89bafedf9468f9a636561c0c193405c9 (patch) | |
tree | 9e73065411411858c9c6ae350c5ee8ffe14598c3 /core | |
parent | c6b22e2727bd3730edd5ad72831a9bb4670d00f3 (diff) | |
download | frameworks_base-57f4b77c89bafedf9468f9a636561c0c193405c9.zip frameworks_base-57f4b77c89bafedf9468f9a636561c0c193405c9.tar.gz frameworks_base-57f4b77c89bafedf9468f9a636561c0c193405c9.tar.bz2 |
Runtime resource overlay, iteration 1.
Runtime resource overlay allows unmodified applications to appear
as if they had been compiled with additional resources defined. See
libs/utils/README for more information.
This commit is the first iteration of runtime resource overlay. It
provides the actual overlay modifications and loading of trusted overlay
packages (ie residing in /vendor) targeting framework-res.apk.
This commit loads exactly one overlay package. The overlay,
if present, must target framework-res.apk and be located at
/vendor/overlay/framework/framework-res.apk.
Change-Id: If26ee7754813004a96c043dba37fbe99fa3919db
Diffstat (limited to 'core')
13 files changed, 297 insertions, 0 deletions
diff --git a/core/tests/overlaytests/Android.mk b/core/tests/overlaytests/Android.mk new file mode 100644 index 0000000..bf69442 --- /dev/null +++ b/core/tests/overlaytests/Android.mk @@ -0,0 +1,4 @@ +# Dummy makefile to halt recursive directory traversal. + +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) diff --git a/core/tests/overlaytests/OverlayTest/Android.mk b/core/tests/overlaytests/OverlayTest/Android.mk new file mode 100644 index 0000000..f7f67f6 --- /dev/null +++ b/core/tests/overlaytests/OverlayTest/Android.mk @@ -0,0 +1,10 @@ +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := tests + +LOCAL_PACKAGE_NAME := OverlayTest + +LOCAL_SRC_FILES := $(call all-java-files-under, src) + +include $(BUILD_PACKAGE) diff --git a/core/tests/overlaytests/OverlayTest/AndroidManifest.xml b/core/tests/overlaytests/OverlayTest/AndroidManifest.xml new file mode 100644 index 0000000..9edba12 --- /dev/null +++ b/core/tests/overlaytests/OverlayTest/AndroidManifest.xml @@ -0,0 +1,10 @@ +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.overlaytest"> + <uses-permission android:name="android.permission.RUN_INSTRUMENTATION"/> + <application> + <uses-library android:name="android.test.runner"/> + </application> + <instrumentation android:name="android.test.InstrumentationTestRunner" + android:targetPackage="com.android.overlaytest" + android:label="Runtime resource overlay tests"/> +</manifest> diff --git a/core/tests/overlaytests/OverlayTest/src/com/android/overlaytest/OverlayBaseTest.java b/core/tests/overlaytests/OverlayTest/src/com/android/overlaytest/OverlayBaseTest.java new file mode 100644 index 0000000..85b49ce --- /dev/null +++ b/core/tests/overlaytests/OverlayTest/src/com/android/overlaytest/OverlayBaseTest.java @@ -0,0 +1,118 @@ +package com.android.overlaytest; + +import android.content.res.Configuration; +import android.content.res.Resources; +import android.test.AndroidTestCase; +import java.io.InputStream; +import java.util.Locale; + +public abstract class OverlayBaseTest extends AndroidTestCase { + private Resources mResources; + protected boolean mWithOverlay; // will be set by subclasses + + protected void setUp() { + mResources = getContext().getResources(); + } + + private int calculateRawResourceChecksum(int resId) throws Throwable { + InputStream input = null; + try { + input = mResources.openRawResource(resId); + int ch, checksum = 0; + while ((ch = input.read()) != -1) { + checksum = (checksum + ch) % 0xffddbb00; + } + return checksum; + } finally { + input.close(); + } + } + + private void setLocale(String code) { + Locale locale = new Locale(code); + Locale.setDefault(locale); + Configuration config = new Configuration(); + config.locale = locale; + mResources.updateConfiguration(config, mResources.getDisplayMetrics()); + } + + private void assertResource(int resId, boolean ewo, boolean ew) throws Throwable { + boolean expected = mWithOverlay ? ew : ewo; + boolean actual = mResources.getBoolean(resId); + assertEquals(expected, actual); + } + + private void assertResource(int resId, String ewo, String ew) throws Throwable { + String expected = mWithOverlay ? ew : ewo; + String actual = mResources.getString(resId); + assertEquals(expected, actual); + } + + private void assertResource(int resId, int[] ewo, int[] ew) throws Throwable { + int[] expected = mWithOverlay ? ew : ewo; + int[] actual = mResources.getIntArray(resId); + assertEquals("length:", expected.length, actual.length); + for (int i = 0; i < actual.length; ++i) { + assertEquals("index " + i + ":", actual[i], expected[i]); + } + } + + public void testBooleanOverlay() throws Throwable { + // config_automatic_brightness_available has overlay (default config) + final int resId = com.android.internal.R.bool.config_automatic_brightness_available; + assertResource(resId, false, true); + } + + public void testBoolean() throws Throwable { + // config_bypass_keyguard_if_slider_open has no overlay + final int resId = com.android.internal.R.bool.config_bypass_keyguard_if_slider_open; + assertResource(resId, true, true); + } + + public void testStringOverlay() throws Throwable { + // phoneTypeCar has an overlay (default config), which shouldn't shadow + // the Swedish translation + final int resId = com.android.internal.R.string.phoneTypeCar; + setLocale("sv_SE"); + assertResource(resId, "Bil", "Bil"); + } + + public void testStringSwedishOverlay() throws Throwable { + // phoneTypeWork has overlay (no default config, only for lang=sv) + final int resId = com.android.internal.R.string.phoneTypeWork; + setLocale("en_US"); + assertResource(resId, "Work", "Work"); + setLocale("sv_SE"); + assertResource(resId, "Arbete", "Jobb"); + } + + public void testString() throws Throwable { + // phoneTypeHome has no overlay + final int resId = com.android.internal.R.string.phoneTypeHome; + setLocale("en_US"); + assertResource(resId, "Home", "Home"); + setLocale("sv_SE"); + assertResource(resId, "Hem", "Hem"); + } + + public void testIntegerArrayOverlay() throws Throwable { + // config_scrollBarrierVibePattern has overlay (default config) + final int resId = com.android.internal.R.array.config_scrollBarrierVibePattern; + assertResource(resId, new int[]{0, 15, 10, 10}, new int[]{100, 200, 300}); + } + + public void testIntegerArray() throws Throwable { + // config_virtualKeyVibePattern has no overlay + final int resId = com.android.internal.R.array.config_virtualKeyVibePattern; + final int[] expected = {0, 10, 20, 30}; + assertResource(resId, expected, expected); + } + + public void testAsset() throws Throwable { + // drawable/default_background.jpg has overlay (default config) + final int resId = com.android.internal.R.drawable.default_wallpaper; + int actual = calculateRawResourceChecksum(resId); + int expected = mWithOverlay ? 0x000051da : 0x0014ebce; + assertEquals(expected, actual); + } +} diff --git a/core/tests/overlaytests/OverlayTest/src/com/android/overlaytest/WithOverlayTest.java b/core/tests/overlaytests/OverlayTest/src/com/android/overlaytest/WithOverlayTest.java new file mode 100644 index 0000000..1292d03 --- /dev/null +++ b/core/tests/overlaytests/OverlayTest/src/com/android/overlaytest/WithOverlayTest.java @@ -0,0 +1,7 @@ +package com.android.overlaytest; + +public class WithOverlayTest extends OverlayBaseTest { + public WithOverlayTest() { + mWithOverlay = true; + } +} diff --git a/core/tests/overlaytests/OverlayTest/src/com/android/overlaytest/WithoutOverlayTest.java b/core/tests/overlaytests/OverlayTest/src/com/android/overlaytest/WithoutOverlayTest.java new file mode 100644 index 0000000..630ff8f --- /dev/null +++ b/core/tests/overlaytests/OverlayTest/src/com/android/overlaytest/WithoutOverlayTest.java @@ -0,0 +1,7 @@ +package com.android.overlaytest; + +public class WithoutOverlayTest extends OverlayBaseTest { + public WithoutOverlayTest() { + mWithOverlay = false; + } +} diff --git a/core/tests/overlaytests/OverlayTestOverlay/Android.mk b/core/tests/overlaytests/OverlayTestOverlay/Android.mk new file mode 100644 index 0000000..cf32c9f --- /dev/null +++ b/core/tests/overlaytests/OverlayTestOverlay/Android.mk @@ -0,0 +1,14 @@ +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := tests + +LOCAL_SRC_FILES := $(call all-java-files-under, src) + +LOCAL_SDK_VERSION := current + +LOCAL_PACKAGE_NAME := com.android.overlaytest.overlay + +LOCAL_AAPT_FLAGS := -o + +include $(BUILD_PACKAGE) diff --git a/core/tests/overlaytests/OverlayTestOverlay/AndroidManifest.xml b/core/tests/overlaytests/OverlayTestOverlay/AndroidManifest.xml new file mode 100644 index 0000000..bcbb0d1 --- /dev/null +++ b/core/tests/overlaytests/OverlayTestOverlay/AndroidManifest.xml @@ -0,0 +1,6 @@ +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.overlaytest.overlay" + android:versionCode="1" + android:versionName="1.0"> + <overlay-package android:name="android"/> +</manifest> diff --git a/core/tests/overlaytests/OverlayTestOverlay/res/drawable/default_wallpaper.jpg b/core/tests/overlaytests/OverlayTestOverlay/res/drawable/default_wallpaper.jpg Binary files differnew file mode 100644 index 0000000..0d944d0 --- /dev/null +++ b/core/tests/overlaytests/OverlayTestOverlay/res/drawable/default_wallpaper.jpg diff --git a/core/tests/overlaytests/OverlayTestOverlay/res/values-sv/config.xml b/core/tests/overlaytests/OverlayTestOverlay/res/values-sv/config.xml new file mode 100644 index 0000000..bc52367 --- /dev/null +++ b/core/tests/overlaytests/OverlayTestOverlay/res/values-sv/config.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="phoneTypeWork">Jobb</string> +</resources> diff --git a/core/tests/overlaytests/OverlayTestOverlay/res/values/config.xml b/core/tests/overlaytests/OverlayTestOverlay/res/values/config.xml new file mode 100644 index 0000000..794f475 --- /dev/null +++ b/core/tests/overlaytests/OverlayTestOverlay/res/values/config.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <bool name="config_automatic_brightness_available">true</bool> + <string name="phoneTypeCar">Automobile</string> + <integer-array name="config_scrollBarrierVibePattern"> + <item>100</item> + <item>200</item> + <item>300</item> + </integer-array> + <!-- The following integer does not exist in the original package. Idmap + generation should therefore ignore it. --> + <integer name="integer_not_in_original_package">0</integer> +</resources> diff --git a/core/tests/overlaytests/README b/core/tests/overlaytests/README new file mode 100644 index 0000000..4b3e6f2 --- /dev/null +++ b/core/tests/overlaytests/README @@ -0,0 +1,15 @@ +Unit tests for runtime resource overlay +======================================= + +As of this writing, runtime resource overlay is only triggered for +/system/framework/framework-res.apk. Because of this, installation of +overlay packages require the Android platform be rebooted. However, the +regular unit tests (triggered via development/testrunner/runtest.py) +cannot handle reboots. As a workaround, this directory contains a shell +script which will trigger the tests in a non-standard way. + +Once runtime resource overlay may be applied to applications, the tests +in this directory should be moved to core/tests/coretests. Also, by +applying runtime resource overlay to a dedicated test application, the +test cases would not need to assume default values for non-overlaid +resources. diff --git a/core/tests/overlaytests/runtests.sh b/core/tests/overlaytests/runtests.sh new file mode 100755 index 0000000..0ad9efb --- /dev/null +++ b/core/tests/overlaytests/runtests.sh @@ -0,0 +1,89 @@ +#!/bin/bash + +adb="adb" +if [[ $# -gt 0 ]]; then + adb="adb $*" # for setting -e, -d or -s <serial> +fi + +function atexit() +{ + local retval=$? + + if [[ $retval -eq 0 ]]; then + rm $log + else + echo "There were errors, please check log at $log" + fi +} + +log=$(mktemp) +trap "atexit" EXIT +failures=0 + +function compile_module() +{ + local android_mk="$1" + + echo "Compiling .${android_mk:${#PWD}}" + ONE_SHOT_MAKEFILE="$android_mk" make -C "../../../../../" files | tee -a $log + if [[ ${PIPESTATUS[0]} -ne 0 ]]; then + exit 1 + fi +} + +function wait_for_boot_completed() +{ + echo "Rebooting device" + $adb wait-for-device logcat -c + $adb wait-for-device logcat | grep -m 1 -e 'PowerManagerService.*bootCompleted' >/dev/null +} + +function disable_overlay() +{ + echo "Disabling overlay" + $adb shell rm /vendor/overlay/framework/framework-res.apk + $adb shell rm /data/resource-cache/vendor@overlay@framework@framework-res.apk@idmap +} + +function enable_overlay() +{ + echo "Enabling overlay" + $adb shell ln -s /data/app/com.android.overlaytest.overlay.apk /vendor/overlay/framework/framework-res.apk +} + +function instrument() +{ + local class="$1" + + echo "Instrumenting $class" + $adb shell am instrument -w -e class $class com.android.overlaytest/android.test.InstrumentationTestRunner | tee -a $log +} + +function sync() +{ + echo "Syncing to device" + $adb remount | tee -a $log + $adb sync data | tee -a $log +} + +# build and sync +compile_module "$PWD/OverlayTest/Android.mk" +compile_module "$PWD/OverlayTestOverlay/Android.mk" +sync + +# instrument test (without overlay) +$adb shell stop +disable_overlay +$adb shell start +wait_for_boot_completed +instrument "com.android.overlaytest.WithoutOverlayTest" + +# instrument test (with overlay) +$adb shell stop +enable_overlay +$adb shell start +wait_for_boot_completed +instrument "com.android.overlaytest.WithOverlayTest" + +# cleanup +exit $(grep -c -e '^FAILURES' $log) |