diff options
Diffstat (limited to 'tests')
36 files changed, 1037 insertions, 397 deletions
diff --git a/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java b/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java index d5549cc1355e..07b3a97817a3 100644 --- a/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java +++ b/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java @@ -439,6 +439,14 @@ public class ActivityTestMain extends Activity { return true; } }); + menu.add("Require unknown permission").setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { + @Override public boolean onMenuItemClick(MenuItem item) { + final Intent intent = new Intent(SLOW_RECEIVER_ACTION); + intent.putExtra(SLOW_RECEIVER_EXTRA, 5038); + sendOrderedBroadcast(intent, "com.google.android.test.activity.permission.UNDEFINED"); + return true; + } + }); menu.add("Stack Doc").setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem item) { ActivityManager.AppTask task = findDocTask(); diff --git a/tests/DexLoggerIntegrationTests/src/com/android/server/pm/dex/DexLoggerIntegrationTests.java b/tests/DexLoggerIntegrationTests/src/com/android/server/pm/dex/DexLoggerIntegrationTests.java index e92cc56322eb..99d1f5ff4bb3 100644 --- a/tests/DexLoggerIntegrationTests/src/com/android/server/pm/dex/DexLoggerIntegrationTests.java +++ b/tests/DexLoggerIntegrationTests/src/com/android/server/pm/dex/DexLoggerIntegrationTests.java @@ -49,13 +49,13 @@ import java.util.List; import java.util.concurrent.TimeUnit; /** - * Integration tests for {@link com.android.server.pm.dex.DexLogger}. + * Integration tests for {@link DynamicCodeLogger}, formerly known as {@code DexLogger}. * * The setup for the test dynamically loads code in a jar extracted * from our assets (a secondary dex file). * * We then use shell commands to trigger dynamic code logging (and wait - * for it to complete). This causes DexLogger to log the hash of the + * for it to complete). This causes DynamicCodeLogger to log the hash of the * file's name and content. We verify that this message appears in * the event log. * @@ -65,6 +65,8 @@ import java.util.concurrent.TimeUnit; @RunWith(JUnit4.class) public final class DexLoggerIntegrationTests { + private static final String SHA_256 = "SHA-256"; + // Event log tag used for SNET related events private static final int SNET_TAG = 0x534e4554; @@ -76,6 +78,13 @@ public final class DexLoggerIntegrationTests { private static final int IDLE_LOGGING_JOB_ID = 2030028; private static final int AUDIT_WATCHING_JOB_ID = 203142925; + // For tests that rely on parsing audit logs, how often to retry. (There are many reasons why + // we might not see the audit logs, including throttling and delays in log generation, so to + // avoid flakiness we run these tests multiple times, allowing progressively longer between + // code loading and checking the logs on each try.) + private static final int AUDIT_LOG_RETRIES = 10; + private static final int RETRY_DELAY_MS = 2_000; + private static Context sContext; private static int sMyUid; @@ -99,7 +108,7 @@ public final class DexLoggerIntegrationTests { } @Test - public void testDexLoggerGeneratesEvents_standardClassLoader() throws Exception { + public void testGeneratesEvents_standardClassLoader() throws Exception { File privateCopyFile = privateFile("copied.jar"); // Obtained via "echo -n copied.jar | sha256sum" String expectedNameHash = @@ -121,7 +130,7 @@ public final class DexLoggerIntegrationTests { } @Test - public void testDexLoggerGeneratesEvents_unknownClassLoader() throws Exception { + public void testGeneratesEvents_unknownClassLoader() throws Exception { File privateCopyFile = privateFile("copied2.jar"); String expectedNameHash = "202158B6A3169D78F1722487205A6B036B3F2F5653FDCFB4E74710611AC7EB93"; @@ -143,79 +152,66 @@ public final class DexLoggerIntegrationTests { } @Test - public void testDexLoggerGeneratesEvents_nativeLibrary() throws Exception { - File privateCopyFile = privateFile("copied.so"); - String expectedNameHash = - "996223BAD4B4FE75C57A3DEC61DB9C0B38E0A7AD479FC95F33494F4BC55A0F0E"; - String expectedContentHash = - copyAndHashResource(libraryPath("DexLoggerNativeTestLibrary.so"), privateCopyFile); - - System.load(privateCopyFile.toString()); - - // Run the job to scan generated audit log entries - runDynamicCodeLoggingJob(AUDIT_WATCHING_JOB_ID); - - // And then make sure we log events about it - long previousEventNanos = mostRecentEventTimeNanos(); - runDynamicCodeLoggingJob(IDLE_LOGGING_JOB_ID); - - assertDclLoggedSince(previousEventNanos, DCL_NATIVE_SUBTAG, - expectedNameHash, expectedContentHash); + public void testGeneratesEvents_nativeLibrary() throws Exception { + new TestNativeCodeWithRetries() { + @Override + protected void loadNativeCode(int tryNumber) throws Exception { + // We need to use a different file name for each retry, because once a file is + // loaded, re-loading it has no effect. + String privateCopyName = "copied" + tryNumber + ".so"; + File privateCopyFile = privateFile(privateCopyName); + mExpectedNameHash = hashOf(privateCopyName); + mExpectedContentHash = copyAndHashResource( + libraryPath("DexLoggerNativeTestLibrary.so"), privateCopyFile); + + System.load(privateCopyFile.toString()); + } + }.runTest(); } @Test - public void testDexLoggerGeneratesEvents_nativeLibrary_escapedName() throws Exception { - // A file name with a space will be escaped in the audit log; verify we un-escape it - // correctly. - File privateCopyFile = privateFile("second copy.so"); - String expectedNameHash = - "8C39990C560B4F36F83E208E279F678746FE23A790E4C50F92686584EA2041CA"; - String expectedContentHash = - copyAndHashResource(libraryPath("DexLoggerNativeTestLibrary.so"), privateCopyFile); - - System.load(privateCopyFile.toString()); - - // Run the job to scan generated audit log entries - runDynamicCodeLoggingJob(AUDIT_WATCHING_JOB_ID); - - // And then make sure we log events about it - long previousEventNanos = mostRecentEventTimeNanos(); - runDynamicCodeLoggingJob(IDLE_LOGGING_JOB_ID); - - assertDclLoggedSince(previousEventNanos, DCL_NATIVE_SUBTAG, - expectedNameHash, expectedContentHash); + public void testGeneratesEvents_nativeLibrary_escapedName() throws Exception { + new TestNativeCodeWithRetries() { + @Override + protected void loadNativeCode(int tryNumber) throws Exception { + // A file name with a space will be escaped in the audit log; verify we un-escape it + // correctly. + String privateCopyName = "second copy " + tryNumber + ".so"; + File privateCopyFile = privateFile(privateCopyName); + mExpectedNameHash = hashOf(privateCopyName); + mExpectedContentHash = copyAndHashResource( + libraryPath("DexLoggerNativeTestLibrary.so"), privateCopyFile); + + System.load(privateCopyFile.toString()); + } + }.runTest(); } @Test - public void testDexLoggerGeneratesEvents_nativeExecutable() throws Exception { - File privateCopyFile = privateFile("test_executable"); - String expectedNameHash = - "3FBEC3F925A132D18F347F11AE9A5BB8DE1238828F8B4E064AA86EB68BD46DCF"; - String expectedContentHash = - copyAndHashResource("/DexLoggerNativeExecutable", privateCopyFile); - assertThat(privateCopyFile.setExecutable(true)).isTrue(); - - Process process = Runtime.getRuntime().exec(privateCopyFile.toString()); - int exitCode = process.waitFor(); - assertThat(exitCode).isEqualTo(0); - - // Run the job to scan generated audit log entries - runDynamicCodeLoggingJob(AUDIT_WATCHING_JOB_ID); - - // And then make sure we log events about it - long previousEventNanos = mostRecentEventTimeNanos(); - runDynamicCodeLoggingJob(IDLE_LOGGING_JOB_ID); - - assertDclLoggedSince(previousEventNanos, DCL_NATIVE_SUBTAG, - expectedNameHash, expectedContentHash); + public void testGeneratesEvents_nativeExecutable() throws Exception { + new TestNativeCodeWithRetries() { + @Override + protected void loadNativeCode(int tryNumber) throws Exception { + String privateCopyName = "test_executable" + tryNumber; + File privateCopyFile = privateFile(privateCopyName); + mExpectedNameHash = hashOf(privateCopyName); + mExpectedContentHash = copyAndHashResource( + "/DexLoggerNativeExecutable", privateCopyFile); + assertThat(privateCopyFile.setExecutable(true)).isTrue(); + + Process process = Runtime.getRuntime().exec(privateCopyFile.toString()); + int exitCode = process.waitFor(); + assertThat(exitCode).isEqualTo(0); + } + }.runTest(); } @Test - public void testDexLoggerGeneratesEvents_spoofed_validFile() throws Exception { + public void testGeneratesEvents_spoofed_validFile() throws Exception { File privateCopyFile = privateFile("spoofed"); - String expectedContentHash = - copyAndHashResource("/DexLoggerNativeExecutable", privateCopyFile); + String expectedContentHash = copyAndHashResource( + "/DexLoggerNativeExecutable", privateCopyFile); EventLog.writeEvent(EventLog.getTagCode("auditd"), "type=1400 avc: granted { execute_no_trans } " @@ -239,7 +235,7 @@ public final class DexLoggerIntegrationTests { } @Test - public void testDexLoggerGeneratesEvents_spoofed_pathTraversal() throws Exception { + public void testGeneratesEvents_spoofed_pathTraversal() throws Exception { File privateDir = privateFile("x").getParentFile(); // Transform /a/b/c -> /a/b/c/../../.. so we get back to the root @@ -276,7 +272,7 @@ public final class DexLoggerIntegrationTests { } @Test - public void testDexLoggerGeneratesEvents_spoofed_otherAppFile() throws Exception { + public void testGeneratesEvents_spoofed_otherAppFile() throws Exception { File ourPath = sContext.getDatabasePath("android_pay"); File targetPath = new File(ourPath.toString() .replace("com.android.frameworks.dexloggertest", "com.google.android.gms")); @@ -304,6 +300,40 @@ public final class DexLoggerIntegrationTests { assertNoDclLoggedSince(previousEventNanos, DCL_NATIVE_SUBTAG, expectedNameHash); } + // Abstract out the logic for running a native code loading test multiple times if needed and + // leaving time for audit messages to reach the log. + private abstract class TestNativeCodeWithRetries { + String mExpectedContentHash; + String mExpectedNameHash; + + abstract void loadNativeCode(int tryNumber) throws Exception; + + final void runTest() throws Exception { + List<String> messages = null; + + for (int i = 0; i < AUDIT_LOG_RETRIES; i++) { + loadNativeCode(i); + + SystemClock.sleep(i * RETRY_DELAY_MS); + + // Run the job to scan generated audit log entries + runDynamicCodeLoggingJob(AUDIT_WATCHING_JOB_ID); + + // And then make sure we log events about it + long previousEventNanos = mostRecentEventTimeNanos(); + runDynamicCodeLoggingJob(IDLE_LOGGING_JOB_ID); + + messages = findMatchingEvents( + previousEventNanos, DCL_NATIVE_SUBTAG, mExpectedNameHash); + if (!messages.isEmpty()) { + break; + } + } + + assertHasDclLog(messages, mExpectedContentHash); + } + } + private static File privateFile(String name) { return new File(sContext.getDir("dcl", Context.MODE_PRIVATE), name); } @@ -315,7 +345,7 @@ public final class DexLoggerIntegrationTests { } private static String copyAndHashResource(String resourcePath, File copyTo) throws Exception { - MessageDigest hasher = MessageDigest.getInstance("SHA-256"); + MessageDigest hasher = MessageDigest.getInstance(SHA_256); // Copy the jar from our Java resources to a private data directory Class<?> thisClass = DexLoggerIntegrationTests.class; @@ -334,6 +364,16 @@ public final class DexLoggerIntegrationTests { // Compute the SHA-256 of the file content so we can check that it is the same as the value // we see logged. + return toHexString(hasher); + } + + private String hashOf(String input) throws Exception { + MessageDigest hasher = MessageDigest.getInstance(SHA_256); + hasher.update(input.getBytes()); + return toHexString(hasher); + } + + private static String toHexString(MessageDigest hasher) { Formatter formatter = new Formatter(); for (byte b : hasher.digest()) { formatter.format("%02X", b); @@ -388,6 +428,10 @@ public final class DexLoggerIntegrationTests { List<String> messages = findMatchingEvents(previousEventNanos, expectedSubTag, expectedNameHash); + assertHasDclLog(messages, expectedContentHash); + } + + private static void assertHasDclLog(List<String> messages, String expectedContentHash) { assertWithMessage("Expected exactly one matching log entry").that(messages).hasSize(1); assertThat(messages.get(0)).endsWith(expectedContentHash); } diff --git a/tests/HwAccelerationTest/Android.bp b/tests/HwAccelerationTest/Android.bp new file mode 100644 index 000000000000..37d3f5d4d97f --- /dev/null +++ b/tests/HwAccelerationTest/Android.bp @@ -0,0 +1,22 @@ +// +// Copyright (C) 2010 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. +// + +android_test { + name: "HwAccelerationTest", + srcs: ["**/*.java"], + platform_apis: true, + certificate: "platform", +} diff --git a/tests/HwAccelerationTest/Android.mk b/tests/HwAccelerationTest/Android.mk deleted file mode 100644 index 79072faeaa0e..000000000000 --- a/tests/HwAccelerationTest/Android.mk +++ /dev/null @@ -1,28 +0,0 @@ -# -# Copyright (C) 2010 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. -# - -LOCAL_PATH:= $(call my-dir) -include $(CLEAR_VARS) - -LOCAL_SRC_FILES := $(call all-subdir-java-files) - -LOCAL_PACKAGE_NAME := HwAccelerationTest -LOCAL_PRIVATE_PLATFORM_APIS := true -LOCAL_CERTIFICATE := platform - -LOCAL_MODULE_TAGS := tests - -include $(BUILD_PACKAGE) diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml index 1a4ec94d77b4..7b8c154dea1e 100644 --- a/tests/HwAccelerationTest/AndroidManifest.xml +++ b/tests/HwAccelerationTest/AndroidManifest.xml @@ -1028,8 +1028,28 @@ </activity> <activity - android:name="PositionListenerActivity" - android:label="RenderNode/PositionListener" + android:name="PositionListenerActivity" + android:label="RenderNode/PositionListener" + android:screenOrientation="fullSensor"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="com.android.test.hwui.TEST" /> + </intent-filter> + </activity> + + <activity + android:name="CustomRenderer" + android:label="HardwareRenderer/HelloTakeSurface" + android:screenOrientation="fullSensor"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="com.android.test.hwui.TEST" /> + </intent-filter> + </activity> + + <activity + android:name="MyLittleTextureView" + android:label="HardwareRenderer/MyLittleTextureView" android:screenOrientation="fullSensor"> <intent-filter> <action android:name="android.intent.action.MAIN" /> diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/CustomRenderer.java b/tests/HwAccelerationTest/src/com/android/test/hwui/CustomRenderer.java new file mode 100644 index 000000000000..60bd60f0bfd1 --- /dev/null +++ b/tests/HwAccelerationTest/src/com/android/test/hwui/CustomRenderer.java @@ -0,0 +1,76 @@ +/* + * 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.test.hwui; + +import android.app.Activity; +import android.graphics.Color; +import android.graphics.HardwareRenderer; +import android.graphics.Paint; +import android.graphics.RecordingCanvas; +import android.graphics.RenderNode; +import android.os.Bundle; +import android.util.Log; +import android.view.SurfaceHolder; + +public class CustomRenderer extends Activity { + private RenderNode mContent = new RenderNode("CustomRenderer"); + private HardwareRenderer mRenderer = new HardwareRenderer(); + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getWindow().takeSurface(mSurfaceCallbacks); + } + + private SurfaceHolder.Callback2 mSurfaceCallbacks = new SurfaceHolder.Callback2() { + + @Override + public void surfaceRedrawNeeded(SurfaceHolder holder) { + } + + @Override + public void surfaceCreated(SurfaceHolder holder) { + } + + @Override + public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { + mContent.setLeftTopRightBottom(0, 0, width, height); + RecordingCanvas canvas = mContent.startRecording(); + canvas.drawColor(Color.WHITE); + Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); + paint.setColor(Color.BLACK); + paint.setTextAlign(Paint.Align.CENTER); + paint.setTextSize(Math.min(width, height) * .05f); + canvas.drawText("Hello custom renderer!", width / 2, height / 2, paint); + mContent.endRecording(); + + mRenderer.setContentRoot(mContent); + mRenderer.setSurface(holder.getSurface()); + mRenderer.createRenderRequest() + .setVsyncTime(System.nanoTime()) + .setFrameCommitCallback(Runnable::run, () -> { + Log.d("CustomRenderer", "Frame committed!"); + }) + .syncAndDraw(); + } + + @Override + public void surfaceDestroyed(SurfaceHolder holder) { + mRenderer.destroy(); + } + }; +} diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/MyLittleTextureView.java b/tests/HwAccelerationTest/src/com/android/test/hwui/MyLittleTextureView.java new file mode 100644 index 000000000000..8bd7d797aea3 --- /dev/null +++ b/tests/HwAccelerationTest/src/com/android/test/hwui/MyLittleTextureView.java @@ -0,0 +1,87 @@ +/* + * 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.test.hwui; + +import android.app.Activity; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.ColorSpace; +import android.graphics.HardwareRenderer; +import android.graphics.Outline; +import android.graphics.PixelFormat; +import android.graphics.Rect; +import android.graphics.RenderNode; +import android.hardware.HardwareBuffer; +import android.media.Image; +import android.media.ImageReader; +import android.os.Bundle; +import android.widget.ImageView; + +public class MyLittleTextureView extends Activity { + private RenderNode mContent = new RenderNode("CustomRenderer"); + private HardwareRenderer mRenderer = new HardwareRenderer(); + private ImageView mImageView; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mImageView = new ImageView(this); + mImageView.setScaleType(ImageView.ScaleType.FIT_CENTER); + setContentView(mImageView); + + ImageReader reader = ImageReader.newInstance(100, 100, PixelFormat.RGBA_8888, 3, + HardwareBuffer.USAGE_GPU_SAMPLED_IMAGE | HardwareBuffer.USAGE_GPU_COLOR_OUTPUT); + mRenderer.setSurface(reader.getSurface()); + mRenderer.setLightSourceAlpha(0.0f, 1.0f); + mRenderer.setLightSourceGeometry(100 / 2f, 0f, 800.0f, 20.0f); + mContent.setLeftTopRightBottom(0, 0, 100, 100); + + Rect childRect = new Rect(25, 25, 65, 65); + RenderNode childNode = new RenderNode("shadowCaster"); + childNode.setLeftTopRightBottom(childRect.left, childRect.top, + childRect.right, childRect.bottom); + Outline outline = new Outline(); + outline.setRect(new Rect(0, 0, childRect.width(), childRect.height())); + outline.setAlpha(1f); + childNode.setOutline(outline); + { + Canvas canvas = childNode.startRecording(); + canvas.drawColor(Color.BLUE); + } + childNode.endRecording(); + childNode.setElevation(20f); + + { + Canvas canvas = mContent.startRecording(); + canvas.drawColor(Color.WHITE); + canvas.enableZ(); + canvas.drawRenderNode(childNode); + canvas.disableZ(); + } + mContent.endRecording(); + mRenderer.setContentRoot(mContent); + mRenderer.createRenderRequest() + .setWaitForPresent(true) + .syncAndDraw(); + Image image = reader.acquireNextImage(); + Bitmap bitmap = Bitmap.wrapHardwareBuffer(image.getHardwareBuffer(), + ColorSpace.get(ColorSpace.Named.SRGB)); + mImageView.setImageBitmap(bitmap); + image.close(); + } +} diff --git a/tests/Internal/src/com/android/internal/colorextraction/ColorExtractorTest.java b/tests/Internal/src/com/android/internal/colorextraction/ColorExtractorTest.java index cb6a83d2644b..39608a40b416 100644 --- a/tests/Internal/src/com/android/internal/colorextraction/ColorExtractorTest.java +++ b/tests/Internal/src/com/android/internal/colorextraction/ColorExtractorTest.java @@ -56,7 +56,7 @@ public class ColorExtractorTest { @Test public void ColorExtractor_extractWhenInitialized() { ExtractionType type = mock(Tonal.class); - new ColorExtractor(mContext, type); + new ColorExtractor(mContext, type, true); // 1 for lock and 1 for system verify(type, times(2)) .extractInto(any(), any(), any(), any()); @@ -83,7 +83,7 @@ public class ColorExtractorTest { outGradientColorsDark.set(colorsExpectedDark); outGradientColorsExtraDark.set(colorsExpectedExtraDark); }; - ColorExtractor extractor = new ColorExtractor(mContext, type); + ColorExtractor extractor = new ColorExtractor(mContext, type, true); GradientColors colors = extractor.getColors(WallpaperManager.FLAG_SYSTEM, ColorExtractor.TYPE_NORMAL); @@ -98,7 +98,7 @@ public class ColorExtractorTest { public void addOnColorsChangedListener_invokesListener() { ColorExtractor.OnColorsChangedListener mockedListeners = mock(ColorExtractor.OnColorsChangedListener.class); - ColorExtractor extractor = new ColorExtractor(mContext, new Tonal(mContext)); + ColorExtractor extractor = new ColorExtractor(mContext, new Tonal(mContext), true); extractor.addOnColorsChangedListener(mockedListeners); extractor.onColorsChanged(new WallpaperColors(Color.valueOf(Color.RED), null, null), diff --git a/tests/JankBench/Android.bp b/tests/JankBench/Android.bp new file mode 100644 index 000000000000..166639d2e7db --- /dev/null +++ b/tests/JankBench/Android.bp @@ -0,0 +1,21 @@ +android_test { + name: "JankBench", + manifest: "app/src/main/AndroidManifest.xml", + sdk_version: "current", + // omit gradle 'build' dir + srcs: ["app/src/main/java/**/*.java"], + // use appcompat/support lib from the tree, so improvements/ + // regressions are reflected in test data + resource_dirs: ["app/src/main/res"], + static_libs: [ + "com.google.android.material_material", + "androidx.legacy_legacy-support-v4", + "androidx.appcompat_appcompat", + "androidx.cardview_cardview", + "androidx.recyclerview_recyclerview", + "androidx.leanback_leanback", + "apache-commons-math", + "junit", + ], + test_suites: ["device-tests"], +} diff --git a/tests/JankBench/Android.mk b/tests/JankBench/Android.mk deleted file mode 100644 index 89c21b7fb605..000000000000 --- a/tests/JankBench/Android.mk +++ /dev/null @@ -1,38 +0,0 @@ -LOCAL_PATH:= $(call my-dir) -include $(CLEAR_VARS) - -LOCAL_MODULE_TAGS := tests - -LOCAL_MANIFEST_FILE := app/src/main/AndroidManifest.xml - -LOCAL_SDK_VERSION := current - -LOCAL_USE_AAPT2 := true - -# omit gradle 'build' dir -LOCAL_SRC_FILES := $(call all-java-files-under,app/src/main/java) - -# use appcompat/support lib from the tree, so improvements/ -# regressions are reflected in test data -LOCAL_RESOURCE_DIR := \ - $(LOCAL_PATH)/app/src/main/res \ - - -LOCAL_STATIC_ANDROID_LIBRARIES := \ - com.google.android.material_material \ - androidx.legacy_legacy-support-v4 \ - androidx.appcompat_appcompat \ - androidx.cardview_cardview \ - androidx.recyclerview_recyclerview \ - androidx.leanback_leanback \ - -LOCAL_STATIC_JAVA_LIBRARIES := \ - apache-commons-math \ - junit - - -LOCAL_PACKAGE_NAME := JankBench - -LOCAL_COMPATIBILITY_SUITE := device-tests - -include $(BUILD_PACKAGE) diff --git a/tests/JankBench/app/src/main/jni/Android.bp.converted b/tests/JankBench/app/src/main/jni/Android.bp.converted new file mode 100644 index 000000000000..9fecf1599fd9 --- /dev/null +++ b/tests/JankBench/app/src/main/jni/Android.bp.converted @@ -0,0 +1,27 @@ +// Copyright (C) 2015 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. + +cc_library_shared { + name: "libnativebench", + cflags: [ + "-Wno-unused-parameter", + "-Wno-unused-variable", + ], + srcs: [ + "Bench.cpp", + "WorkerPool.cpp", + "test.cpp", + ], + host_ldlibs: ["-llog"], +} diff --git a/tests/JankBench/app/src/main/jni/Android.mk b/tests/JankBench/app/src/main/jni/Android.mk deleted file mode 100644 index 8ba874de0e8a..000000000000 --- a/tests/JankBench/app/src/main/jni/Android.mk +++ /dev/null @@ -1,31 +0,0 @@ -# Copyright (C) 2015 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. - -LOCAL_PATH := $(call my-dir) -LOCAL_SDK_VERSION := 26 - -include $(CLEAR_VARS) - -LOCAL_CFLAGS = -Wno-unused-parameter - -LOCAL_MODULE:= libnativebench - -LOCAL_SRC_FILES := \ - Bench.cpp \ - WorkerPool.cpp \ - test.cpp - -LOCAL_LDLIBS := -llog - -include $(BUILD_SHARED_LIBRARY) diff --git a/tests/RollbackTest/Android.mk b/tests/RollbackTest/Android.mk index 40d4eff53577..0967ad3767c6 100644 --- a/tests/RollbackTest/Android.mk +++ b/tests/RollbackTest/Android.mk @@ -71,7 +71,7 @@ ROLLBACK_TEST_APP_BV2 := $(LOCAL_INSTALLED_MODULE) # RollbackTest include $(CLEAR_VARS) -LOCAL_SRC_FILES := $(call all-java-files-under, src) +LOCAL_SRC_FILES := $(call all-java-files-under, RollbackTest/src) LOCAL_PACKAGE_NAME := RollbackTest LOCAL_MODULE_TAGS := tests LOCAL_STATIC_JAVA_LIBRARIES := android-support-test @@ -84,10 +84,21 @@ LOCAL_JAVA_RESOURCE_FILES := \ $(ROLLBACK_TEST_APP_BV1) \ $(ROLLBACK_TEST_APP_BV2) \ $(ROLLBACK_TEST_APEX_V2) +LOCAL_MANIFEST_FILE := RollbackTest/AndroidManifest.xml LOCAL_SDK_VERSION := system_current LOCAL_TEST_CONFIG := RollbackTest.xml include $(BUILD_PACKAGE) +# StagedRollbackTest +include $(CLEAR_VARS) +LOCAL_SRC_FILES := $(call all-java-files-under, StagedRollbackTest/src) +LOCAL_MODULE := StagedRollbackTest +LOCAL_MODULE_TAGS := tests +LOCAL_JAVA_LIBRARIES := tradefed +LOCAL_COMPATIBILITY_SUITE := general-tests +LOCAL_TEST_CONFIG := StagedRollbackTest.xml +include $(BUILD_HOST_JAVA_LIBRARY) + # Clean up local variables ROLLBACK_TEST_APP_AV1 := ROLLBACK_TEST_APP_AV2 := diff --git a/tests/RollbackTest/README.txt b/tests/RollbackTest/README.txt new file mode 100644 index 000000000000..c0b718a3e2c1 --- /dev/null +++ b/tests/RollbackTest/README.txt @@ -0,0 +1,23 @@ +This directory contains a test for the rollback manager service. + +Directory structure +=================== +RollbackTest + - device driven test for rollbacks not involving staged rollbacks. + +StagedRollbackTest + - device driven test for staged rollbacks. + +TestApp + - source for dummy apks used in testing. + +TestApex + - source for dummy apex modules used in testing. + +Running the tests +================= + +You can manually run the tests as follows: + + atest RollbackTest + atest StagedRollbackTest diff --git a/tests/RollbackTest/RollbackTest.xml b/tests/RollbackTest/RollbackTest.xml index adbad56cd934..ac39f853656a 100644 --- a/tests/RollbackTest/RollbackTest.xml +++ b/tests/RollbackTest/RollbackTest.xml @@ -21,5 +21,9 @@ <test class="com.android.tradefed.testtype.AndroidJUnitTest" > <option name="package" value="com.android.tests.rollback" /> <option name="runner" value="android.support.test.runner.AndroidJUnitRunner" /> + + <!-- Exclude the StagedRollbackTest tests, which needs to be specially + driven from the StagedRollbackTest host test --> + <option name="exclude-filter" value="com.android.tests.rollback.StagedRollbackTest" /> </test> </configuration> diff --git a/tests/RollbackTest/AndroidManifest.xml b/tests/RollbackTest/RollbackTest/AndroidManifest.xml index e57a768ad1b5..e57a768ad1b5 100644 --- a/tests/RollbackTest/AndroidManifest.xml +++ b/tests/RollbackTest/RollbackTest/AndroidManifest.xml diff --git a/tests/RollbackTest/src/com/android/tests/rollback/LocalIntentSender.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/LocalIntentSender.java index ddcf1dabcafc..ddcf1dabcafc 100644 --- a/tests/RollbackTest/src/com/android/tests/rollback/LocalIntentSender.java +++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/LocalIntentSender.java diff --git a/tests/RollbackTest/src/com/android/tests/rollback/RollbackBroadcastReceiver.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackBroadcastReceiver.java index e10f866c899f..e10f866c899f 100644 --- a/tests/RollbackTest/src/com/android/tests/rollback/RollbackBroadcastReceiver.java +++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackBroadcastReceiver.java diff --git a/tests/RollbackTest/src/com/android/tests/rollback/RollbackTest.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java index f07ae9f65b1b..f3edf09c5e95 100644 --- a/tests/RollbackTest/src/com/android/tests/rollback/RollbackTest.java +++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java @@ -16,6 +16,10 @@ package com.android.tests.rollback; +import static com.android.tests.rollback.RollbackTestUtils.assertPackageRollbackInfoEquals; +import static com.android.tests.rollback.RollbackTestUtils.assertRollbackInfoEquals; +import static com.android.tests.rollback.RollbackTestUtils.getUniqueRollbackInfoForPackage; + import android.Manifest; import android.app.ActivityManager; import android.content.BroadcastReceiver; @@ -24,7 +28,6 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.VersionedPackage; -import android.content.rollback.PackageRollbackInfo; import android.content.rollback.RollbackInfo; import android.content.rollback.RollbackManager; import android.os.Handler; @@ -42,7 +45,6 @@ import org.junit.runner.RunWith; import org.junit.runners.JUnit4; import java.util.Collections; -import java.util.List; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.SynchronousQueue; @@ -617,17 +619,6 @@ public class RollbackTest { } } - // Helper function to test the value of a PackageRollbackInfo - private void assertPackageRollbackInfoEquals(String packageName, - long versionRolledBackFrom, long versionRolledBackTo, - PackageRollbackInfo info) { - assertEquals(packageName, info.getPackageName()); - assertEquals(packageName, info.getVersionRolledBackFrom().getPackageName()); - assertEquals(versionRolledBackFrom, info.getVersionRolledBackFrom().getLongVersionCode()); - assertEquals(packageName, info.getVersionRolledBackTo().getPackageName()); - assertEquals(versionRolledBackTo, info.getVersionRolledBackTo().getLongVersionCode()); - } - /** * Test bad update automatic rollback. */ @@ -713,23 +704,6 @@ public class RollbackTest { } } - // Helper function to test the value of a RollbackInfo with single package - private void assertRollbackInfoEquals(String packageName, - long versionRolledBackFrom, long versionRolledBackTo, - RollbackInfo info, VersionedPackage... causePackages) { - assertNotNull(info); - assertEquals(1, info.getPackages().size()); - assertPackageRollbackInfoEquals(packageName, versionRolledBackFrom, versionRolledBackTo, - info.getPackages().get(0)); - assertEquals(causePackages.length, info.getCausePackages().size()); - for (int i = 0; i < causePackages.length; ++i) { - assertEquals(causePackages[i].getPackageName(), - info.getCausePackages().get(i).getPackageName()); - assertEquals(causePackages[i].getLongVersionCode(), - info.getCausePackages().get(i).getLongVersionCode()); - } - } - // Helper function to test that the given rollback info is a rollback for // the atomic set {A2, B2} -> {A1, B1}. private void assertRollbackInfoForAandB(RollbackInfo rollback) { @@ -743,23 +717,4 @@ public class RollbackTest { assertPackageRollbackInfoEquals(TEST_APP_A, 2, 1, rollback.getPackages().get(1)); } } - - // Helper function to return the RollbackInfo with a given package in the - // list of rollbacks. Throws an assertion failure if there is more than - // one such rollback info. Returns null if there are no such rollback - // infos. - private RollbackInfo getUniqueRollbackInfoForPackage(List<RollbackInfo> rollbacks, - String packageName) { - RollbackInfo found = null; - for (RollbackInfo rollback : rollbacks) { - for (PackageRollbackInfo info : rollback.getPackages()) { - if (packageName.equals(info.getPackageName())) { - assertNull(found); - found = rollback; - break; - } - } - } - return found; - } } diff --git a/tests/RollbackTest/src/com/android/tests/rollback/RollbackTestUtils.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTestUtils.java index 60c7a59d9456..280ee1d1c576 100644 --- a/tests/RollbackTest/src/com/android/tests/rollback/RollbackTestUtils.java +++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTestUtils.java @@ -16,19 +16,31 @@ package com.android.tests.rollback; +import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; +import android.content.IntentFilter; import android.content.pm.PackageInfo; import android.content.pm.PackageInstaller; import android.content.pm.PackageManager; import android.content.pm.VersionedPackage; +import android.content.rollback.PackageRollbackInfo; +import android.content.rollback.RollbackInfo; import android.content.rollback.RollbackManager; import android.support.test.InstrumentationRegistry; +import android.util.Log; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Arrays; +import java.util.List; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; /** * Utilities to facilitate testing rollbacks. @@ -157,20 +169,28 @@ class RollbackTestUtils { /** * Installs the apks with the given resource names as an atomic set. + * <p> + * In case of staged installs, this function will return succesfully after + * the staged install has been committed and is ready for the device to + * reboot. * + * @param staged if the rollback should be staged. * @param enableRollback if rollback should be enabled. * @param resourceNames names of the class loader resource for the apks to * install. * @throws AssertionError if the installation fails. */ - static void installMultiPackage(boolean enableRollback, String... resourceNames) - throws InterruptedException, IOException { + private static void install(boolean staged, boolean enableRollback, + String... resourceNames) throws InterruptedException, IOException { Context context = InstrumentationRegistry.getContext(); PackageInstaller packageInstaller = context.getPackageManager().getPackageInstaller(); PackageInstaller.SessionParams multiPackageParams = new PackageInstaller.SessionParams( PackageInstaller.SessionParams.MODE_FULL_INSTALL); multiPackageParams.setMultiPackage(); + if (staged) { + multiPackageParams.setStaged(); + } if (enableRollback) { // TODO: Do we set this on the parent params, the child params, or // both? @@ -183,6 +203,9 @@ class RollbackTestUtils { PackageInstaller.Session session = null; PackageInstaller.SessionParams params = new PackageInstaller.SessionParams( PackageInstaller.SessionParams.MODE_FULL_INSTALL); + if (staged) { + params.setStaged(); + } if (enableRollback) { params.setEnableRollback(); } @@ -204,6 +227,36 @@ class RollbackTestUtils { // Commit the session (this will start the installation workflow). multiPackage.commit(LocalIntentSender.getIntentSender()); assertStatusSuccess(LocalIntentSender.getIntentSenderResult()); + + if (staged) { + waitForSessionReady(multiPackageId); + } + } + + /** + * Installs the apks with the given resource names as an atomic set. + * + * @param enableRollback if rollback should be enabled. + * @param resourceNames names of the class loader resource for the apks to + * install. + * @throws AssertionError if the installation fails. + */ + static void installMultiPackage(boolean enableRollback, String... resourceNames) + throws InterruptedException, IOException { + install(false, enableRollback, resourceNames); + } + + /** + * Installs the apks with the given resource names as a staged atomic set. + * + * @param enableRollback if rollback should be enabled. + * @param resourceNames names of the class loader resource for the apks to + * install. + * @throws AssertionError if the installation fails. + */ + static void installStaged(boolean enableRollback, String... resourceNames) + throws InterruptedException, IOException { + install(true, enableRollback, resourceNames); } static void adoptShellPermissionIdentity(String... permissions) { @@ -219,4 +272,104 @@ class RollbackTestUtils { .getUiAutomation() .dropShellPermissionIdentity(); } + + /** + * Returns the RollbackInfo with a given package in the list of rollbacks. + * Throws an assertion failure if there is more than one such rollback + * info. Returns null if there are no such rollback infos. + */ + static RollbackInfo getUniqueRollbackInfoForPackage(List<RollbackInfo> rollbacks, + String packageName) { + RollbackInfo found = null; + for (RollbackInfo rollback : rollbacks) { + for (PackageRollbackInfo info : rollback.getPackages()) { + if (packageName.equals(info.getPackageName())) { + assertNull(found); + found = rollback; + break; + } + } + } + return found; + } + + /** + * Asserts that the given PackageRollbackInfo has the expected package + * name and versions. + */ + static void assertPackageRollbackInfoEquals(String packageName, + long versionRolledBackFrom, long versionRolledBackTo, + PackageRollbackInfo info) { + assertEquals(packageName, info.getPackageName()); + assertEquals(packageName, info.getVersionRolledBackFrom().getPackageName()); + assertEquals(versionRolledBackFrom, info.getVersionRolledBackFrom().getLongVersionCode()); + assertEquals(packageName, info.getVersionRolledBackTo().getPackageName()); + assertEquals(versionRolledBackTo, info.getVersionRolledBackTo().getLongVersionCode()); + } + + /** + * Asserts that the given RollbackInfo has a single package with expected + * package name and versions. + */ + static void assertRollbackInfoEquals(String packageName, + long versionRolledBackFrom, long versionRolledBackTo, + RollbackInfo info, VersionedPackage... causePackages) { + assertNotNull(info); + assertEquals(1, info.getPackages().size()); + assertPackageRollbackInfoEquals(packageName, versionRolledBackFrom, versionRolledBackTo, + info.getPackages().get(0)); + assertEquals(causePackages.length, info.getCausePackages().size()); + for (int i = 0; i < causePackages.length; ++i) { + assertEquals(causePackages[i].getPackageName(), + info.getCausePackages().get(i).getPackageName()); + assertEquals(causePackages[i].getLongVersionCode(), + info.getCausePackages().get(i).getLongVersionCode()); + } + } + + /** + * Waits for the given session to be marked as ready. + * Throws an assertion if the session fails. + */ + static void waitForSessionReady(int sessionId) { + BlockingQueue<PackageInstaller.SessionInfo> sessionStatus = new LinkedBlockingQueue<>(); + BroadcastReceiver sessionUpdatedReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + PackageInstaller.SessionInfo info = + intent.getParcelableExtra(PackageInstaller.EXTRA_SESSION); + if (info != null && info.getSessionId() == sessionId) { + if (info.isSessionReady() || info.isSessionFailed()) { + try { + sessionStatus.put(info); + } catch (InterruptedException e) { + Log.e(TAG, "Failed to put session info.", e); + } + } + } + } + }; + IntentFilter sessionUpdatedFilter = + new IntentFilter(PackageInstaller.ACTION_SESSION_UPDATED); + + Context context = InstrumentationRegistry.getContext(); + context.registerReceiver(sessionUpdatedReceiver, sessionUpdatedFilter); + + PackageInstaller installer = context.getPackageManager().getPackageInstaller(); + PackageInstaller.SessionInfo info = installer.getSessionInfo(sessionId); + + try { + if (info.isSessionReady() || info.isSessionFailed()) { + sessionStatus.put(info); + } + + info = sessionStatus.take(); + context.unregisterReceiver(sessionUpdatedReceiver); + if (info.isSessionFailed()) { + throw new AssertionError(info.getStagedSessionErrorMessage()); + } + } catch (InterruptedException e) { + throw new AssertionError(e); + } + } } diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java new file mode 100644 index 000000000000..297bf869278f --- /dev/null +++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java @@ -0,0 +1,131 @@ +/* + * 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.tests.rollback; + +import static com.android.tests.rollback.RollbackTestUtils.assertRollbackInfoEquals; +import static com.android.tests.rollback.RollbackTestUtils.getUniqueRollbackInfoForPackage; + +import android.Manifest; +import android.content.rollback.RollbackInfo; +import android.content.rollback.RollbackManager; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertTrue; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** + * Tests for rollback of staged installs. + * <p> + * Note: These tests require reboot in between test phases. They are run + * specially so that the testFooEnableRollback, testFooCommitRollback, and + * testFooConfirmRollback phases of each test are run in order with reboots in + * between them. + */ +@RunWith(JUnit4.class) +public class StagedRollbackTest { + + private static final String TAG = "RollbackTest"; + private static final String TEST_APP_A = "com.android.tests.rollback.testapp.A"; + + /** + * Adopts common shell permissions needed for rollback tests. + */ + @Before + public void adoptShellPermissions() { + RollbackTestUtils.adoptShellPermissionIdentity( + Manifest.permission.INSTALL_PACKAGES, + Manifest.permission.DELETE_PACKAGES, + Manifest.permission.MANAGE_ROLLBACKS); + } + + /** + * Drops shell permissions needed for rollback tests. + */ + @After + public void dropShellPermissions() { + RollbackTestUtils.dropShellPermissionIdentity(); + } + + + /** + * Test basic rollbacks. Enable rollback phase. + */ + @Test + public void testBasicEnableRollback() throws Exception { + RollbackTestUtils.uninstall(TEST_APP_A); + assertEquals(-1, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); + + RollbackTestUtils.install("RollbackTestAppAv1.apk", false); + assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); + + RollbackTestUtils.installStaged(true, "RollbackTestAppAv2.apk"); + + // At this point, the host test driver will reboot the device and run + // testBasicCommitRollback(). + } + + /** + * Test basic rollbacks. Commit rollback phase. + */ + @Test + public void testBasicCommitRollback() throws Exception { + assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); + + RollbackManager rm = RollbackTestUtils.getRollbackManager(); + RollbackInfo rollback = getUniqueRollbackInfoForPackage( + rm.getAvailableRollbacks(), TEST_APP_A); + assertRollbackInfoEquals(TEST_APP_A, 2, 1, rollback); + assertTrue(rollback.isStaged()); + + RollbackTestUtils.rollback(rollback.getRollbackId()); + + rollback = getUniqueRollbackInfoForPackage( + rm.getRecentlyCommittedRollbacks(), TEST_APP_A); + assertRollbackInfoEquals(TEST_APP_A, 2, 1, rollback); + assertTrue(rollback.isStaged()); + assertNotEquals(-1, rollback.getCommittedSessionId()); + + RollbackTestUtils.waitForSessionReady(rollback.getCommittedSessionId()); + + // The app should not be rolled back until after reboot. + assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); + + // At this point, the host test driver will reboot the device and run + // testBasicConfirmRollback(). + } + + /** + * Test basic rollbacks. Confirm rollback phase. + */ + @Test + public void testBasicConfirmRollback() throws Exception { + assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); + + RollbackManager rm = RollbackTestUtils.getRollbackManager(); + RollbackInfo rollback = getUniqueRollbackInfoForPackage( + rm.getRecentlyCommittedRollbacks(), TEST_APP_A); + assertRollbackInfoEquals(TEST_APP_A, 2, 1, rollback); + assertTrue(rollback.isStaged()); + assertNotEquals(-1, rollback.getCommittedSessionId()); + } +} diff --git a/tests/RollbackTest/StagedRollbackTest.xml b/tests/RollbackTest/StagedRollbackTest.xml new file mode 100644 index 000000000000..2750d3765c20 --- /dev/null +++ b/tests/RollbackTest/StagedRollbackTest.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- 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. +--> +<configuration description="Runs the staged rollback tests"> + <option name="test-suite-tag" value="StagedRollbackTest" /> + <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller"> + <option name="cleanup-apks" value="true" /> + <option name="test-file-name" value="RollbackTest.apk" /> + </target_preparer> + <test class="com.android.tradefed.testtype.HostTest" > + <option name="class" value="com.android.tests.rollback.host.StagedRollbackTest" /> + </test> +</configuration> diff --git a/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java b/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java new file mode 100644 index 000000000000..6cb0dd091392 --- /dev/null +++ b/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java @@ -0,0 +1,56 @@ +/* + * 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.tests.rollback.host; + +import static org.junit.Assert.assertTrue; + +import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; +import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test; + +import org.junit.Test; +import org.junit.runner.RunWith; + +/** + * Runs the staged rollback tests. + */ +@RunWith(DeviceJUnit4ClassRunner.class) +public class StagedRollbackTest extends BaseHostJUnit4Test { + + /** + * Runs the given phase of a test by calling into the device. + * Throws an exception if the test phase fails. + * <p> + * For example, <code>runPhase("testBasicEnableRollback");</code> + */ + private void runPhase(String phase) throws Exception { + assertTrue(runDeviceTests("com.android.tests.rollback", + "com.android.tests.rollback.StagedRollbackTest", + phase)); + } + + /** + * Tests staged rollbacks. + */ + @Test + public void testBasic() throws Exception { + runPhase("testBasicEnableRollback"); + getDevice().reboot(); + runPhase("testBasicCommitRollback"); + getDevice().reboot(); + runPhase("testBasicConfirmRollback"); + } +} diff --git a/tests/RollbackTest/TEST_MAPPING b/tests/RollbackTest/TEST_MAPPING index c1d95ac85c23..6be93a0a199b 100644 --- a/tests/RollbackTest/TEST_MAPPING +++ b/tests/RollbackTest/TEST_MAPPING @@ -2,6 +2,9 @@ "presubmit": [ { "name": "RollbackTest" + }, + { + "name": "StagedRollbackTest" } ] } diff --git a/tests/UiBench/Android.bp b/tests/UiBench/Android.bp new file mode 100644 index 000000000000..e0608e288459 --- /dev/null +++ b/tests/UiBench/Android.bp @@ -0,0 +1,19 @@ +android_test { + name: "UiBench", + sdk_version: "current", + min_sdk_version: "21", + // omit gradle 'build' dir + srcs: ["src/**/*.java"], + // use appcompat/support lib from the tree, so improvements/ + // regressions are reflected in test data + resource_dirs: ["res"], + static_libs: [ + "com.google.android.material_material", + "androidx.legacy_legacy-support-v4", + "androidx.appcompat_appcompat", + "androidx.cardview_cardview", + "androidx.recyclerview_recyclerview", + "androidx.leanback_leanback", + ], + test_suites: ["device-tests"], +} diff --git a/tests/UiBench/Android.mk b/tests/UiBench/Android.mk deleted file mode 100644 index 608bf2f226f5..000000000000 --- a/tests/UiBench/Android.mk +++ /dev/null @@ -1,29 +0,0 @@ -LOCAL_PATH:= $(call my-dir) -include $(CLEAR_VARS) - -LOCAL_MODULE_TAGS := tests -LOCAL_SDK_VERSION := current -LOCAL_MIN_SDK_VERSION := 21 - -# omit gradle 'build' dir -LOCAL_SRC_FILES := $(call all-java-files-under,src) - -# use appcompat/support lib from the tree, so improvements/ -# regressions are reflected in test data -LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res - -LOCAL_USE_AAPT2 := true - -LOCAL_STATIC_ANDROID_LIBRARIES := \ - com.google.android.material_material \ - androidx.legacy_legacy-support-v4 \ - androidx.appcompat_appcompat \ - androidx.cardview_cardview \ - androidx.recyclerview_recyclerview \ - androidx.leanback_leanback - -LOCAL_PACKAGE_NAME := UiBench - -LOCAL_COMPATIBILITY_SUITE := device-tests - -include $(BUILD_PACKAGE) diff --git a/tests/UsageStatsTest/Android.bp b/tests/UsageStatsTest/Android.bp new file mode 100644 index 000000000000..0808b05ec053 --- /dev/null +++ b/tests/UsageStatsTest/Android.bp @@ -0,0 +1,8 @@ +android_test { + name: "UsageStatsTest", + // Only compile source java files in this apk. + srcs: ["src/**/*.java"], + static_libs: ["androidx.legacy_legacy-support-v4"], + certificate: "platform", + platform_apis: true, +} diff --git a/tests/UsageStatsTest/Android.mk b/tests/UsageStatsTest/Android.mk deleted file mode 100644 index 5eed38c86657..000000000000 --- a/tests/UsageStatsTest/Android.mk +++ /dev/null @@ -1,17 +0,0 @@ -LOCAL_PATH:= $(call my-dir) -include $(CLEAR_VARS) - -LOCAL_MODULE_TAGS := tests - -# Only compile source java files in this apk. -LOCAL_SRC_FILES := $(call all-java-files-under, src) - -LOCAL_USE_AAPT2 := true -LOCAL_STATIC_ANDROID_LIBRARIES := androidx.legacy_legacy-support-v4 - -LOCAL_CERTIFICATE := platform - -LOCAL_PACKAGE_NAME := UsageStatsTest -LOCAL_PRIVATE_PLATFORM_APIS := true - -include $(BUILD_PACKAGE) diff --git a/tests/libs-permissions/Android.bp b/tests/libs-permissions/Android.bp new file mode 100644 index 000000000000..c7c4b10a8405 --- /dev/null +++ b/tests/libs-permissions/Android.bp @@ -0,0 +1,29 @@ +java_library { + name: "com.android.test.libs.product", + installable: true, + product_specific: true, + srcs: ["product/java/**/*.java"], + required: ["com.android.test.libs.product.xml"], +} + +prebuilt_etc { + name: "com.android.test.libs.product.xml", + src: "product/com.android.test.libs.product.xml", + sub_dir: "permissions", + product_specific: true, +} + +java_library { + name: "com.android.test.libs.product_services", + installable: true, + product_services_specific: true, + srcs: ["product_services/java/**/*.java"], + required: ["com.android.test.libs.product_services.xml"], +} + +prebuilt_etc { + name: "com.android.test.libs.product_services.xml", + src: "product_services/com.android.test.libs.product_services.xml", + sub_dir: "permissions", + product_services_specific: true, +} diff --git a/tests/libs-permissions/Android.mk b/tests/libs-permissions/Android.mk deleted file mode 100644 index f4250c8b4e97..000000000000 --- a/tests/libs-permissions/Android.mk +++ /dev/null @@ -1,29 +0,0 @@ -LOCAL_PATH:= $(call my-dir) - -include $(CLEAR_VARS) -LOCAL_MODULE := com.android.test.libs.product -LOCAL_PRODUCT_MODULE := true -LOCAL_SRC_FILES := $(call all-java-files-under, product/java) -LOCAL_REQUIRED_MODULES := com.android.test.libs.product.xml -include $(BUILD_JAVA_LIBRARY) - -include $(CLEAR_VARS) -LOCAL_MODULE := com.android.test.libs.product.xml -LOCAL_MODULE_CLASS := ETC -LOCAL_MODULE_PATH := $(TARGET_OUT_PRODUCT_ETC)/permissions -LOCAL_SRC_FILES:= product/com.android.test.libs.product.xml -include $(BUILD_PREBUILT) - -include $(CLEAR_VARS) -LOCAL_MODULE := com.android.test.libs.product_services -LOCAL_PRODUCT_SERVICES_MODULE := true -LOCAL_SRC_FILES := $(call all-java-files-under, product_services/java) -LOCAL_REQUIRED_MODULES := com.android.test.libs.product_services.xml -include $(BUILD_JAVA_LIBRARY) - -include $(CLEAR_VARS) -LOCAL_MODULE := com.android.test.libs.product_services.xml -LOCAL_MODULE_CLASS := ETC -LOCAL_MODULE_PATH := $(TARGET_OUT_PRODUCT_SERVICES_ETC)/permissions -LOCAL_SRC_FILES:= product_services/com.android.test.libs.product_services.xml -include $(BUILD_PREBUILT) diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index a7c95c78d05d..a10fb4ee1305 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -20,6 +20,7 @@ import static android.net.ConnectivityManager.CONNECTIVITY_ACTION; import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OFF; import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OPPORTUNISTIC; import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME; +import static android.net.ConnectivityManager.NETID_UNSET; import static android.net.ConnectivityManager.TYPE_ETHERNET; import static android.net.ConnectivityManager.TYPE_MOBILE; import static android.net.ConnectivityManager.TYPE_MOBILE_FOTA; @@ -123,7 +124,7 @@ import android.net.NetworkMisc; import android.net.NetworkParcelable; import android.net.NetworkRequest; import android.net.NetworkSpecifier; -import android.net.NetworkStack; +import android.net.NetworkStackClient; import android.net.NetworkUtils; import android.net.ProxyInfo; import android.net.RouteInfo; @@ -245,7 +246,7 @@ public class ConnectivityServiceTest { @Mock INetworkStatsService mStatsService; @Mock INetworkPolicyManager mNpm; @Mock INetd mMockNetd; - @Mock NetworkStack mNetworkStack; + @Mock NetworkStackClient mNetworkStack; private ArgumentCaptor<String[]> mStringArrayCaptor = ArgumentCaptor.forClass(String[].class); @@ -901,11 +902,14 @@ public class ConnectivityServiceTest { public void setUids(Set<UidRange> uids) { mNetworkCapabilities.setUids(uids); - updateCapabilities(); + updateCapabilities(null /* defaultNetwork */); } @Override public int getNetId() { + if (mMockNetworkAgent == null) { + return NETID_UNSET; + } return mMockNetworkAgent.getNetwork().netId; } @@ -927,12 +931,13 @@ public class ConnectivityServiceTest { } @Override - public void updateCapabilities() { - if (!mConnected) return; - super.updateCapabilities(); - // Because super.updateCapabilities will update the capabilities of the agent but not - // the mock agent, the mock agent needs to know about them. + public NetworkCapabilities updateCapabilities(Network defaultNetwork) { + if (!mConnected) return null; + super.updateCapabilities(defaultNetwork); + // Because super.updateCapabilities will update the capabilities of the agent but + // not the mock agent, the mock agent needs to know about them. copyCapabilitiesToNetworkAgent(); + return new NetworkCapabilities(mNetworkCapabilities); } private void copyCapabilitiesToNetworkAgent() { @@ -1077,6 +1082,11 @@ public class ConnectivityServiceTest { } @Override + protected NetworkStackClient getNetworkStack() { + return mNetworkStack; + } + + @Override public WakeupMessage makeWakeupMessage( Context context, Handler handler, String cmdName, int cmd, Object obj) { return new FakeWakeupMessage(context, handler, cmdName, cmd, 0, 0, obj); @@ -3817,11 +3827,14 @@ public class ConnectivityServiceTest { } @Test - public void testNattSocketKeepalives() throws Exception { + public void testNattSocketKeepalives_SingleThreadExecutor() throws Exception { final ExecutorService executorSingleThread = Executors.newSingleThreadExecutor(); doTestNattSocketKeepalivesWithExecutor(executorSingleThread); executorSingleThread.shutdown(); + } + @Test + public void testNattSocketKeepalives_InlineExecutor() throws Exception { final Executor executorInline = (Runnable r) -> r.run(); doTestNattSocketKeepalivesWithExecutor(executorInline); } @@ -3963,6 +3976,7 @@ public class ConnectivityServiceTest { testSocket2.close(); mWiFiNetworkAgent.disconnect(); + waitFor(mWiFiNetworkAgent.getDisconnectedCV()); } @Test @@ -4686,6 +4700,7 @@ public class ConnectivityServiceTest { vpnNetworkAgent.connect(false); mMockVpn.connect(); + mMockVpn.setUnderlyingNetworks(new Network[0]); genericNetworkCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent); genericNotVpnNetworkCallback.assertNoCallback(); @@ -4718,6 +4733,7 @@ public class ConnectivityServiceTest { ranges.add(new UidRange(uid, uid)); mMockVpn.setUids(ranges); + vpnNetworkAgent.setUids(ranges); genericNetworkCallback.expectAvailableCallbacksValidated(vpnNetworkAgent); genericNotVpnNetworkCallback.assertNoCallback(); @@ -4751,12 +4767,11 @@ public class ConnectivityServiceTest { } @Test - public void testVpnWithAndWithoutInternet() { + public void testVpnWithoutInternet() { final int uid = Process.myUid(); final TestNetworkCallback defaultCallback = new TestNetworkCallback(); mCm.registerDefaultNetworkCallback(defaultCallback); - defaultCallback.assertNoCallback(); mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); mWiFiNetworkAgent.connect(true); @@ -4778,11 +4793,30 @@ public class ConnectivityServiceTest { vpnNetworkAgent.disconnect(); defaultCallback.assertNoCallback(); - vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN); + mCm.unregisterNetworkCallback(defaultCallback); + } + + @Test + public void testVpnWithInternet() { + final int uid = Process.myUid(); + + final TestNetworkCallback defaultCallback = new TestNetworkCallback(); + mCm.registerDefaultNetworkCallback(defaultCallback); + + mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); + mWiFiNetworkAgent.connect(true); + + defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent); + assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); + + MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN); + final ArraySet<UidRange> ranges = new ArraySet<>(); + ranges.add(new UidRange(uid, uid)); mMockVpn.setNetworkAgent(vpnNetworkAgent); mMockVpn.setUids(ranges); vpnNetworkAgent.connect(true /* validated */, true /* hasInternet */); mMockVpn.connect(); + defaultCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent); assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); @@ -4790,14 +4824,6 @@ public class ConnectivityServiceTest { defaultCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent); defaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent); - vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN); - ranges.clear(); - mMockVpn.setNetworkAgent(vpnNetworkAgent); - mMockVpn.setUids(ranges); - vpnNetworkAgent.connect(false /* validated */, true /* hasInternet */); - mMockVpn.connect(); - defaultCallback.assertNoCallback(); - mCm.unregisterNetworkCallback(defaultCallback); } @@ -4900,6 +4926,70 @@ public class ConnectivityServiceTest { } @Test + public void testNullUnderlyingNetworks() { + final int uid = Process.myUid(); + + final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback(); + final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder() + .removeCapability(NET_CAPABILITY_NOT_VPN) + .addTransportType(TRANSPORT_VPN) + .build(); + NetworkCapabilities nc; + mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback); + vpnNetworkCallback.assertNoCallback(); + + final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN); + final ArraySet<UidRange> ranges = new ArraySet<>(); + ranges.add(new UidRange(uid, uid)); + mMockVpn.setNetworkAgent(vpnNetworkAgent); + mMockVpn.connect(); + mMockVpn.setUids(ranges); + vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */); + + vpnNetworkCallback.expectAvailableThenValidatedCallbacks(vpnNetworkAgent); + nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork()); + assertTrue(nc.hasTransport(TRANSPORT_VPN)); + assertFalse(nc.hasTransport(TRANSPORT_CELLULAR)); + assertFalse(nc.hasTransport(TRANSPORT_WIFI)); + // By default, VPN is set to track default network (i.e. its underlying networks is null). + // In case of no default network, VPN is considered metered. + assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED)); + + // Connect to Cell; Cell is the default network. + mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); + mCellNetworkAgent.connect(true); + + vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN) + && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI) + && !caps.hasCapability(NET_CAPABILITY_NOT_METERED), + vpnNetworkAgent); + + // Connect to WiFi; WiFi is the new default. + mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); + mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED); + mWiFiNetworkAgent.connect(true); + + vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN) + && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI) + && caps.hasCapability(NET_CAPABILITY_NOT_METERED), + vpnNetworkAgent); + + // Disconnect Cell. The default network did not change, so there shouldn't be any changes in + // the capabilities. + mCellNetworkAgent.disconnect(); + + // Disconnect wifi too. Now we have no default network. + mWiFiNetworkAgent.disconnect(); + + vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN) + && !caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI) + && !caps.hasCapability(NET_CAPABILITY_NOT_METERED), + vpnNetworkAgent); + + mMockVpn.disconnect(); + } + + @Test public void testNetworkBlockedStatus() { final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback(); final NetworkRequest cellRequest = new NetworkRequest.Builder() diff --git a/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java b/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java index e877a8f7e6c1..5057443eee07 100644 --- a/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java +++ b/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java @@ -38,7 +38,6 @@ import android.net.NetworkCapabilities; import android.net.NetworkFactory; import android.net.NetworkInfo; import android.net.NetworkMisc; -import android.net.NetworkStack; import android.os.INetworkManagementService; import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; @@ -75,16 +74,12 @@ public class LingerMonitorTest { @Mock NetworkMisc mMisc; @Mock NetworkNotificationManager mNotifier; @Mock Resources mResources; - @Mock NetworkStack mNetworkStack; @Before public void setUp() { MockitoAnnotations.initMocks(this); when(mCtx.getResources()).thenReturn(mResources); when(mCtx.getPackageName()).thenReturn("com.android.server.connectivity"); - when(mCtx.getSystemServiceName(NetworkStack.class)) - .thenReturn(Context.NETWORK_STACK_SERVICE); - when(mCtx.getSystemService(Context.NETWORK_STACK_SERVICE)).thenReturn(mNetworkStack); mMonitor = new TestableLingerMonitor(mCtx, mNotifier, HIGH_DAILY_LIMIT, HIGH_RATE_LIMIT); } diff --git a/tests/net/java/com/android/server/connectivity/TetheringTest.java b/tests/net/java/com/android/server/connectivity/TetheringTest.java index a4a735d1a89d..533d7ad2a472 100644 --- a/tests/net/java/com/android/server/connectivity/TetheringTest.java +++ b/tests/net/java/com/android/server/connectivity/TetheringTest.java @@ -195,10 +195,6 @@ public class TetheringTest { } public class MockIpServerDependencies extends IpServer.Dependencies { - MockIpServerDependencies() { - super(null); - } - @Override public RouterAdvertisementDaemon getRouterAdvertisementDaemon( InterfaceParams ifParams) { @@ -266,7 +262,7 @@ public class TetheringTest { } @Override - public IpServer.Dependencies getIpServerDependencies(Context context) { + public IpServer.Dependencies getIpServerDependencies() { return mIpServerDependencies; } diff --git a/tests/net/java/com/android/server/connectivity/VpnTest.java b/tests/net/java/com/android/server/connectivity/VpnTest.java index 46de3d0608ff..b5d1ff9a0298 100644 --- a/tests/net/java/com/android/server/connectivity/VpnTest.java +++ b/tests/net/java/com/android/server/connectivity/VpnTest.java @@ -28,6 +28,7 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING; import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; import static android.net.NetworkCapabilities.TRANSPORT_VPN; import static android.net.NetworkCapabilities.TRANSPORT_WIFI; +import static android.net.RouteInfo.RTN_UNREACHABLE; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -89,6 +90,7 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; import java.net.Inet4Address; +import java.net.Inet6Address; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.Arrays; @@ -566,7 +568,7 @@ public class VpnTest { final NetworkCapabilities caps = new NetworkCapabilities(); - Vpn.updateCapabilities( + Vpn.applyUnderlyingCapabilities( mConnectivityManager, new Network[] {}, caps, false /* isAlwaysMetered */); assertTrue(caps.hasTransport(TRANSPORT_VPN)); assertFalse(caps.hasTransport(TRANSPORT_CELLULAR)); @@ -577,7 +579,7 @@ public class VpnTest { assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_ROAMING)); assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_CONGESTED)); - Vpn.updateCapabilities( + Vpn.applyUnderlyingCapabilities( mConnectivityManager, new Network[] {mobile}, caps, @@ -591,7 +593,7 @@ public class VpnTest { assertFalse(caps.hasCapability(NET_CAPABILITY_NOT_ROAMING)); assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_CONGESTED)); - Vpn.updateCapabilities( + Vpn.applyUnderlyingCapabilities( mConnectivityManager, new Network[] {wifi}, caps, false /* isAlwaysMetered */); assertTrue(caps.hasTransport(TRANSPORT_VPN)); assertFalse(caps.hasTransport(TRANSPORT_CELLULAR)); @@ -602,7 +604,7 @@ public class VpnTest { assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_ROAMING)); assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_CONGESTED)); - Vpn.updateCapabilities( + Vpn.applyUnderlyingCapabilities( mConnectivityManager, new Network[] {wifi}, caps, true /* isAlwaysMetered */); assertTrue(caps.hasTransport(TRANSPORT_VPN)); assertFalse(caps.hasTransport(TRANSPORT_CELLULAR)); @@ -613,7 +615,7 @@ public class VpnTest { assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_ROAMING)); assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_CONGESTED)); - Vpn.updateCapabilities( + Vpn.applyUnderlyingCapabilities( mConnectivityManager, new Network[] {mobile, wifi}, caps, @@ -775,6 +777,16 @@ public class VpnTest { // V4 does not, but V6 has sufficient coverage again lp.addRoute(new RouteInfo(new IpPrefix("::/1"))); assertTrue(Vpn.providesRoutesToMostDestinations(lp)); + + lp.clear(); + // V4-unreachable route should not be treated as sufficient coverage + lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), RTN_UNREACHABLE)); + assertFalse(Vpn.providesRoutesToMostDestinations(lp)); + + lp.clear(); + // V6-unreachable route should not be treated as sufficient coverage + lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), RTN_UNREACHABLE)); + assertFalse(Vpn.providesRoutesToMostDestinations(lp)); } @Test diff --git a/tests/privapp-permissions/Android.bp b/tests/privapp-permissions/Android.bp new file mode 100644 index 000000000000..ca7864f047c7 --- /dev/null +++ b/tests/privapp-permissions/Android.bp @@ -0,0 +1,61 @@ +android_app { + name: "PrivAppPermissionTest", + sdk_version: "current", + privileged: true, + manifest: "system/AndroidManifest.xml", + required: ["privapp-permissions-test.xml"], +} + +prebuilt_etc { + name: "privapp-permissions-test.xml", + src: "system/privapp-permissions-test.xml", + sub_dir: "permissions", +} + +android_app { + name: "VendorPrivAppPermissionTest", + sdk_version: "current", + privileged: true, + manifest: "vendor/AndroidManifest.xml", + vendor: true, + required: ["vendorprivapp-permissions-test.xml"], +} + +prebuilt_etc { + name: "vendorprivapp-permissions-test.xml", + src: "vendor/privapp-permissions-test.xml", + sub_dir: "permissions", + proprietary: true, +} + +android_app { + name: "ProductPrivAppPermissionTest", + sdk_version: "current", + privileged: true, + manifest: "product/AndroidManifest.xml", + product_specific: true, + required: ["productprivapp-permissions-test.xml"], +} + +prebuilt_etc { + name: "productprivapp-permissions-test.xml", + src: "product/privapp-permissions-test.xml", + sub_dir: "permissions", + product_specific: true, +} + +android_app { + name: "ProductServicesPrivAppPermissionTest", + sdk_version: "current", + privileged: true, + manifest: "product_services/AndroidManifest.xml", + product_services_specific: true, + required: ["product_servicesprivapp-permissions-test.xml"], +} + +prebuilt_etc { + name: "product_servicesprivapp-permissions-test.xml", + src: "product_services/privapp-permissions-test.xml", + sub_dir: "permissions", + product_services_specific: true, +} diff --git a/tests/privapp-permissions/Android.mk b/tests/privapp-permissions/Android.mk deleted file mode 100644 index 1149b8a8fe40..000000000000 --- a/tests/privapp-permissions/Android.mk +++ /dev/null @@ -1,64 +0,0 @@ -LOCAL_PATH:= $(call my-dir) - -include $(CLEAR_VARS) -LOCAL_PACKAGE_NAME := PrivAppPermissionTest -LOCAL_SDK_VERSION := current -LOCAL_PRIVILEGED_MODULE := true -LOCAL_MANIFEST_FILE := system/AndroidManifest.xml -LOCAL_REQUIRED_MODULES := privapp-permissions-test.xml -include $(BUILD_PACKAGE) - -include $(CLEAR_VARS) -LOCAL_MODULE := privapp-permissions-test.xml -LOCAL_MODULE_CLASS := ETC -LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/permissions -LOCAL_SRC_FILES:= system/privapp-permissions-test.xml -include $(BUILD_PREBUILT) - -include $(CLEAR_VARS) -LOCAL_PACKAGE_NAME := VendorPrivAppPermissionTest -LOCAL_SDK_VERSION := current -LOCAL_PRIVILEGED_MODULE := true -LOCAL_MANIFEST_FILE := vendor/AndroidManifest.xml -LOCAL_VENDOR_MODULE := true -LOCAL_REQUIRED_MODULES := vendorprivapp-permissions-test.xml -include $(BUILD_PACKAGE) - -include $(CLEAR_VARS) -LOCAL_MODULE := vendorprivapp-permissions-test.xml -LOCAL_MODULE_CLASS := ETC -LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR_ETC)/permissions -LOCAL_SRC_FILES:= vendor/privapp-permissions-test.xml -include $(BUILD_PREBUILT) - -include $(CLEAR_VARS) -LOCAL_PACKAGE_NAME := ProductPrivAppPermissionTest -LOCAL_SDK_VERSION := current -LOCAL_PRIVILEGED_MODULE := true -LOCAL_MANIFEST_FILE := product/AndroidManifest.xml -LOCAL_PRODUCT_MODULE := true -LOCAL_REQUIRED_MODULES := productprivapp-permissions-test.xml -include $(BUILD_PACKAGE) - -include $(CLEAR_VARS) -LOCAL_MODULE := productprivapp-permissions-test.xml -LOCAL_MODULE_CLASS := ETC -LOCAL_MODULE_PATH := $(TARGET_OUT_PRODUCT_ETC)/permissions -LOCAL_SRC_FILES:= product/privapp-permissions-test.xml -include $(BUILD_PREBUILT) - -include $(CLEAR_VARS) -LOCAL_PACKAGE_NAME := ProductServicesPrivAppPermissionTest -LOCAL_SDK_VERSION := current -LOCAL_PRIVILEGED_MODULE := true -LOCAL_MANIFEST_FILE := product_services/AndroidManifest.xml -LOCAL_PRODUCT_SERVICES_MODULE := true -LOCAL_REQUIRED_MODULES := product_servicesprivapp-permissions-test.xml -include $(BUILD_PACKAGE) - -include $(CLEAR_VARS) -LOCAL_MODULE := product_servicesprivapp-permissions-test.xml -LOCAL_MODULE_CLASS := ETC -LOCAL_MODULE_PATH := $(TARGET_OUT_PRODUCT_SERVICES_ETC)/permissions -LOCAL_SRC_FILES:= product_services/privapp-permissions-test.xml -include $(BUILD_PREBUILT) |