Merge "Skip SystemUpdatePolicy Tests"
diff --git a/apps/CameraITS/tests/scene0/test_test_patterns.py b/apps/CameraITS/tests/scene0/test_test_patterns.py
index a1d9cb8..48d464d 100644
--- a/apps/CameraITS/tests/scene0/test_test_patterns.py
+++ b/apps/CameraITS/tests/scene0/test_test_patterns.py
@@ -21,7 +21,7 @@
import numpy as np
NAME = os.path.basename(__file__).split('.')[0]
-PATTERNS = [1, 2]
+CHECKED_PATTERNS = [1, 2] # [SOLID_COLOR, COLOR_BARS]
COLOR_BAR_ORDER = ['WHITE', 'YELLOW', 'CYAN', 'GREEN', 'MAGENTA', 'RED',
'BLUE', 'BLACK']
COLOR_CHECKER = {'BLACK': [0, 0, 0], 'RED': [1, 0, 0], 'GREEN': [0, 1, 0],
@@ -29,6 +29,7 @@
'YELLOW': [1, 1, 0], 'WHITE': [1, 1, 1]}
CH_TOL = 2E-3 # 1/2 DN in [0:1]
LSFR_COEFFS = 0b100010000 # PN9
+REQUIRED_PATTERNS = [2] # [COLOR_BARS]
def check_solid_color(cap, props):
@@ -127,7 +128,7 @@
sens_min, _ = props['android.sensor.info.sensitivityRange']
exposure = min(props['android.sensor.info.exposureTimeRange'])
- for pattern in PATTERNS:
+ for pattern in CHECKED_PATTERNS:
if pattern in avail_patterns:
req = its.objects.manual_capture_request(int(sens_min),
exposure)
@@ -143,7 +144,11 @@
# Check pattern for correctness
assert check_pattern(cap, props, pattern)
else:
- print 'Pattern not in android.sensor.availableTestPatternModes.'
+ print '%d not in android.sensor.availableTestPatternModes.' % (
+ pattern)
+ msg = 'avail_patterns: %s, REQUIRED_PATTERNS: %s' % (
+ str(avail_patterns), str(REQUIRED_PATTERNS))
+ assert set(REQUIRED_PATTERNS).issubset(avail_patterns), msg
def main():
diff --git a/apps/CameraITS/tools/run_all_tests.py b/apps/CameraITS/tools/run_all_tests.py
index d630e1a..34b6192 100644
--- a/apps/CameraITS/tools/run_all_tests.py
+++ b/apps/CameraITS/tools/run_all_tests.py
@@ -90,11 +90,11 @@
}
# Not yet mandated tests ['test', first_api_level mandatory]
-# ie. ['test_test_patterns', 28] is MANDATED for first_api_level >= 28
+# ie. ['test_test_patterns', 30] is MANDATED for first_api_level >= 30
NOT_YET_MANDATED = {
'scene0': [
- ['test_test_patterns', 28],
- ['test_tonemap_curve', 28]
+ ['test_test_patterns', 30],
+ ['test_tonemap_curve', 30]
],
'scene1_1': [
['test_ae_precapture_trigger', 28],
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index 5e618a1..be3dd9b 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -56,6 +56,7 @@
<uses-feature android:name="android.hardware.vr.high_performance" android:required="false"/>
<uses-feature android:name="android.software.companion_device_setup" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
diff --git a/apps/CtsVerifier/proguard.flags b/apps/CtsVerifier/proguard.flags
index 62eadbe..776ac1b 100644
--- a/apps/CtsVerifier/proguard.flags
+++ b/apps/CtsVerifier/proguard.flags
@@ -19,11 +19,15 @@
}
# ensure we keep public camera test methods, these are needed at runtime
--keepclassmembers class * extends android.hardware.camera2.cts.testcases.Camera2AndroidBasicTestCase {
+-keepclassmembers class android.hardware.camera2.cts.PerformanceTest {
public <methods>;
}
--keepclassmembers class * extends android.hardware.cts.CameraTestCase {
+-keepclassmembers class android.hardware.cts.LegacyCameraPerformanceTest {
+ public <methods>;
+}
+
+-keepclassmembers class org.junit.runners.JUnit4 {
public <methods>;
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioAEC.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioAEC.java
index 636dc2b..24e273c 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioAEC.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioAEC.java
@@ -16,6 +16,7 @@
package com.android.cts.verifier.audio;
+import android.content.Context;
import android.media.*;
import android.media.audiofx.AcousticEchoCanceler;
import android.os.Bundle;
@@ -61,8 +62,10 @@
private final int CORRELATION_DURATION_MS = TEST_DURATION_MS - 3000;
private final int SHOT_COUNT_CORRELATION = CORRELATION_DURATION_MS/SHOT_FREQUENCY_MS;
private final int SHOT_COUNT = TEST_DURATION_MS/SHOT_FREQUENCY_MS;
+ private final float MIN_RMS_DB = -60.0f; //dB
+ private final float MIN_RMS_VAL = (float)Math.pow(10,(MIN_RMS_DB/20));
- private final double TEST_THRESHOLD_AEC_ON = 0.4; //From SoloTester
+ private final double TEST_THRESHOLD_AEC_ON = 0.5;
private final double TEST_THRESHOLD_AEC_OFF = 0.6;
private RmsHelper mRMSRecorder1 = new RmsHelper(mBlockSizeSamples, SHOT_COUNT);
private RmsHelper mRMSRecorder2 = new RmsHelper(mBlockSizeSamples, SHOT_COUNT);
@@ -131,6 +134,9 @@
count++;
}
float rms = count > 0 ? (float)Math.sqrt(rmsTempSum / count) : 0f;
+ if (rms < MIN_RMS_VAL) {
+ rms = MIN_RMS_VAL;
+ }
double alpha = 0.9;
double total_rms = rms * alpha + mRmsCurrent * (1.0f - alpha);
@@ -162,9 +168,10 @@
DspBufferDouble crossCorr = new DspBufferDouble(actualLen);
for (int i = firstShot, index = 0; i <= lastShot; ++i, ++index) {
- double valPlayerdB = Math.max(20 * Math.log10(buffRmsPlayer.mData[i]), -120);
+ double valPlayerdB = Math.max(20 * Math.log10(buffRmsPlayer.mData[i]), MIN_RMS_DB);
rmsPlayerdB.setValue(index, valPlayerdB);
- double valRecorderdB = Math.max(20 * Math.log10(buffRmsRecorder.mData[i]), -120);
+ double valRecorderdB = Math.max(20 * Math.log10(buffRmsRecorder.mData[i]),
+ MIN_RMS_DB);
rmsRecorderdB.setValue(index, valRecorderdB);
}
@@ -288,20 +295,37 @@
return;
}
- int playbackStreamType = AudioManager.STREAM_MUSIC;
+ //Step 0. Prepare system
+ AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
+ int targetMode = AudioManager.MODE_IN_COMMUNICATION;
+ int originalMode = am.getMode();
+ am.setMode(targetMode);
+
+ if (am.getMode() != targetMode) {
+ sendMessage(AudioTestRunner.TEST_ENDED_ERROR,
+ "Couldn't set mode to MODE_IN_COMMUNICATION.");
+ return;
+ }
+
+ int playbackStreamType = AudioManager.STREAM_VOICE_CALL;
int maxLevel = getMaxLevelForStream(playbackStreamType);
int desiredLevel = maxLevel - 1;
setLevelForStream(playbackStreamType, desiredLevel);
int currentLevel = getLevelForStream(playbackStreamType);
if (currentLevel != desiredLevel) {
+ am.setMode(originalMode);
sendMessage(AudioTestRunner.TEST_ENDED_ERROR,
- "Couldn't set level for STREAM_MUSIC. Expected " +
+ "Couldn't set level for STREAM_VOICE_CALL. Expected " +
desiredLevel +" got: " + currentLevel);
return;
}
+ boolean originalSpeakerPhone = am.isSpeakerphoneOn();
+ am.setSpeakerphoneOn(true);
+
//Step 1. With AEC (on by Default when using VOICE_COMMUNICATION audio source).
+ mSPlayer.setStreamType(playbackStreamType);
mSPlayer.setSoundWithResId(getApplicationContext(), R.raw.speech);
mSRecorder.startRecording();
@@ -316,16 +340,20 @@
} catch (Exception e) {
mSRecorder.stopRecording();
String msg = "Could not create AEC Effect. " + e.toString();
- sendMessage(AudioTestRunner.TEST_ENDED_ERROR, msg);
recordTestResults(mMandatory, 0, 0, msg);
+ am.setSpeakerphoneOn(originalSpeakerPhone);
+ am.setMode(originalMode);
+ sendMessage(AudioTestRunner.TEST_ENDED_ERROR, msg);
return;
}
if (mAec == null) {
mSRecorder.stopRecording();
String msg = "Could not create AEC Effect (AEC Null)";
- sendMessage(AudioTestRunner.TEST_ENDED_ERROR, msg);
recordTestResults(mMandatory,0, 0, msg);
+ am.setSpeakerphoneOn(originalSpeakerPhone);
+ am.setMode(originalMode);
+ sendMessage(AudioTestRunner.TEST_ENDED_ERROR, msg);
return;
}
@@ -333,8 +361,10 @@
String msg = "AEC is not enabled by default.";
if (mMandatory) {
mSRecorder.stopRecording();
- sendMessage(AudioTestRunner.TEST_ENDED_ERROR, msg);
recordTestResults(mMandatory,0, 0, msg);
+ am.setSpeakerphoneOn(originalSpeakerPhone);
+ am.setMode(originalMode);
+ sendMessage(AudioTestRunner.TEST_ENDED_ERROR, msg);
return;
} else {
sb.append("Warning. " + msg + "\n");
@@ -358,9 +388,9 @@
20 * Math.log10(mRMSPlayer1.getRmsCurrent())));
}
- mSPlayer.play(false);
mRMSPlayer1.setRunning(false);
mRMSRecorder1.setRunning(false);
+ mSPlayer.play(false);
int lastShot = SHOT_COUNT - 1;
int firstShot = SHOT_COUNT - SHOT_COUNT_CORRELATION;
@@ -397,10 +427,13 @@
20 * Math.log10(mRMSPlayer2.getRmsCurrent())));
}
- mSRecorder.stopRecording();
- mSPlayer.play(false);
mRMSPlayer2.setRunning(false);
mRMSRecorder2.setRunning(false);
+ mSRecorder.stopRecording();
+ mSPlayer.play(false);
+
+ am.setSpeakerphoneOn(originalSpeakerPhone);
+ am.setMode(originalMode);
double maxNoAEC = computeAcousticCouplingFactor(mRMSPlayer2.getRmsSnapshots(),
mRMSRecorder2.getRmsSnapshots(), firstShot, lastShot);
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/biometrics/BiometricTest.java b/apps/CtsVerifier/src/com/android/cts/verifier/biometrics/BiometricTest.java
index 26597c3..340b09b 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/biometrics/BiometricTest.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/biometrics/BiometricTest.java
@@ -18,8 +18,6 @@
import android.Manifest;
import android.app.AlertDialog;
-import android.app.Dialog;
-import android.app.DialogFragment;
import android.app.KeyguardManager;
import android.content.DialogInterface;
import android.content.Intent;
@@ -30,6 +28,7 @@
import android.os.CancellationSignal;
import android.os.Handler;
import android.os.Looper;
+import android.provider.Settings;
import android.text.InputType;
import android.util.Log;
import android.view.View;
@@ -54,7 +53,6 @@
public class BiometricTest extends PassFailButtons.Activity {
private static final String TAG = "BiometricTest";
- private static final String BIOMETRIC_ENROLL = "android.settings.BIOMETRIC_ENROLL";
private static final int BIOMETRIC_PERMISSION_REQUEST_CODE = 0;
// Test that BiometricPrompt setAllowDeviceCredentials returns ERROR_NO_DEVICE_CREDENTIAL when
@@ -183,7 +181,9 @@
});
mButtonEnroll.setOnClickListener((view) -> {
final Intent intent = new Intent();
- intent.setAction(BIOMETRIC_ENROLL);
+ intent.setAction(Settings.ACTION_BIOMETRIC_ENROLL);
+ intent.putExtra(Settings.EXTRA_BIOMETRIC_MINIMUM_STRENGTH_REQUIRED,
+ BiometricManager.Authenticators.BIOMETRIC_STRONG);
startActivity(intent);
});
mButtonTestCredential.setOnClickListener((view) -> {
@@ -234,6 +234,9 @@
} else if (testType == TEST_AUTHENTICATE) {
if (result == BiometricManager.BIOMETRIC_SUCCESS) {
showBiometricPrompt(false /* allowCredential */);
+ } else if (result == BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE) {
+ showToastAndLog("No biometric features, test passed.");
+ getPassButton().setEnabled(true);
} else {
showToastAndLog("Error: " + result +
" Please ensure at least one biometric is enrolled and try again");
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/camera/bokeh/CameraBokehActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/camera/bokeh/CameraBokehActivity.java
index b62c2c1..fd38e98 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/camera/bokeh/CameraBokehActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/camera/bokeh/CameraBokehActivity.java
@@ -43,7 +43,7 @@
import android.hardware.camera2.CameraMetadata;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.CaptureResult;
-import android.hardware.camera2.params.CapabilityAndMaxSize;
+import android.hardware.camera2.params.Capability;
import android.hardware.camera2.params.StreamConfigurationMap;
import android.hardware.camera2.TotalCaptureResult;
import android.media.Image;
@@ -126,7 +126,7 @@
private CaptureRequest.Builder mStillCaptureRequestBuilder;
private CaptureRequest mStillCaptureRequest;
- private HashMap<String, ArrayList<CapabilityAndMaxSize>> mTestCases = new HashMap<>();
+ private HashMap<String, ArrayList<Capability>> mTestCases = new HashMap<>();
private int mCurrentCameraIndex = -1;
private String mCameraId;
private CameraCaptureSession mCaptureSession;
@@ -221,19 +221,16 @@
for (String id : mCameraIdList) {
CameraCharacteristics characteristics =
mCameraManager.getCameraCharacteristics(id);
- Key<CapabilityAndMaxSize[]> key =
+ Key<Capability[]> key =
CameraCharacteristics.CONTROL_AVAILABLE_BOKEH_CAPABILITIES;
- CapabilityAndMaxSize[] bokehCaps = characteristics.get(key);
+ Capability[] bokehCaps = characteristics.get(key);
if (bokehCaps == null) {
continue;
- } else if (bokehCaps.length == 1 &&
- bokehCaps[0].getMode() == CameraMetadata.CONTROL_BOKEH_MODE_OFF) {
- continue;
}
- ArrayList<CapabilityAndMaxSize> nonOffModes = new ArrayList<>();
- for (CapabilityAndMaxSize bokehCap : bokehCaps) {
+ ArrayList<Capability> nonOffModes = new ArrayList<>();
+ for (Capability bokehCap : bokehCaps) {
int mode = bokehCap.getMode();
if (mode == CameraMetadata.CONTROL_BOKEH_MODE_STILL_CAPTURE ||
mode == CameraMetadata.CONTROL_BOKEH_MODE_CONTINUOUS) {
@@ -329,8 +326,8 @@
// There is untested combination for the current camera, set the next untested combination.
mNextCombination = combination.get();
int nextMode = mNextCombination.mMode;
- ArrayList<CapabilityAndMaxSize> bokehCaps = mTestCases.get(mCameraId);
- for (CapabilityAndMaxSize cap : bokehCaps) {
+ ArrayList<Capability> bokehCaps = mTestCases.get(mCameraId);
+ for (Capability cap : bokehCaps) {
if (cap.getMode() == nextMode) {
mMaxBokehStreamingSize = cap.getMaxStreamingSize();
}
@@ -619,8 +616,8 @@
}
// Update untested entries
- ArrayList<CapabilityAndMaxSize> currentTestCase = mTestCases.get(mCameraId);
- for (CapabilityAndMaxSize bokehCap : currentTestCase) {
+ ArrayList<Capability> currentTestCase = mTestCases.get(mCameraId);
+ for (Capability bokehCap : currentTestCase) {
Size maxStreamingSize = bokehCap.getMaxStreamingSize();
Size previewSize;
if ((maxStreamingSize.getWidth() == 0 && maxStreamingSize.getHeight() == 0) ||
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/camera/performance/CameraPerformanceActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/camera/performance/CameraPerformanceActivity.java
index 59b7a03..41b8569 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/camera/performance/CameraPerformanceActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/camera/performance/CameraPerformanceActivity.java
@@ -21,8 +21,6 @@
import android.app.ProgressDialog;
import android.content.Context;
import android.hardware.camera2.cts.PerformanceTest;
-import android.hardware.camera2.cts.testcases.Camera2AndroidBasicTestCase;
-import android.hardware.cts.CameraTestCase;
import android.hardware.cts.LegacyCameraPerformanceTest;
import android.os.Bundle;
import android.util.Log;
@@ -35,12 +33,9 @@
import com.android.cts.verifier.R;
import com.android.cts.verifier.TestResult;
-import junit.framework.Test;
-import junit.framework.TestCase;
-import junit.framework.TestSuite;
-
import org.junit.runner.Description;
import org.junit.runner.JUnitCore;
+import org.junit.runner.Request;
import org.junit.runner.Result;
import org.junit.runner.notification.Failure;
import org.junit.runner.notification.RunListener;
@@ -48,7 +43,6 @@
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
-import java.util.Enumeration;
import java.util.HashMap;
import java.util.Set;
import java.util.concurrent.ExecutorService;
@@ -67,7 +61,7 @@
private CameraTestInstrumentation mCameraInstrumentation = new CameraTestInstrumentation();
private Instrumentation mCachedInstrumentation;
private Bundle mCachedInstrumentationArgs;
- private HashMap<String, TestCase> mTestCaseMap = new HashMap<String, TestCase>();
+ private HashMap<String, Class> mTestCaseMap = new HashMap<String, Class>();
private ProgressDialog mSpinnerDialog;
private AlertDialog mResultDialog;
private ArrayList<Metric> mResults = new ArrayList<Metric>();
@@ -77,10 +71,12 @@
R.string.camera_performance_test_info, R.string.camera_performance_test_info);
}
- private void executeTest(TestCase testCase) {
+ private void executeTest(Class testClass, String testName) {
JUnitCore testRunner = new JUnitCore();
+ Log.v(TAG, String.format("Execute Test: %s#%s", testClass.getSimpleName(), testName));
+ Request request = Request.method(testClass, testName);
testRunner.addListener(new CameraRunListener());
- testRunner.run(testCase);
+ testRunner.run(request);
}
private class MetricListener implements CameraTestInstrumentation.MetricListener {
@@ -124,8 +120,8 @@
StringBuilder message = new StringBuilder();
for (Metric m : mResults) {
message.append(String.format("%s : %5.2f %s\n",
- m.getMessage().replaceAll("_", " "), m.getValues()[0],
- m.getUnit()));
+ m.getMessage().replaceAll("_", " "), m.getValues()[0],
+ m.getUnit()));
}
mResultDialog.setMessage(message);
mResultDialog.show();
@@ -193,42 +189,15 @@
}
private void initializeTestCases(Context ctx) {
- TestSuite suite = new TestSuite(TEST_CLASSES);
- Enumeration<Test> testSuite = suite.tests();
- while (testSuite.hasMoreElements()) {
- Test s = testSuite.nextElement();
- if (s instanceof TestSuite) {
- Enumeration<Test> tests = ((TestSuite) s).tests();
- while (tests.hasMoreElements()) {
- Test test = tests.nextElement();
- if (test instanceof Camera2AndroidBasicTestCase) {
- Camera2AndroidBasicTestCase testCase = (Camera2AndroidBasicTestCase) test;
-
- // The base case class has one internal test that can
- // be ignored for the purpose of this test activity.
- try {
- Method method = testCase.getClass().getMethod(testCase.getName());
- Annotation an = method.getAnnotation(
- android.test.suitebuilder.annotation.Suppress.class);
- if (an != null) {
- continue;
- }
- } catch (Exception e) {
- e.printStackTrace();
- continue;
- }
-
- testCase.setContext(ctx);
- mTestCaseMap.put(testCase.getName(), testCase);
- } else if (test instanceof CameraTestCase) {
- TestCase testCase = (CameraTestCase) test;
- mTestCaseMap.put(testCase.getName(), testCase);
- } else {
- Log.d(TAG, "Test is not instance of any known camera test cases");
- }
+ for (Class testClass : TEST_CLASSES) {
+ Log.v(TAG, String.format("Test class: %s", testClass.getSimpleName()));
+ for (Method method : testClass.getMethods()) {
+ Annotation an = method.getAnnotation((Class) org.junit.Test.class);
+ Log.v(TAG, String.format("Test method: %s; Annotation: %s", method.getName(), an));
+ if (an == null) {
+ continue;
}
- } else {
- Log.d(TAG, "Test is not instance of TestSuite");
+ mTestCaseMap.put(method.getName(), testClass);
}
}
}
@@ -264,8 +233,8 @@
@Override
public void performTest(DialogTestListActivity activity) {
- TestCase testCase = mTestCaseMap.get(mTestId);
- if (testCase == null) {
+ Class testClass = mTestCaseMap.get(mTestId);
+ if (testClass == null) {
Log.e(TAG, "Test case with name: " + mTestId + " not found!");
return;
}
@@ -273,7 +242,7 @@
mExecutorService.execute(new Runnable() {
@Override
public void run() {
- executeTest(testCase);
+ executeTest(testClass, mTestId);
}
});
}
@@ -318,4 +287,4 @@
}
mCameraInstrumentation.release();
}
-}
+}
\ No newline at end of file
diff --git a/common/device-side/util-axt/src/com/android/compatibility/common/util/BlockedNumberService.java b/common/device-side/util-axt/src/com/android/compatibility/common/util/BlockedNumberService.java
index 360c078..bb27360 100644
--- a/common/device-side/util-axt/src/com/android/compatibility/common/util/BlockedNumberService.java
+++ b/common/device-side/util-axt/src/com/android/compatibility/common/util/BlockedNumberService.java
@@ -23,11 +23,16 @@
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Intent;
+import android.database.ContentObserver;
import android.net.Uri;
import android.os.Bundle;
+import android.os.Handler;
import android.os.ResultReceiver;
import android.util.Log;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
/**
* A service to handle interactions with the BlockedNumberProvider. The BlockedNumberProvider
* can only be accessed by the primary user. This service can be run as a singleton service
@@ -41,11 +46,14 @@
static final String PHONE_NUMBER_EXTRA = "number";
static final String URI_EXTRA = "uri";
static final String ROWS_EXTRA = "rows";
+ static final String FAIL_EXTRA = "fail";
static final String RESULT_RECEIVER_EXTRA = "resultReceiver";
private static final String TAG = "CtsBlockNumberSvc";
+ private static final int ASYNC_TIMEOUT = 10000;
private ContentResolver mContentResolver;
+ private Handler mHandler = new Handler();
public BlockedNumberService() {
super(BlockedNumberService.class.getName());
@@ -77,14 +85,37 @@
private Bundle insertBlockedNumber(String number) {
Log.i(TAG, "insertBlockedNumber: " + number);
+ CountDownLatch blockedNumberLatch = getBlockedNumberLatch();
ContentValues cv = new ContentValues();
cv.put(COLUMN_ORIGINAL_NUMBER, number);
Uri uri = mContentResolver.insert(CONTENT_URI, cv);
Bundle bundle = new Bundle();
bundle.putString(URI_EXTRA, uri.toString());
+
+ // Wait for the content provider to be updated.
+ try {
+ blockedNumberLatch.await(ASYNC_TIMEOUT, TimeUnit.MILLISECONDS);
+ } catch (InterruptedException e) {
+ bundle.putBoolean(FAIL_EXTRA, true);
+ }
return bundle;
}
+ private CountDownLatch getBlockedNumberLatch() {
+ CountDownLatch changeLatch = new CountDownLatch(1);
+ getContentResolver().registerContentObserver(
+ CONTENT_URI, true,
+ new ContentObserver(mHandler) {
+ @Override
+ public void onChange(boolean selfChange, Uri uri) {
+ getContentResolver().unregisterContentObserver(this);
+ changeLatch.countDown();
+ super.onChange(selfChange);
+ }
+ });
+ return changeLatch;
+ }
+
private Bundle deleteBlockedNumber(Uri uri) {
Log.i(TAG, "deleteBlockedNumber: " + uri);
diff --git a/common/device-side/util-axt/src/com/android/compatibility/common/util/BlockedNumberUtil.java b/common/device-side/util-axt/src/com/android/compatibility/common/util/BlockedNumberUtil.java
index e5a0ce4..91959d5 100644
--- a/common/device-side/util-axt/src/com/android/compatibility/common/util/BlockedNumberUtil.java
+++ b/common/device-side/util-axt/src/com/android/compatibility/common/util/BlockedNumberUtil.java
@@ -51,7 +51,11 @@
Intent intent = new Intent(INSERT_ACTION);
intent.putExtra(PHONE_NUMBER_EXTRA, phoneNumber);
- return Uri.parse(runBlockedNumberService(context, intent).getString(URI_EXTRA));
+ Bundle result = runBlockedNumberService(context, intent);
+ if (result.getBoolean(BlockedNumberService.FAIL_EXTRA)) {
+ return null;
+ }
+ return Uri.parse(result.getString(URI_EXTRA));
}
/** Remove a number from the blocked number provider and returns the number of rows deleted. */
diff --git a/common/device-side/util-axt/src/com/android/compatibility/common/util/DeviceConfigStateManager.java b/common/device-side/util-axt/src/com/android/compatibility/common/util/DeviceConfigStateManager.java
index 040641c..6875ae1 100644
--- a/common/device-side/util-axt/src/com/android/compatibility/common/util/DeviceConfigStateManager.java
+++ b/common/device-side/util-axt/src/com/android/compatibility/common/util/DeviceConfigStateManager.java
@@ -26,8 +26,7 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import com.google.common.base.Preconditions;
-
+import java.util.Objects;
import java.util.concurrent.atomic.AtomicReference;
/**
@@ -52,9 +51,9 @@
@NonNull String key) {
debug("DeviceConfigStateManager", "namespace=%s, key=%s", namespace, key);
- mContext = Preconditions.checkNotNull(context);
- mNamespace = Preconditions.checkNotNull(namespace);
- mKey = Preconditions.checkNotNull(key);
+ mContext = Objects.requireNonNull(context);
+ mNamespace = Objects.requireNonNull(namespace);
+ mKey = Objects.requireNonNull(key);
}
@Override
diff --git a/common/device-side/util-axt/src/com/android/compatibility/common/util/OneTimeDeviceConfigListener.java b/common/device-side/util-axt/src/com/android/compatibility/common/util/OneTimeDeviceConfigListener.java
index e5be3f41..3581764 100644
--- a/common/device-side/util-axt/src/com/android/compatibility/common/util/OneTimeDeviceConfigListener.java
+++ b/common/device-side/util-axt/src/com/android/compatibility/common/util/OneTimeDeviceConfigListener.java
@@ -23,8 +23,7 @@
import androidx.annotation.NonNull;
-import com.google.common.base.Preconditions;
-
+import java.util.Objects;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -50,8 +49,8 @@
public OneTimeDeviceConfigListener(@NonNull String namespace, @NonNull String key,
long timeoutMs) {
- mNamespace = Preconditions.checkNotNull(namespace);
- mKey = Preconditions.checkNotNull(key);
+ mNamespace = Objects.requireNonNull(namespace);
+ mKey = Objects.requireNonNull(key);
mTimeoutMs = timeoutMs;
}
diff --git a/common/device-side/util-axt/src/com/android/compatibility/common/util/RetryRule.java b/common/device-side/util-axt/src/com/android/compatibility/common/util/RetryRule.java
index 32dedea..ca0e3e2 100644
--- a/common/device-side/util-axt/src/com/android/compatibility/common/util/RetryRule.java
+++ b/common/device-side/util-axt/src/com/android/compatibility/common/util/RetryRule.java
@@ -18,6 +18,8 @@
import android.util.Log;
+import androidx.annotation.Nullable;
+
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
@@ -28,7 +30,17 @@
public class RetryRule implements TestRule {
private static final String TAG = "RetryRule";
+
+ /**
+ * An interface is used to clean up testing objects between the retries to make sure
+ * the testing environment is clean.
+ */
+ public interface RetryCleaner {
+ void clean();
+ }
+
private final int mMaxAttempts;
+ private final RetryCleaner mCleaner;
/**
* Retries the underlying test when it catches a {@link RetryableException}.
@@ -38,10 +50,24 @@
* @throws IllegalArgumentException if {@code retries} is less than {@code 0}.
*/
public RetryRule(int retries) {
+ this(retries, null);
+ }
+
+ /**
+ * Retries the underlying test when it catches a {@link RetryableException}.
+ *
+ * @param retries number of retries. Use {@code 0} to disable rule.
+ * @param cleaner a {@link RetryCleaner} to clean up the objects generated by the testing
+ * between retries
+ *
+ * @throws IllegalArgumentException if {@code retries} is less than {@code 0}.
+ */
+ public RetryRule(int retries, @Nullable RetryCleaner cleaner) {
if (retries < 0) {
throw new IllegalArgumentException("retries must be more than 0");
}
mMaxAttempts = retries + 1;
+ mCleaner = cleaner;
}
@Override
@@ -78,6 +104,9 @@
+ " to " + timeout.ms() + "ms");
}
caught = e;
+ if (i != mMaxAttempts && mCleaner != null) {
+ mCleaner.clean();
+ }
}
Log.w(TAG, "Arrrr! " + name + " failed at attempt " + i + "/" + mMaxAttempts
+ ": " + caught);
diff --git a/common/device-side/util-axt/src/com/android/compatibility/common/util/SettingsStateManager.java b/common/device-side/util-axt/src/com/android/compatibility/common/util/SettingsStateManager.java
index bab06a6..c7be6b3 100644
--- a/common/device-side/util-axt/src/com/android/compatibility/common/util/SettingsStateManager.java
+++ b/common/device-side/util-axt/src/com/android/compatibility/common/util/SettingsStateManager.java
@@ -22,7 +22,7 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import com.google.common.base.Preconditions;
+import java.util.Objects;
/**
* Manages the state of a preference backed by {@link Settings}.
@@ -42,9 +42,9 @@
*/
public SettingsStateManager(@NonNull Context context, @NonNull String namespace,
@NonNull String key) {
- mContext = Preconditions.checkNotNull(context);
- mNamespace = Preconditions.checkNotNull(namespace);
- mKey = Preconditions.checkNotNull(key);
+ mContext = Objects.requireNonNull(context);
+ mNamespace = Objects.requireNonNull(namespace);
+ mKey = Objects.requireNonNull(key);
}
@Override
diff --git a/common/device-side/util-axt/src/com/android/compatibility/common/util/StateChangerRule.java b/common/device-side/util-axt/src/com/android/compatibility/common/util/StateChangerRule.java
index 4e59f13..3a0ceb0 100644
--- a/common/device-side/util-axt/src/com/android/compatibility/common/util/StateChangerRule.java
+++ b/common/device-side/util-axt/src/com/android/compatibility/common/util/StateChangerRule.java
@@ -19,8 +19,6 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import com.google.common.base.Preconditions;
-
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
@@ -47,7 +45,7 @@
* @param value value to be set before the test is run.
*/
public StateChangerRule(@NonNull StateManager<T> stateManager, @Nullable T value) {
- mStateManager = Preconditions.checkNotNull(stateManager);
+ mStateManager = Objects.requireNonNull(stateManager);
mValue = value;
}
diff --git a/common/device-side/util-axt/src/com/android/compatibility/common/util/StateKeeperRule.java b/common/device-side/util-axt/src/com/android/compatibility/common/util/StateKeeperRule.java
index ecc02a2..76e5fa7 100644
--- a/common/device-side/util-axt/src/com/android/compatibility/common/util/StateKeeperRule.java
+++ b/common/device-side/util-axt/src/com/android/compatibility/common/util/StateKeeperRule.java
@@ -18,8 +18,6 @@
import androidx.annotation.NonNull;
-import com.google.common.base.Preconditions;
-
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
@@ -43,7 +41,7 @@
* @param stateManager abstraction used to mange the state.
*/
public StateKeeperRule(@NonNull StateManager<T> stateManager) {
- mStateManager = Preconditions.checkNotNull(stateManager);
+ mStateManager = Objects.requireNonNull(stateManager);
}
/**
diff --git a/hostsidetests/appsecurity/Android.mk b/hostsidetests/appsecurity/Android.mk
index c37fd33..91706c4 100644
--- a/hostsidetests/appsecurity/Android.mk
+++ b/hostsidetests/appsecurity/Android.mk
@@ -28,7 +28,7 @@
LOCAL_CTS_TEST_PACKAGE := android.appsecurity
# tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests mts
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests mts sts
LOCAL_REQUIRED_MODULES := \
CtsCorruptApkTests_b71360999 \
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/AppSecurityTests.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/AppSecurityTests.java
index 46ee46f..008eea4 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/AppSecurityTests.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/AppSecurityTests.java
@@ -23,6 +23,7 @@
import android.platform.test.annotations.AppModeFull;
import android.platform.test.annotations.AppModeInstant;
+import android.platform.test.annotations.SecurityTest;
import com.android.ddmlib.Log;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -224,6 +225,7 @@
*/
@Test
@AppModeFull(reason = "Only the platform can define permissions obtainable by instant applications")
+ @SecurityTest
public void testPermissionDiffCert() throws Exception {
Log.i(LOG_TAG, "installing app that attempts to use permission of another app");
try {
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/ExternalStorageHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/ExternalStorageHostTest.java
index 8ae80fc..ec3594e 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/ExternalStorageHostTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/ExternalStorageHostTest.java
@@ -614,6 +614,11 @@
runDeviceTests(config.pkg, config.clazz, "testMediaEscalation_Open", user);
runDeviceTests(config.pkg, config.clazz, "testMediaEscalation_Update", user);
runDeviceTests(config.pkg, config.clazz, "testMediaEscalation_Delete", user);
+
+ runDeviceTests(config.pkg, config.clazz, "testMediaEscalation_RequestWrite", user);
+ runDeviceTests(config.pkg, config.clazz, "testMediaEscalation_RequestTrash", user);
+ runDeviceTests(config.pkg, config.clazz, "testMediaEscalation_RequestFavorite", user);
+ runDeviceTests(config.pkg, config.clazz, "testMediaEscalation_RequestDelete", user);
}
@Test
diff --git a/hostsidetests/appsecurity/test-apps/Android.mk b/hostsidetests/appsecurity/test-apps/Android.mk
index f697a59..24249f2 100644
--- a/hostsidetests/appsecurity/test-apps/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/Android.mk
@@ -17,7 +17,7 @@
include $(CLEAR_VARS)
# tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests sts
# Build the test APKs using their own makefiles
include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/hostsidetests/appsecurity/test-apps/DeviceIdentifiers/src/android/appsecurity/cts/deviceids/DeviceIdentifierAppOpTest.java b/hostsidetests/appsecurity/test-apps/DeviceIdentifiers/src/android/appsecurity/cts/deviceids/DeviceIdentifierAppOpTest.java
index 1025c4d..71cd7d2 100644
--- a/hostsidetests/appsecurity/test-apps/DeviceIdentifiers/src/android/appsecurity/cts/deviceids/DeviceIdentifierAppOpTest.java
+++ b/hostsidetests/appsecurity/test-apps/DeviceIdentifiers/src/android/appsecurity/cts/deviceids/DeviceIdentifierAppOpTest.java
@@ -64,6 +64,9 @@
ShellIdentityUtils.invokeMethodWithShellPermissions(telephonyManager,
(tm) -> tm.getSimSerialNumber()),
telephonyManager.getSimSerialNumber());
+ assertEquals(String.format(DEVICE_ID_WITH_APPOP_ERROR_MESSAGE, "getNai"),
+ ShellIdentityUtils.invokeMethodWithShellPermissions(telephonyManager,
+ (tm) -> tm.getNai()), telephonyManager.getNai());
assertEquals(String.format(DEVICE_ID_WITH_APPOP_ERROR_MESSAGE, "Build#getSerial"),
ShellIdentityUtils.invokeStaticMethodWithShellPermissions(Build::getSerial),
Build.getSerial());
diff --git a/hostsidetests/appsecurity/test-apps/MediaStorageApp/src/com/android/cts/mediastorageapp/MediaStorageTest.java b/hostsidetests/appsecurity/test-apps/MediaStorageApp/src/com/android/cts/mediastorageapp/MediaStorageTest.java
index 30291a0..aafb94e 100644
--- a/hostsidetests/appsecurity/test-apps/MediaStorageApp/src/com/android/cts/mediastorageapp/MediaStorageTest.java
+++ b/hostsidetests/appsecurity/test-apps/MediaStorageApp/src/com/android/cts/mediastorageapp/MediaStorageTest.java
@@ -27,6 +27,7 @@
import android.app.Activity;
import android.app.Instrumentation;
+import android.app.PendingIntent;
import android.app.RecoverableSecurityException;
import android.content.ContentResolver;
import android.content.ContentUris;
@@ -42,6 +43,7 @@
import android.provider.MediaStore;
import android.provider.MediaStore.MediaColumns;
import android.support.test.uiautomator.UiDevice;
+import android.support.test.uiautomator.UiObject;
import android.support.test.uiautomator.UiSelector;
import androidx.test.InstrumentationRegistry;
@@ -59,6 +61,7 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.util.Arrays;
import java.util.HashSet;
import java.util.concurrent.Callable;
@@ -103,9 +106,9 @@
@Test
public void testClearFiles() throws Exception {
TEST_JPG.delete();
- assertNull(MediaStore.scanFileFromShell(mContext, TEST_JPG));
+ assertNull(MediaStore.scanFile(mContentResolver, TEST_JPG));
TEST_PDF.delete();
- assertNull(MediaStore.scanFileFromShell(mContext, TEST_PDF));
+ assertNull(MediaStore.scanFile(mContentResolver, TEST_PDF));
}
private void doSandboxed(boolean sandboxed) throws Exception {
@@ -137,8 +140,8 @@
assertTrue(TEST_JPG.exists());
assertTrue(TEST_PDF.exists());
- final Uri jpgUri = MediaStore.scanFileFromShell(mContext, TEST_JPG);
- final Uri pdfUri = MediaStore.scanFileFromShell(mContext, TEST_PDF);
+ final Uri jpgUri = MediaStore.scanFile(mContentResolver, TEST_JPG);
+ final Uri pdfUri = MediaStore.scanFile(mContentResolver, TEST_PDF);
final HashSet<Long> seen = new HashSet<>();
try (Cursor c = mContentResolver.query(
@@ -375,7 +378,89 @@
assertEquals(1, mContentResolver.delete(red, null, null));
}
+ @Test
+ public void testMediaEscalation_RequestWrite() throws Exception {
+ doMediaEscalation_RequestWrite(MediaStorageTest::createAudio);
+ doMediaEscalation_RequestWrite(MediaStorageTest::createVideo);
+ doMediaEscalation_RequestWrite(MediaStorageTest::createImage);
+ }
+
+ private void doMediaEscalation_RequestWrite(Callable<Uri> create) throws Exception {
+ final Uri red = create.call();
+ clearMediaOwner(red, mUserId);
+
+ try (ParcelFileDescriptor pfd = mContentResolver.openFileDescriptor(red, "w")) {
+ fail("Expected write access to be blocked");
+ } catch (RecoverableSecurityException expected) {
+ }
+
+ doEscalation(MediaStore.createWriteRequest(mContentResolver, Arrays.asList(red)));
+
+ try (ParcelFileDescriptor pfd = mContentResolver.openFileDescriptor(red, "w")) {
+ }
+ }
+
+ @Test
+ public void testMediaEscalation_RequestTrash() throws Exception {
+ doMediaEscalation_RequestTrash(MediaStorageTest::createAudio);
+ doMediaEscalation_RequestTrash(MediaStorageTest::createVideo);
+ doMediaEscalation_RequestTrash(MediaStorageTest::createImage);
+ }
+
+ private void doMediaEscalation_RequestTrash(Callable<Uri> create) throws Exception {
+ final Uri red = create.call();
+ clearMediaOwner(red, mUserId);
+
+ assertEquals("0", queryForSingleColumn(red, MediaColumns.IS_TRASHED));
+ doEscalation(MediaStore.createTrashRequest(mContentResolver, Arrays.asList(red), true));
+ assertEquals("1", queryForSingleColumn(red, MediaColumns.IS_TRASHED));
+ doEscalation(MediaStore.createTrashRequest(mContentResolver, Arrays.asList(red), false));
+ assertEquals("0", queryForSingleColumn(red, MediaColumns.IS_TRASHED));
+ }
+
+ @Test
+ public void testMediaEscalation_RequestFavorite() throws Exception {
+ doMediaEscalation_RequestFavorite(MediaStorageTest::createAudio);
+ doMediaEscalation_RequestFavorite(MediaStorageTest::createVideo);
+ doMediaEscalation_RequestFavorite(MediaStorageTest::createImage);
+ }
+
+ private void doMediaEscalation_RequestFavorite(Callable<Uri> create) throws Exception {
+ final Uri red = create.call();
+ clearMediaOwner(red, mUserId);
+
+ assertEquals("0", queryForSingleColumn(red, MediaColumns.IS_FAVORITE));
+ doEscalation(MediaStore.createFavoriteRequest(mContentResolver, Arrays.asList(red), true));
+ assertEquals("1", queryForSingleColumn(red, MediaColumns.IS_FAVORITE));
+ doEscalation(MediaStore.createFavoriteRequest(mContentResolver, Arrays.asList(red), false));
+ assertEquals("0", queryForSingleColumn(red, MediaColumns.IS_FAVORITE));
+ }
+
+ @Test
+ public void testMediaEscalation_RequestDelete() throws Exception {
+ doMediaEscalation_RequestDelete(MediaStorageTest::createAudio);
+ doMediaEscalation_RequestDelete(MediaStorageTest::createVideo);
+ doMediaEscalation_RequestDelete(MediaStorageTest::createImage);
+ }
+
+ private void doMediaEscalation_RequestDelete(Callable<Uri> create) throws Exception {
+ final Uri red = create.call();
+ clearMediaOwner(red, mUserId);
+
+ try (Cursor c = mContentResolver.query(red, null, null, null)) {
+ assertEquals(1, c.getCount());
+ }
+ doEscalation(MediaStore.createDeleteRequest(mContentResolver, Arrays.asList(red)));
+ try (Cursor c = mContentResolver.query(red, null, null, null)) {
+ assertEquals(0, c.getCount());
+ }
+ }
+
private void doEscalation(RecoverableSecurityException exception) throws Exception {
+ doEscalation(exception.getUserAction().getActionIntent());
+ }
+
+ private void doEscalation(PendingIntent pi) throws Exception {
// Try launching the action to grant ourselves access
final Instrumentation inst = InstrumentationRegistry.getInstrumentation();
final Intent intent = new Intent(inst.getContext(), GetResultActivity.class);
@@ -389,12 +474,17 @@
final GetResultActivity activity = (GetResultActivity) inst.startActivitySync(intent);
device.waitForIdle();
activity.clearResult();
- activity.startIntentSenderForResult(
- exception.getUserAction().getActionIntent().getIntentSender(),
- 42, null, 0, 0, 0);
+ activity.startIntentSenderForResult(pi.getIntentSender(), 42, null, 0, 0, 0);
device.waitForIdle();
- device.findObject(new UiSelector().textMatches("(?i:Allow)")).click();
+
+ // Some dialogs may have granted access automatically, so we're willing
+ // to keep rolling forward if we can't find our grant button
+ final UiSelector grant = new UiSelector()
+ .textMatches("(Allow|Change|Move to trash|Move out of trash|Delete)");
+ if (new UiObject(grant).waitForExists(2_000)) {
+ device.findObject(grant).click();
+ }
// Verify that we now have access
final GetResultActivity.Result res = activity.getResult();
@@ -446,6 +536,16 @@
}
}
+ private static String queryForSingleColumn(Uri uri, String column) throws Exception {
+ final ContentResolver resolver = InstrumentationRegistry.getTargetContext()
+ .getContentResolver();
+ try (Cursor c = resolver.query(uri, new String[] { column }, null, null)) {
+ assertEquals(c.getCount(), 1);
+ assertTrue(c.moveToFirst());
+ return c.getString(0);
+ }
+ }
+
private static void clearMediaOwner(Uri uri, int userId) throws IOException {
final String cmd = String.format(
"content update --uri %s --user %d --bind owner_package_name:n:",
diff --git a/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/Android.bp b/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/Android.bp
index 64a8e7c..4c79dca 100644
--- a/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/Android.bp
+++ b/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/Android.bp
@@ -23,6 +23,7 @@
"cts",
"vts",
"general-tests",
+ "sts",
],
// sign this app with a different cert than CtsUsePermissionDiffCert
certificate: ":cts-testkey1",
diff --git a/hostsidetests/appsecurity/test-apps/PermissionDeclareAppCompat/Android.bp b/hostsidetests/appsecurity/test-apps/PermissionDeclareAppCompat/Android.bp
index 54161d6..76203e9 100644
--- a/hostsidetests/appsecurity/test-apps/PermissionDeclareAppCompat/Android.bp
+++ b/hostsidetests/appsecurity/test-apps/PermissionDeclareAppCompat/Android.bp
@@ -23,6 +23,7 @@
"cts",
"vts",
"general-tests",
+ "sts",
],
// sign this app with a different cert than CtsUsePermissionDiffCert
certificate: ":cts-testkey1",
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionApp23/src/com/android/cts/usepermission/BasePermissionsTest.java b/hostsidetests/appsecurity/test-apps/UsePermissionApp23/src/com/android/cts/usepermission/BasePermissionsTest.java
index d116a08..8b5630c 100755
--- a/hostsidetests/appsecurity/test-apps/UsePermissionApp23/src/com/android/cts/usepermission/BasePermissionsTest.java
+++ b/hostsidetests/appsecurity/test-apps/UsePermissionApp23/src/com/android/cts/usepermission/BasePermissionsTest.java
@@ -449,7 +449,7 @@
waitForIdle();
}
- final boolean wasGranted = isTv() ? false : !(waitFindObject(byText(R.string.Deny)).isChecked() || waitFindObject(byText(R.string.Ask)).isChecked());
+ final boolean wasGranted = isTv() ? false : !(waitFindObject(byText(R.string.Deny)).isChecked() || (!legacyApp && waitFindObject(byText(R.string.Ask)).isChecked()));
boolean alreadyChecked = false;
if (isTv()) {
waitFindObject(By.text(permissionLabel)).click();
@@ -460,7 +460,12 @@
object.click();
}
} else if (state == STATE_DENIED){
- UiObject2 object = waitFindObject(byText(R.string.Ask));
+ UiObject2 object;
+ if (legacyApp) {
+ object = waitFindObject(byText(R.string.Deny));
+ } else {
+ object = waitFindObject(byText(R.string.Ask));
+ }
alreadyChecked = object.isChecked();
if (!alreadyChecked) {
object.click();
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionDiffCert/Android.bp b/hostsidetests/appsecurity/test-apps/UsePermissionDiffCert/Android.bp
index b11c4cc..cbedea9 100644
--- a/hostsidetests/appsecurity/test-apps/UsePermissionDiffCert/Android.bp
+++ b/hostsidetests/appsecurity/test-apps/UsePermissionDiffCert/Android.bp
@@ -29,6 +29,7 @@
"cts",
"vts",
"general-tests",
+ "sts",
],
// sign this app with a different cert than CtsPermissionDeclareApp
certificate: ":cts-testkey2",
diff --git a/hostsidetests/appsecurity/test-apps/WriteExternalStorageApp/src/com/android/cts/writeexternalstorageapp/WriteExternalStorageTest.java b/hostsidetests/appsecurity/test-apps/WriteExternalStorageApp/src/com/android/cts/writeexternalstorageapp/WriteExternalStorageTest.java
index dd2d9ff..7d96581 100644
--- a/hostsidetests/appsecurity/test-apps/WriteExternalStorageApp/src/com/android/cts/writeexternalstorageapp/WriteExternalStorageTest.java
+++ b/hostsidetests/appsecurity/test-apps/WriteExternalStorageApp/src/com/android/cts/writeexternalstorageapp/WriteExternalStorageTest.java
@@ -261,7 +261,7 @@
final List<File> paths = getAllPackageSpecificPathsExceptMedia(getContext());
for (File path : paths) {
- MediaStore.scanFile(getContext(), path);
+ MediaStore.scanFile(getContext().getContentResolver(), path);
}
// Require that .nomedia was created somewhere above each dir
diff --git a/hostsidetests/devicepolicy/app/CorpOwnedManagedProfile/src/com/android/cts/comp/provisioning/UserRestrictionTest.java b/hostsidetests/devicepolicy/app/CorpOwnedManagedProfile/src/com/android/cts/comp/provisioning/UserRestrictionTest.java
index 95972a2..05335a1 100644
--- a/hostsidetests/devicepolicy/app/CorpOwnedManagedProfile/src/com/android/cts/comp/provisioning/UserRestrictionTest.java
+++ b/hostsidetests/devicepolicy/app/CorpOwnedManagedProfile/src/com/android/cts/comp/provisioning/UserRestrictionTest.java
@@ -24,23 +24,6 @@
import com.android.cts.comp.AdminReceiver;
public class UserRestrictionTest extends AndroidTestCase {
-
- public void testAddDisallowAddManagedProfileRestriction() {
- setUserRestriction(UserManager.DISALLOW_ADD_MANAGED_PROFILE, true);
- }
-
- public void testClearDisallowAddManagedProfileRestriction() {
- setUserRestriction(UserManager.DISALLOW_ADD_MANAGED_PROFILE, false);
- }
-
- public void testAddDisallowRemoveManagedProfileRestriction() {
- setUserRestriction(UserManager.DISALLOW_REMOVE_MANAGED_PROFILE, true);
- }
-
- public void testClearDisallowRemoveManagedProfileRestriction() {
- setUserRestriction(UserManager.DISALLOW_REMOVE_MANAGED_PROFILE, false);
- }
-
public void testAddDisallowRemoveUserRestriction() {
setUserRestriction(UserManager.DISALLOW_REMOVE_USER, true);
}
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/DeviceIdentifiersTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/DeviceIdentifiersTest.java
index 2e5f4b2..ebaf592 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/DeviceIdentifiersTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/DeviceIdentifiersTest.java
@@ -15,6 +15,8 @@
*/
package com.android.cts.deviceandprofileowner;
+import static org.testng.Assert.assertThrows;
+
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Build;
@@ -61,6 +63,9 @@
ShellIdentityUtils.invokeMethodWithShellPermissions(telephonyManager,
(tm) -> tm.getSimSerialNumber()),
telephonyManager.getSimSerialNumber());
+ assertEquals(String.format(DEVICE_ID_WITH_PERMISSION_ERROR_MESSAGE, "getNai"),
+ ShellIdentityUtils.invokeMethodWithShellPermissions(telephonyManager,
+ (tm) -> tm.getNai()), telephonyManager.getNai());
assertEquals(String.format(DEVICE_ID_WITH_PERMISSION_ERROR_MESSAGE, "Build#getSerial"),
ShellIdentityUtils.invokeStaticMethodWithShellPermissions(Build::getSerial),
Build.getSerial());
@@ -78,64 +83,22 @@
// Allow the APIs to also return null if the telephony feature is not supported.
boolean hasTelephonyFeature =
mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY);
- try {
- String deviceId = telephonyManager.getDeviceId();
- if (hasTelephonyFeature) {
- fail(String.format(NO_SECURITY_EXCEPTION_ERROR_MESSAGE, "getDeviceId"));
- } else {
- assertEquals(null, deviceId);
- }
- } catch (SecurityException expected) {
- }
-
- try {
- String imei = telephonyManager.getImei();
- if (hasTelephonyFeature) {
- fail(String.format(NO_SECURITY_EXCEPTION_ERROR_MESSAGE, "getImei"));
- } else {
- assertEquals(null, imei);
- }
- } catch (SecurityException expected) {
- }
-
- try {
- String meid = telephonyManager.getMeid();
- if (hasTelephonyFeature) {
- fail(String.format(NO_SECURITY_EXCEPTION_ERROR_MESSAGE, "getMeid"));
- } else {
- assertEquals(null, meid);
- }
- } catch (SecurityException expected) {
- }
-
- try {
- String subscriberId = telephonyManager.getSubscriberId();
- if (hasTelephonyFeature) {
- fail(String.format(NO_SECURITY_EXCEPTION_ERROR_MESSAGE, "getSubscriberId"));
- } else {
- assertEquals(null, subscriberId);
- }
- } catch (SecurityException expected) {
- }
-
- try {
- String simSerialNumber = telephonyManager.getSimSerialNumber();
- if (hasTelephonyFeature) {
- fail(String.format(NO_SECURITY_EXCEPTION_ERROR_MESSAGE, "getSimSerialNumber"));
- } else {
- assertEquals(null, simSerialNumber);
- }
- } catch (SecurityException expected) {
- }
-
- try {
- String serial = Build.getSerial();
- if (hasTelephonyFeature) {
- fail(String.format(NO_SECURITY_EXCEPTION_ERROR_MESSAGE, "Build#getSerial"));
- } else {
- assertEquals(null, serial);
- }
- } catch (SecurityException expected) {
+ if (hasTelephonyFeature) {
+ assertThrows(SecurityException.class, telephonyManager::getDeviceId);
+ assertThrows(SecurityException.class, telephonyManager::getImei);
+ assertThrows(SecurityException.class, telephonyManager::getMeid);
+ assertThrows(SecurityException.class, telephonyManager::getSubscriberId);
+ assertThrows(SecurityException.class, telephonyManager::getSimSerialNumber);
+ assertThrows(SecurityException.class, telephonyManager::getNai);
+ assertThrows(SecurityException.class, Build::getSerial);
+ } else {
+ assertNull(telephonyManager.getDeviceId());
+ assertNull(telephonyManager.getImei());
+ assertNull(telephonyManager.getMeid());
+ assertNull(telephonyManager.getSubscriberId());
+ assertNull(telephonyManager.getSimSerialNumber());
+ assertNull(telephonyManager.getNai());
+ assertNull(Build.getSerial());
}
}
}
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/KeyManagementTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/KeyManagementTest.java
index 302523b..0b6ce32 100755
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/KeyManagementTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/KeyManagementTest.java
@@ -17,6 +17,7 @@
import static android.app.admin.DevicePolicyManager.ID_TYPE_BASE_INFO;
import static android.app.admin.DevicePolicyManager.ID_TYPE_IMEI;
+import static android.app.admin.DevicePolicyManager.ID_TYPE_INDIVIDUAL_ATTESTATION;
import static android.app.admin.DevicePolicyManager.ID_TYPE_MEID;
import static android.app.admin.DevicePolicyManager.ID_TYPE_SERIAL;
import static android.keystore.cts.CertificateUtils.createCertificate;
@@ -657,7 +658,103 @@
}
}
- public void testCanSetKeyPairCert() throws Exception {
+ public void testUniqueDeviceAttestationUsingDifferentAttestationCert() throws Exception {
+ // This test is only applicable in modes where Device ID attestation can be performed
+ // _and_ the device has StrongBox, which is provisioned with individual attestation
+ // certificates.
+ // The functionality tested should equally work for when the Profile Owner can perform
+ // Device ID attestation, but since the underlying StrongBox implementation cannot
+ // differentiate between PO and DO modes, for simplicity, it is only tested in DO mode.
+ if (!isDeviceOwner() || !hasStrongBox() || !isUniqueDeviceAttestationSupported()) {
+ return;
+ }
+ final String no_id_alias = "com.android.test.key_attested";
+ final String dev_unique_alias = "com.android.test.individual_dev_attested";
+
+ byte[] attestationChallenge = new byte[] {0x01, 0x02, 0x03};
+ try {
+ KeyGenParameterSpec specKeyAttOnly = new KeyGenParameterSpec.Builder(
+ no_id_alias,
+ KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY)
+ .setDigests(KeyProperties.DIGEST_SHA256)
+ .setAttestationChallenge(attestationChallenge)
+ .setIsStrongBoxBacked(true)
+ .build();
+
+ AttestedKeyPair attestedKeyPair = mDevicePolicyManager.generateKeyPair(
+ getWho(), KeyProperties.KEY_ALGORITHM_EC, specKeyAttOnly,
+ 0 /* device id attestation flags */);
+ assertWithMessage(
+ String.format("Failed generating a key with attestation in StrongBox."))
+ .that(attestedKeyPair)
+ .isNotNull();
+
+ KeyGenParameterSpec specIndividualAtt = new KeyGenParameterSpec.Builder(
+ dev_unique_alias,
+ KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY)
+ .setDigests(KeyProperties.DIGEST_SHA256)
+ .setAttestationChallenge(attestationChallenge)
+ .setIsStrongBoxBacked(true)
+ .build();
+
+ AttestedKeyPair individuallyAttestedPair = mDevicePolicyManager.generateKeyPair(
+ getWho(), KeyProperties.KEY_ALGORITHM_EC, specIndividualAtt,
+ ID_TYPE_INDIVIDUAL_ATTESTATION /* device id attestation flags */);
+ assertWithMessage(
+ String.format("Failed generating a key for unique attestation in StrongBox."))
+ .that(individuallyAttestedPair)
+ .isNotNull();
+
+ X509Certificate keyAttestationIntermediate = (X509Certificate)
+ attestedKeyPair.getAttestationRecord().get(1);
+ X509Certificate devUniqueAttestationIntermediate = (X509Certificate)
+ individuallyAttestedPair.getAttestationRecord().get(1);
+ assertWithMessage("Device unique attestation intermediate certificate"
+ + " should be different to the key attestation certificate.")
+ .that(devUniqueAttestationIntermediate.getEncoded())
+ .isNotEqualTo(keyAttestationIntermediate.getEncoded());
+ } finally {
+ mDevicePolicyManager.removeKeyPair(getWho(), no_id_alias);
+ mDevicePolicyManager.removeKeyPair(getWho(), dev_unique_alias);
+ }
+ }
+
+ public void testUniqueDeviceAttestationFailsWhenUnsupported() {
+ if (!isDeviceOwner() || !hasStrongBox()) {
+ return;
+ }
+
+ if (isUniqueDeviceAttestationSupported()) {
+ // testUniqueDeviceAttestationUsingDifferentAttestationCert is the positive test case.
+ return;
+ }
+
+ byte[] attestationChallenge = new byte[] {0x01, 0x02, 0x03};
+ final String someAlias = "com.android.test.should_not_exist";
+ try {
+ KeyGenParameterSpec specIndividualAtt = new KeyGenParameterSpec.Builder(
+ someAlias,
+ KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY)
+ .setDigests(KeyProperties.DIGEST_SHA256)
+ .setAttestationChallenge(attestationChallenge)
+ .setIsStrongBoxBacked(true)
+ .build();
+
+ AttestedKeyPair individuallyAttestedPair = mDevicePolicyManager.generateKeyPair(
+ getWho(), KeyProperties.KEY_ALGORITHM_EC, specIndividualAtt,
+ ID_TYPE_INDIVIDUAL_ATTESTATION /* device id attestation flags */);
+ assertWithMessage(
+ String.format("When unique attestation is not supported, key generation "
+ + "should fail."))
+ .that(individuallyAttestedPair)
+ .isNull();
+ } finally {
+ mDevicePolicyManager.removeKeyPair(getWho(), someAlias);
+ }
+ }
+
+
+ public void testCanSetKeyPairCert() throws Exception {
final String alias = "com.android.test.set-ec-1";
try {
KeyGenParameterSpec spec = new KeyGenParameterSpec.Builder(
@@ -798,4 +895,8 @@
return mActivity.getPackageManager()
.hasSystemFeature(PackageManager.FEATURE_STRONGBOX_KEYSTORE);
}
+
+ boolean isUniqueDeviceAttestationSupported() {
+ return mDevicePolicyManager.isUniqueDeviceAttestationSupported();
+ }
}
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/OrgOwnedProfileOwnerParentTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/OrgOwnedProfileOwnerParentTest.java
index 869b861..2b36cde 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/OrgOwnedProfileOwnerParentTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/OrgOwnedProfileOwnerParentTest.java
@@ -22,19 +22,22 @@
import android.app.admin.DevicePolicyManager;
import android.content.Context;
+import android.os.Bundle;
+import android.os.UserManager;
import android.test.InstrumentationTestCase;
public class OrgOwnedProfileOwnerParentTest extends InstrumentationTestCase {
protected Context mContext;
private DevicePolicyManager mParentDevicePolicyManager;
+ private DevicePolicyManager mDevicePolicyManager;
@Override
protected void setUp() throws Exception {
super.setUp();
mContext = getInstrumentation().getContext();
- DevicePolicyManager mDevicePolicyManager = (DevicePolicyManager)
+ mDevicePolicyManager = (DevicePolicyManager)
mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
mParentDevicePolicyManager =
mDevicePolicyManager.getParentProfileInstance(ADMIN_RECEIVER_COMPONENT);
@@ -62,4 +65,22 @@
// TODO: (145604715) test camera is actually disabled
}
-}
+ public void testAddGetAndClearUserRestriction_onParent() {
+ mParentDevicePolicyManager.addUserRestriction(ADMIN_RECEIVER_COMPONENT,
+ UserManager.DISALLOW_CONFIG_DATE_TIME);
+
+ Bundle restrictions = mParentDevicePolicyManager.getUserRestrictions(
+ ADMIN_RECEIVER_COMPONENT);
+ assertThat(restrictions.get(UserManager.DISALLOW_CONFIG_DATE_TIME)).isNotNull();
+
+ restrictions = mDevicePolicyManager.getUserRestrictions(ADMIN_RECEIVER_COMPONENT);
+ assertThat(restrictions.get(UserManager.DISALLOW_CONFIG_DATE_TIME)).isNull();
+
+ mParentDevicePolicyManager.clearUserRestriction(ADMIN_RECEIVER_COMPONENT,
+ UserManager.DISALLOW_CONFIG_DATE_TIME);
+
+ restrictions = mParentDevicePolicyManager.getUserRestrictions(ADMIN_RECEIVER_COMPONENT);
+ assertThat(restrictions.get(UserManager.DISALLOW_CONFIG_DATE_TIME)).isNull();
+ }
+
+}
\ No newline at end of file
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/TimeManagementTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/TimeManagementTest.java
new file mode 100644
index 0000000..771b13b
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/TimeManagementTest.java
@@ -0,0 +1,35 @@
+/*
+ * 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.cts.deviceandprofileowner;
+
+import static com.google.common.truth.Truth.assertThat;
+
+public class TimeManagementTest extends BaseDeviceAdminTest {
+
+ public void testSetAutoTimeZone() {
+ mDevicePolicyManager.setAutoTimeZone(ADMIN_RECEIVER_COMPONENT, true);
+
+ boolean autoTimeZone = mDevicePolicyManager.getAutoTimeZone(ADMIN_RECEIVER_COMPONENT);
+ assertThat(autoTimeZone).isTrue();
+
+ mDevicePolicyManager.setAutoTimeZone(ADMIN_RECEIVER_COMPONENT, false);
+
+ autoTimeZone = mDevicePolicyManager.getAutoTimeZone(ADMIN_RECEIVER_COMPONENT);
+ assertThat(autoTimeZone).isFalse();
+ }
+
+}
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/UserRestrictionsParentTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/UserRestrictionsParentTest.java
new file mode 100644
index 0000000..b0b398e
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/UserRestrictionsParentTest.java
@@ -0,0 +1,65 @@
+/*
+ * 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.cts.deviceandprofileowner;
+
+import static com.android.cts.deviceandprofileowner.BaseDeviceAdminTest.ADMIN_RECEIVER_COMPONENT;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.Context;
+import android.os.UserManager;
+import android.test.InstrumentationTestCase;
+
+public class UserRestrictionsParentTest extends InstrumentationTestCase {
+
+ protected Context mContext;
+ private DevicePolicyManager mDevicePolicyManager;
+ private UserManager mUserManager;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mContext = getInstrumentation().getContext();
+
+ mDevicePolicyManager = (DevicePolicyManager)
+ mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
+ assertNotNull(mDevicePolicyManager);
+
+ mUserManager = mContext.getSystemService(UserManager.class);
+ assertNotNull(mUserManager);
+ }
+
+ public void testAddUserRestriction_onParent() {
+ DevicePolicyManager parentDevicePolicyManager =
+ mDevicePolicyManager.getParentProfileInstance(ADMIN_RECEIVER_COMPONENT);
+ assertNotNull(parentDevicePolicyManager);
+
+ parentDevicePolicyManager.addUserRestriction(ADMIN_RECEIVER_COMPONENT,
+ UserManager.DISALLOW_CONFIG_DATE_TIME);
+ }
+
+ public void testHasUserRestriction() {
+ assertThat(mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_DATE_TIME)).isTrue();
+ }
+
+ public void testUserRestrictionAreNotPersisted() {
+ assertThat(
+ mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_DATE_TIME)).isFalse();
+ }
+
+}
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/userrestrictions/BaseUserRestrictionsTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/userrestrictions/BaseUserRestrictionsTest.java
index 5569653..41c162e 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/userrestrictions/BaseUserRestrictionsTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/userrestrictions/BaseUserRestrictionsTest.java
@@ -42,14 +42,12 @@
UserManager.DISALLOW_USB_FILE_TRANSFER,
UserManager.DISALLOW_CONFIG_CREDENTIALS,
UserManager.DISALLOW_REMOVE_USER,
- UserManager.DISALLOW_REMOVE_MANAGED_PROFILE,
UserManager.DISALLOW_DEBUGGING_FEATURES,
UserManager.DISALLOW_CONFIG_VPN,
UserManager.DISALLOW_CONFIG_TETHERING,
UserManager.DISALLOW_NETWORK_RESET,
UserManager.DISALLOW_FACTORY_RESET,
UserManager.DISALLOW_ADD_USER,
- UserManager.DISALLOW_ADD_MANAGED_PROFILE,
UserManager.ENSURE_VERIFY_APPS,
UserManager.DISALLOW_CONFIG_CELL_BROADCASTS,
UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS,
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/userrestrictions/DeviceOwnerUserRestrictionsTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/userrestrictions/DeviceOwnerUserRestrictionsTest.java
index 6c33dba..2b6dca6 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/userrestrictions/DeviceOwnerUserRestrictionsTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/userrestrictions/DeviceOwnerUserRestrictionsTest.java
@@ -30,14 +30,12 @@
UserManager.DISALLOW_USB_FILE_TRANSFER,
UserManager.DISALLOW_CONFIG_CREDENTIALS,
UserManager.DISALLOW_REMOVE_USER,
- UserManager.DISALLOW_REMOVE_MANAGED_PROFILE,
// UserManager.DISALLOW_DEBUGGING_FEATURES, // Need for CTS
UserManager.DISALLOW_CONFIG_VPN,
UserManager.DISALLOW_CONFIG_TETHERING,
UserManager.DISALLOW_NETWORK_RESET,
UserManager.DISALLOW_FACTORY_RESET,
UserManager.DISALLOW_ADD_USER,
- UserManager.DISALLOW_ADD_MANAGED_PROFILE,
// UserManager.ENSURE_VERIFY_APPS, // Has unrecoverable side effects.
UserManager.DISALLOW_CONFIG_CELL_BROADCASTS,
UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS,
@@ -68,7 +66,7 @@
};
public static final String[] DEFAULT_ENABLED = new String[] {
- UserManager.DISALLOW_ADD_MANAGED_PROFILE
+ // No restrictions set for DO by default.
};
@Override
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/DeviceIdentifiersTest.java b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/DeviceIdentifiersTest.java
index 3c53de9..e5ea597 100644
--- a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/DeviceIdentifiersTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/DeviceIdentifiersTest.java
@@ -15,6 +15,8 @@
*/
package com.android.cts.deviceowner;
+import static org.testng.Assert.assertThrows;
+
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Build;
@@ -30,9 +32,6 @@
private static final String DEVICE_ID_WITH_PERMISSION_ERROR_MESSAGE =
"An unexpected value was received by the device owner with the READ_PHONE_STATE "
+ "permission when invoking %s";
- private static final String NO_SECURITY_EXCEPTION_ERROR_MESSAGE =
- "A device owner that does not have the READ_PHONE_STATE permission must receive a "
- + "SecurityException when invoking %s";
public void testDeviceOwnerCanGetDeviceIdentifiersWithPermission() throws Exception {
// The device owner with the READ_PHONE_STATE permission should have access to all device
@@ -59,6 +58,10 @@
ShellIdentityUtils.invokeMethodWithShellPermissions(telephonyManager,
(tm) -> tm.getSimSerialNumber()),
telephonyManager.getSimSerialNumber());
+ assertEquals(
+ String.format(DEVICE_ID_WITH_PERMISSION_ERROR_MESSAGE, "getNai"),
+ ShellIdentityUtils.invokeMethodWithShellPermissions(telephonyManager,
+ (tm) -> tm.getNai()), telephonyManager.getNai());
assertEquals(String.format(DEVICE_ID_WITH_PERMISSION_ERROR_MESSAGE, "Build#getSerial"),
ShellIdentityUtils.invokeStaticMethodWithShellPermissions(Build::getSerial),
Build.getSerial());
@@ -76,64 +79,22 @@
// Allow the APIs to also return null if the telephony feature is not supported.
boolean hasTelephonyFeature =
mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY);
- try {
- String deviceId = telephonyManager.getDeviceId();
- if (hasTelephonyFeature) {
- fail(String.format(NO_SECURITY_EXCEPTION_ERROR_MESSAGE, "getDeviceId"));
- } else {
- assertEquals(null, deviceId);
- }
- } catch (SecurityException expected) {
- }
-
- try {
- String imei = telephonyManager.getImei();
- if (hasTelephonyFeature) {
- fail(String.format(NO_SECURITY_EXCEPTION_ERROR_MESSAGE, "getImei"));
- } else {
- assertEquals(null, imei);
- }
- } catch (SecurityException expected) {
- }
-
- try {
- String meid = telephonyManager.getMeid();
- if (hasTelephonyFeature) {
- fail(String.format(NO_SECURITY_EXCEPTION_ERROR_MESSAGE, "getMeid"));
- } else {
- assertEquals(null, meid);
- }
- } catch (SecurityException expected) {
- }
-
- try {
- String subscriberId = telephonyManager.getSubscriberId();
- if (hasTelephonyFeature) {
- fail(String.format(NO_SECURITY_EXCEPTION_ERROR_MESSAGE, "getSubscriberId"));
- } else {
- assertEquals(null, subscriberId);
- }
- } catch (SecurityException expected) {
- }
-
- try {
- String simSerialNumber = telephonyManager.getSimSerialNumber();
- if (hasTelephonyFeature) {
- fail(String.format(NO_SECURITY_EXCEPTION_ERROR_MESSAGE, "getSimSerialNumber"));
- } else {
- assertEquals(null, simSerialNumber);
- }
- } catch (SecurityException expected) {
- }
-
- try {
- String serial = Build.getSerial();
- if (hasTelephonyFeature) {
- fail(String.format(NO_SECURITY_EXCEPTION_ERROR_MESSAGE, "Build#getSerial"));
- } else {
- assertEquals(null, serial);
- }
- } catch (SecurityException expected) {
+ if (hasTelephonyFeature) {
+ assertThrows(SecurityException.class, telephonyManager::getDeviceId);
+ assertThrows(SecurityException.class, telephonyManager::getImei);
+ assertThrows(SecurityException.class, telephonyManager::getMeid);
+ assertThrows(SecurityException.class, telephonyManager::getSubscriberId);
+ assertThrows(SecurityException.class, telephonyManager::getSimSerialNumber);
+ assertThrows(SecurityException.class, telephonyManager::getNai);
+ assertThrows(SecurityException.class, Build::getSerial);
+ } else {
+ assertNull(telephonyManager.getDeviceId());
+ assertNull(telephonyManager.getImei());
+ assertNull(telephonyManager.getMeid());
+ assertNull(telephonyManager.getSubscriberId());
+ assertNull(telephonyManager.getSimSerialNumber());
+ assertNull(telephonyManager.getNai());
+ assertNull(Build.getSerial());
}
}
}
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/CrossProfileTest.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/CrossProfileTest.java
new file mode 100644
index 0000000..795e34f
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/CrossProfileTest.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.cts.managedprofile;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.admin.DeviceAdminReceiver;
+import android.content.ComponentName;
+
+import java.util.Collections;
+import java.util.Set;
+
+/** App-side tests for interacting across profiles. */
+public class CrossProfileTest extends BaseManagedProfileTest {
+ private static final ComponentName NON_ADMIN_RECEIVER =
+ new ComponentName(
+ NonAdminReceiver.class.getPackage().getName(),
+ NonAdminReceiver.class.getName());
+
+ private static final Set<String> TEST_CROSS_PROFILE_PACKAGES =
+ Collections.singleton("test.package.name");
+
+ public void testSetCrossProfilePackages_notProfileOwner_throwsSecurityException() {
+ try {
+ mDevicePolicyManager.setCrossProfilePackages(
+ NON_ADMIN_RECEIVER, TEST_CROSS_PROFILE_PACKAGES);
+ fail("SecurityException excepted.");
+ } catch (SecurityException ignored) {}
+ }
+
+ public void testGetCrossProfilePackages_notProfileOwner_throwsSecurityException() {
+ try {
+ mDevicePolicyManager.getCrossProfilePackages(NON_ADMIN_RECEIVER);
+ fail("SecurityException expected.");
+ } catch (SecurityException ignored) {}
+ }
+
+ public void testGetCrossProfilePackages_notSet_returnsEmpty() {
+ assertThat(mDevicePolicyManager.getCrossProfilePackages(ADMIN_RECEIVER_COMPONENT))
+ .isEmpty();
+ }
+
+ public void testGetCrossProfilePackages_whenSet_returnsEqual() {
+ mDevicePolicyManager.setCrossProfilePackages(
+ ADMIN_RECEIVER_COMPONENT, TEST_CROSS_PROFILE_PACKAGES);
+ assertThat(mDevicePolicyManager.getCrossProfilePackages(ADMIN_RECEIVER_COMPONENT))
+ .isEqualTo(TEST_CROSS_PROFILE_PACKAGES);
+ }
+
+ public void testGetCrossProfilePackages_whenSetTwice_returnsLatestNotConcatenated() {
+ final Set<String> packages1 = Collections.singleton("test.package.name.1");
+ final Set<String> packages2 = Collections.singleton("test.package.name.2");
+
+ mDevicePolicyManager.setCrossProfilePackages(ADMIN_RECEIVER_COMPONENT, packages1);
+ mDevicePolicyManager.setCrossProfilePackages(ADMIN_RECEIVER_COMPONENT, packages2);
+
+ assertThat(mDevicePolicyManager.getCrossProfilePackages(ADMIN_RECEIVER_COMPONENT))
+ .isEqualTo(packages2);
+ }
+
+ private static class NonAdminReceiver extends DeviceAdminReceiver {}
+}
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/DeviceIdentifiersTest.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/DeviceIdentifiersTest.java
index edfd1bb..68c4d3c 100644
--- a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/DeviceIdentifiersTest.java
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/DeviceIdentifiersTest.java
@@ -15,6 +15,8 @@
*/
package com.android.cts.managedprofile;
+import static org.testng.Assert.assertThrows;
+
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Build;
@@ -24,9 +26,6 @@
* Verifies a profile owner on a personal device cannot access device identifiers.
*/
public class DeviceIdentifiersTest extends BaseManagedProfileTest {
- private static final String NO_SECURITY_EXCEPTION_ERROR_MESSAGE =
- "A profile owner that does not have the READ_PHONE_STATE permission must receive a "
- + "SecurityException when invoking %s";
public void testProfileOwnerOnPersonalDeviceCannotGetDeviceIdentifiers() throws Exception {
// The profile owner with the READ_PHONE_STATE permission should still receive a
@@ -37,64 +36,22 @@
// Allow the APIs to also return null if the telephony feature is not supported.
boolean hasTelephonyFeature =
mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY);
- try {
- String deviceId = telephonyManager.getDeviceId();
- if (hasTelephonyFeature) {
- fail(String.format(NO_SECURITY_EXCEPTION_ERROR_MESSAGE, "getDeviceId"));
- } else {
- assertEquals(null, deviceId);
- }
- } catch (SecurityException expected) {
- }
-
- try {
- String imei = telephonyManager.getImei();
- if (hasTelephonyFeature) {
- fail(String.format(NO_SECURITY_EXCEPTION_ERROR_MESSAGE, "getImei"));
- } else {
- assertEquals(null, imei);
- }
- } catch (SecurityException expected) {
- }
-
- try {
- String meid = telephonyManager.getMeid();
- if (hasTelephonyFeature) {
- fail(String.format(NO_SECURITY_EXCEPTION_ERROR_MESSAGE, "getMeid"));
- } else {
- assertEquals(null, meid);
- }
- } catch (SecurityException expected) {
- }
-
- try {
- String subscriberId = telephonyManager.getSubscriberId();
- if (hasTelephonyFeature) {
- fail(String.format(NO_SECURITY_EXCEPTION_ERROR_MESSAGE, "getSubscriberId"));
- } else {
- assertEquals(null, subscriberId);
- }
- } catch (SecurityException expected) {
- }
-
- try {
- String simSerialNumber = telephonyManager.getSimSerialNumber();
- if (hasTelephonyFeature) {
- fail(String.format(NO_SECURITY_EXCEPTION_ERROR_MESSAGE, "getSimSerialNumber"));
- } else {
- assertEquals(null, simSerialNumber);
- }
- } catch (SecurityException expected) {
- }
-
- try {
- String serial = Build.getSerial();
- if (hasTelephonyFeature) {
- fail(String.format(NO_SECURITY_EXCEPTION_ERROR_MESSAGE, "Build#getSerial"));
- } else {
- assertEquals(null, serial);
- }
- } catch (SecurityException expected) {
+ if (hasTelephonyFeature) {
+ assertThrows(SecurityException.class, telephonyManager::getDeviceId);
+ assertThrows(SecurityException.class, telephonyManager::getImei);
+ assertThrows(SecurityException.class, telephonyManager::getMeid);
+ assertThrows(SecurityException.class, telephonyManager::getSubscriberId);
+ assertThrows(SecurityException.class, telephonyManager::getSimSerialNumber);
+ assertThrows(SecurityException.class, telephonyManager::getNai);
+ assertThrows(SecurityException.class, Build::getSerial);
+ } else {
+ assertNull(telephonyManager.getDeviceId());
+ assertNull(telephonyManager.getImei());
+ assertNull(telephonyManager.getMeid());
+ assertNull(telephonyManager.getSubscriberId());
+ assertNull(telephonyManager.getSimSerialNumber());
+ assertNull(telephonyManager.getNai());
+ assertNull(Build.getSerial());
}
}
}
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/ParentProfileTest.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/ParentProfileTest.java
index aa221cc..a901d73 100644
--- a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/ParentProfileTest.java
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/ParentProfileTest.java
@@ -16,6 +16,8 @@
package com.android.cts.managedprofile;
+import static org.testng.Assert.assertThrows;
+
import android.app.admin.DevicePolicyManager;
import android.util.Log;
@@ -82,6 +84,9 @@
.add("setRequiredStrongAuthTimeout")
.add("isDeviceIdAttestationSupported")
.add("isUniqueDeviceAttestationSupported")
+ .add("wipeData")
+ .add("getAutoTime")
+ .add("setAutoTime")
.build();
private static final String LOG_TAG = "ParentProfileTest";
@@ -146,4 +151,18 @@
assertTrue(name + " is not found in the API list", allNames.contains(name));
}
}
+
+ public void testCannotWipeParentProfile() {
+ assertThrows(SecurityException.class,
+ () -> mParentDevicePolicyManager.wipeData(0));
+ }
+
+ public void testCannotCallAutoTimeMethodsOnParentProfile() {
+ assertThrows(SecurityException.class,
+ () -> mParentDevicePolicyManager.setAutoTime(ADMIN_RECEIVER_COMPONENT, true));
+
+ assertThrows(SecurityException.class,
+ () -> mParentDevicePolicyManager.getAutoTime(ADMIN_RECEIVER_COMPONENT));
+ }
+
}
diff --git a/hostsidetests/devicepolicy/app/TransferOwnerOutgoingApp/src/com/android/cts/transferowner/DeviceAndProfileOwnerTransferOutgoingTest.java b/hostsidetests/devicepolicy/app/TransferOwnerOutgoingApp/src/com/android/cts/transferowner/DeviceAndProfileOwnerTransferOutgoingTest.java
index 6aedd1b..bead632 100644
--- a/hostsidetests/devicepolicy/app/TransferOwnerOutgoingApp/src/com/android/cts/transferowner/DeviceAndProfileOwnerTransferOutgoingTest.java
+++ b/hostsidetests/devicepolicy/app/TransferOwnerOutgoingApp/src/com/android/cts/transferowner/DeviceAndProfileOwnerTransferOutgoingTest.java
@@ -146,16 +146,6 @@
}
@Test
- public void testClearDisallowAddManagedProfileRestriction() {
- setUserRestriction(UserManager.DISALLOW_ADD_MANAGED_PROFILE, false);
- }
-
- @Test
- public void testAddDisallowAddManagedProfileRestriction() {
- setUserRestriction(UserManager.DISALLOW_REMOVE_MANAGED_PROFILE, true);
- }
-
- @Test
public void testSetAffiliationId1() {
setAffiliationId("id.number.1");
}
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerHostSideTransferTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerHostSideTransferTest.java
index d12dbb3..89788c7 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerHostSideTransferTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerHostSideTransferTest.java
@@ -182,15 +182,7 @@
protected int setupManagedProfileOnDeviceOwner(String apkName, String adminReceiverClassName)
throws Exception {
- // Temporary disable the DISALLOW_ADD_MANAGED_PROFILE, so that we can create profile
- // using adb command.
- clearDisallowAddManagedProfileRestriction();
- try {
- return setupManagedProfile(apkName, adminReceiverClassName);
- } finally {
- // Adding back DISALLOW_ADD_MANAGED_PROFILE.
- addDisallowAddManagedProfileRestriction();
- }
+ return setupManagedProfile(apkName, adminReceiverClassName);
}
protected int setupManagedProfile(String apkName, String adminReceiverClassName)
@@ -207,28 +199,6 @@
return userId;
}
- /**
- * Clear {@link android.os.UserManager#DISALLOW_ADD_MANAGED_PROFILE}.
- */
- private void clearDisallowAddManagedProfileRestriction() throws Exception {
- runDeviceTestsAsUser(
- TRANSFER_OWNER_OUTGOING_PKG,
- mOutgoingTestClassName,
- "testClearDisallowAddManagedProfileRestriction",
- mPrimaryUserId);
- }
-
- /**
- * Add {@link android.os.UserManager#DISALLOW_ADD_MANAGED_PROFILE}.
- */
- private void addDisallowAddManagedProfileRestriction() throws Exception {
- runDeviceTestsAsUser(
- TRANSFER_OWNER_OUTGOING_PKG,
- mOutgoingTestClassName,
- "testAddDisallowAddManagedProfileRestriction",
- mPrimaryUserId);
- }
-
@Test
public void testTargetDeviceAdminServiceBound() throws Exception {
if (!mHasFeature) {
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java
index 191ef17..9e605d6 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java
@@ -1941,6 +1941,23 @@
}
@Test
+ public void testSetAutoTimeZone() throws Exception {
+ if (!mHasFeature) {
+ return;
+ }
+ assertMetricsLogged(getDevice(), () -> {
+ executeDeviceTestMethod(".TimeManagementTest", "testSetAutoTimeZone");
+ }, new DevicePolicyEventWrapper.Builder(EventId.SET_AUTO_TIME_ZONE_VALUE)
+ .setAdminPackageName(DEVICE_ADMIN_PKG)
+ .setBoolean(true)
+ .build(),
+ new DevicePolicyEventWrapper.Builder(EventId.SET_AUTO_TIME_ZONE_VALUE)
+ .setAdminPackageName(DEVICE_ADMIN_PKG)
+ .setBoolean(false)
+ .build());
+ }
+
+ @Test
public void testEnableSystemAppLogged() throws Exception {
if (!mHasFeature || !isStatsdEnabled(getDevice())) {
return;
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerPlusProfileOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerPlusProfileOwnerTest.java
index 33ec4fa..a6b791b 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerPlusProfileOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerPlusProfileOwnerTest.java
@@ -31,6 +31,7 @@
import com.android.cts.devicepolicy.metrics.DevicePolicyEventWrapper;
import com.android.cts.devicepolicy.metrics.DevicePolicyEventWrapper.Builder;
+import org.junit.Ignore;
import org.junit.Test;
import java.util.List;
@@ -239,19 +240,6 @@
verifyBindDeviceAdminServiceAsUser(secondaryUserId);
}
- @Test
- public void testCannotRemoveProfileIfRestrictionSet() throws Exception {
- if (!mHasFeature) {
- return;
- }
- int profileUserId = setupManagedProfile(COMP_DPC_APK2, COMP_DPC_PKG2, COMP_DPC_ADMIN2);
- addDisallowRemoveManagedProfileRestriction();
- assertFalse(getDevice().removeUser(profileUserId));
-
- clearDisallowRemoveManagedProfileRestriction();
- assertTrue(getDevice().removeUser(profileUserId));
- }
-
@FlakyTest(bugId = 141161038)
@Test
public void testCannotRemoveUserIfRestrictionSet() throws Exception {
@@ -285,7 +273,6 @@
}
int profileUserId = setupManagedProfile(COMP_DPC_APK, COMP_DPC_PKG, COMP_DPC_ADMIN);
addDisallowRemoveUserRestriction();
- addDisallowRemoveManagedProfileRestriction();
// The DO should be allowed to remove the managed profile, even though disallow remove user
// and disallow remove managed profile restrictions are set.
@@ -297,7 +284,10 @@
assertUserGetsRemoved(profileUserId);
}
+ //TODO(b/138709492) Re-enable once restriction on creating a work profile when there's
+ // a device owner is on by default.
@Test
+ @Ignore
public void testCannotAddProfileIfRestrictionSet() throws Exception {
if (!mHasFeature) {
return;
@@ -307,6 +297,7 @@
}
/**
+ * TODO(b/138709492): Remove this test as a part of the COMP deprecation.
* Both device owner and profile are the same package ({@link #COMP_DPC_PKG}).
*/
@Test
@@ -315,27 +306,18 @@
return;
}
installAppAsUser(COMP_DPC_APK2, mPrimaryUserId);
- // By default, disallow add managed profile is set, so provisioning a managed profile is
- // not allowed for DPCs other than the device owner.
- assertProvisionManagedProfileNotAllowed(COMP_DPC_PKG2);
- // But the device owner can still provision a managed profile because it owns the
- // restriction.
+ // Disallowing adding managed profile is no longer set by default, so every DPC can
+ // provision a work profile.
+ assertProvisionManagedProfileAllowed(COMP_DPC_PKG2);
+ // Including the device owner, which can still provision a managed profile.
assertProvisionManagedProfileAllowed(COMP_DPC_PKG);
setupManagedProfile(COMP_DPC_APK, COMP_DPC_PKG, COMP_DPC_ADMIN);
- clearDisallowAddManagedProfileRestriction();
// We've created a managed profile, but it's still possible to delete it to create a new
// one.
assertProvisionManagedProfileAllowed(COMP_DPC_PKG2);
assertProvisionManagedProfileAllowed(COMP_DPC_PKG);
-
- addDisallowRemoveManagedProfileRestriction();
- // Now we can't delete the managed profile any more to create a new one.
- assertProvisionManagedProfileNotAllowed(COMP_DPC_PKG2);
- // But if it is initiated by the device owner, it is still possible, because the device
- // owner itself has set the restriction
- assertProvisionManagedProfileAllowed(COMP_DPC_PKG);
}
@Test
@@ -344,7 +326,6 @@
return;
}
int profileUserId = setupManagedProfile(COMP_DPC_APK, COMP_DPC_PKG, COMP_DPC_ADMIN);
- addDisallowRemoveManagedProfileRestriction();
// The PO of the managed profile should be allowed to delete the managed profile, even
// though the disallow remove profile restriction is set.
runDeviceTestsAsUser(
@@ -361,7 +342,6 @@
return;
}
int profileUserId = setupManagedProfile(COMP_DPC_APK, COMP_DPC_PKG, COMP_DPC_ADMIN);
- addDisallowRemoveManagedProfileRestriction();
assertMetricsLogged(getDevice(), () -> {
runDeviceTestsAsUser(COMP_DPC_PKG, MANAGEMENT_TEST, "testWipeData", profileUserId);
}, WIPE_DATA_WITH_REASON_DEVICE_POLICY_EVENT);
@@ -624,24 +604,16 @@
/** Returns the user id of the newly created managed profile */
private int setupManagedProfile(String apkName, String packageName,
String adminReceiverClassName) throws Exception {
- // Temporary disable the DISALLOW_ADD_MANAGED_PROFILE, so that we can create profile
- // using adb command.
- clearDisallowAddManagedProfileRestriction();
- try {
- final int userId = createManagedProfile(mPrimaryUserId);
- installAppAsUser(apkName, userId);
- setProfileOwnerOrFail(adminReceiverClassName, userId);
- startUserAndWait(userId);
- runDeviceTestsAsUser(
- packageName,
- MANAGEMENT_TEST,
- "testIsManagedProfile",
- userId);
- return userId;
- } finally {
- // Adding back DISALLOW_ADD_MANAGED_PROFILE.
- addDisallowAddManagedProfileRestriction();
- }
+ final int userId = createManagedProfile(mPrimaryUserId);
+ installAppAsUser(apkName, userId);
+ setProfileOwnerOrFail(adminReceiverClassName, userId);
+ startUserAndWait(userId);
+ runDeviceTestsAsUser(
+ packageName,
+ MANAGEMENT_TEST,
+ "testIsManagedProfile",
+ userId);
+ return userId;
}
/** Returns the user id of the newly created secondary user */
@@ -671,50 +643,6 @@
}
/**
- * Clear {@link android.os.UserManager#DISALLOW_ADD_MANAGED_PROFILE}.
- */
- private void clearDisallowAddManagedProfileRestriction() throws Exception {
- runDeviceTestsAsUser(
- COMP_DPC_PKG,
- USER_RESTRICTION_TEST,
- "testClearDisallowAddManagedProfileRestriction",
- mPrimaryUserId);
- }
-
- /**
- * Add {@link android.os.UserManager#DISALLOW_ADD_MANAGED_PROFILE}.
- */
- private void addDisallowAddManagedProfileRestriction() throws Exception {
- runDeviceTestsAsUser(
- COMP_DPC_PKG,
- USER_RESTRICTION_TEST,
- "testAddDisallowAddManagedProfileRestriction",
- mPrimaryUserId);
- }
-
- /**
- * Clear {@link android.os.UserManager#DISALLOW_REMOVE_MANAGED_PROFILE}.
- */
- private void clearDisallowRemoveManagedProfileRestriction() throws Exception {
- runDeviceTestsAsUser(
- COMP_DPC_PKG,
- USER_RESTRICTION_TEST,
- "testClearDisallowRemoveManagedProfileRestriction",
- mPrimaryUserId);
- }
-
- /**
- * Add {@link android.os.UserManager#DISALLOW_REMOVE_MANAGED_PROFILE}.
- */
- private void addDisallowRemoveManagedProfileRestriction() throws Exception {
- runDeviceTestsAsUser(
- COMP_DPC_PKG,
- USER_RESTRICTION_TEST,
- "testAddDisallowRemoveManagedProfileRestriction",
- mPrimaryUserId);
- }
-
- /**
* Add {@link android.os.UserManager#DISALLOW_REMOVE_USER}.
*/
private void addDisallowRemoveUserRestriction() throws Exception {
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileCrossProfileTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileCrossProfileTest.java
index 640eb8b..5feb67a 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileCrossProfileTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileCrossProfileTest.java
@@ -320,6 +320,71 @@
runCrossProfileCalendarTestsWhenNotWhitelisted();
}
+ @Test
+ public void testSetCrossProfilePackages_notProfileOwner_throwsSecurityException()
+ throws Exception {
+ if (!mHasFeature) {
+ return;
+ }
+ runDeviceTestsAsUser(
+ MANAGED_PROFILE_PKG,
+ ".CrossProfileTest",
+ "testSetCrossProfilePackages_notProfileOwner_throwsSecurityException",
+ mProfileUserId);
+ }
+
+ @Test
+ public void testGetCrossProfilePackages_notProfileOwner_throwsSecurityException()
+ throws Exception {
+ if (!mHasFeature) {
+ return;
+ }
+ runDeviceTestsAsUser(
+ MANAGED_PROFILE_PKG,
+ ".CrossProfileTest",
+ "testGetCrossProfilePackages_notProfileOwner_throwsSecurityException",
+ mProfileUserId);
+ }
+
+ @Test
+ public void testGetCrossProfilePackages_notSet_returnsEmpty()
+ throws Exception {
+ if (!mHasFeature) {
+ return;
+ }
+ runDeviceTestsAsUser(
+ MANAGED_PROFILE_PKG,
+ ".CrossProfileTest",
+ "testGetCrossProfilePackages_notSet_returnsEmpty",
+ mProfileUserId);
+ }
+
+ @Test
+ public void testGetCrossProfilePackages_whenSetTwice_returnsLatestNotConcatenated()
+ throws Exception {
+ if (!mHasFeature) {
+ return;
+ }
+ runDeviceTestsAsUser(
+ MANAGED_PROFILE_PKG,
+ ".CrossProfileTest",
+ "testGetCrossProfilePackages_whenSetTwice_returnsLatestNotConcatenated",
+ mProfileUserId);
+ }
+
+ @Test
+ public void testGetCrossProfilePackages_whenSet_returnsEqual()
+ throws Exception {
+ if (!mHasFeature) {
+ return;
+ }
+ runDeviceTestsAsUser(
+ MANAGED_PROFILE_PKG,
+ ".CrossProfileTest",
+ "testGetCrossProfilePackages_whenSet_returnsEqual",
+ mProfileUserId);
+ }
+
@FlakyTest
@Test
public void testDisallowSharingIntoPersonalFromProfile() throws Exception {
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
index d4f920a..eb0d46b 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
@@ -224,6 +224,18 @@
"testParentProfileApiDisabled", mProfileUserId);
}
+ @Test
+ public void testCannotCallMethodsOnParentProfile() throws Exception {
+ if (!mHasFeature) {
+ return;
+ }
+ runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ParentProfileTest",
+ "testCannotWipeParentProfile", mProfileUserId);
+
+ runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ParentProfileTest",
+ "testCannotCallAutoTimeMethodsOnParentProfile", mProfileUserId);
+ }
+
// TODO: This test is not specific to managed profiles, but applies to multi-user in general.
// Move it to a MultiUserTest class when there is one. Should probably move
// SetPolicyActivity to a more generic apk too as it might be useful for different kinds
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/OrgOwnedProfileOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/OrgOwnedProfileOwnerTest.java
index a21d81e..f837274 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/OrgOwnedProfileOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/OrgOwnedProfileOwnerTest.java
@@ -18,8 +18,9 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.junit.Assert.assertTrue;
+
import android.platform.test.annotations.FlakyTest;
-import android.platform.test.annotations.LargeTest;
import com.android.tradefed.device.DeviceNotAvailableException;
@@ -40,6 +41,7 @@
private int mParentUserId = -1;
protected int mUserId;
private boolean mHasProfileToRemove = true;
+ private boolean mHasSecondaryProfileToRemove = false;
@Override
public void setUp() throws Exception {
@@ -73,6 +75,10 @@
removeOrgOwnedProfile();
removeUser(mUserId);
}
+ if (mHasSecondaryProfileToRemove) {
+ removeTestUsers();
+ getDevice().uninstallPackage(DEVICE_ADMIN_PKG);
+ }
super.tearDown();
}
@@ -145,6 +151,33 @@
runDeviceTestsAsUser(DEVICE_ADMIN_PKG, ".OrgOwnedProfileOwnerParentTest", mUserId);
}
+ @Test
+ public void testUserRestrictionsSetOnParentAreNotPersisted() throws Exception {
+ if (!mHasFeature) {
+ return;
+ }
+ int secondaryUserId = createUser();
+ setPoAsUser(secondaryUserId);
+ mHasSecondaryProfileToRemove = true;
+
+ runDeviceTestsAsUser(DEVICE_ADMIN_PKG, ".UserRestrictionsParentTest",
+ "testAddUserRestriction_onParent", mUserId);
+ runDeviceTestsAsUser(DEVICE_ADMIN_PKG, ".UserRestrictionsParentTest",
+ "testHasUserRestriction", mUserId);
+ runDeviceTestsAsUser(DEVICE_ADMIN_PKG, ".UserRestrictionsParentTest",
+ "testHasUserRestriction", secondaryUserId);
+ removeOrgOwnedProfile();
+ assertHasNoUser(mUserId);
+ mHasProfileToRemove = false;
+
+ // Make sure the user restrictions are removed before continuing
+ waitForBroadcastIdle();
+
+ // User restrictions are not persist after organization-owned profile owner is removed
+ runDeviceTestsAsUser(DEVICE_ADMIN_PKG, ".UserRestrictionsParentTest",
+ "testUserRestrictionAreNotPersisted", secondaryUserId);
+ }
+
@FlakyTest(bugId = 137088260)
@Test
public void testWifi() throws Exception {
@@ -172,4 +205,12 @@
assertThat(listUsers()).doesNotContain(userId);
}
+
+ private void setPoAsUser(int userId) throws Exception {
+ installAppAsUser(DEVICE_ADMIN_APK, true, true, userId);
+ assertTrue("Failed to set profile owner",
+ setProfileOwner(DEVICE_ADMIN_PKG + "/" + ADMIN_RECEIVER_TEST_CLASS,
+ userId, /* expectFailure */ false));
+ }
+
}
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/UserRestrictionsTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/UserRestrictionsTest.java
index 2a5c117..331b2e2 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/UserRestrictionsTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/UserRestrictionsTest.java
@@ -17,8 +17,6 @@
import static org.junit.Assert.assertTrue;
-import android.platform.test.annotations.FlakyTest;
-
import com.android.tradefed.device.DeviceNotAvailableException;
import org.junit.Test;
@@ -137,7 +135,6 @@
}
// Checks restrictions for managed profile.
- @FlakyTest
@Test
public void testUserRestrictions_managedProfileOwnerOnly() throws Exception {
if (!mHasFeature || !mSupportsMultiUser || !mHasManagedUserFeature) {
@@ -161,7 +158,6 @@
/**
* DO + PO combination. Make sure global DO restrictions are visible on secondary users.
*/
- @FlakyTest
@Test
public void testUserRestrictions_layering() throws Exception {
if (!mHasFeature || !mSupportsMultiUser) {
@@ -230,7 +226,6 @@
* DO sets profile global restrictions (only ENSURE_VERIFY_APPS), should affect all
* users (not a particularly special case but to be sure).
*/
- @FlakyTest
@Test
public void testUserRestrictions_profileGlobalRestrictionsAsDo() throws Exception {
if (!mHasFeature || !mSupportsMultiUser) {
@@ -252,7 +247,6 @@
* Managed profile owner sets profile global restrictions (only ENSURE_VERIFY_APPS), should
* affect all users.
*/
- @FlakyTest
@Test
public void testUserRestrictions_ProfileGlobalRestrictionsAsPo() throws Exception {
if (!mHasFeature || !mSupportsMultiUser || !mHasManagedUserFeature) {
@@ -276,7 +270,8 @@
/** Installs admin package and makes it a profile owner for a given user. */
private void setPoAsUser(int userId) throws Exception {
- installAppAsUser(DEVICE_ADMIN_APK, userId);
+ installAppAsUser(DEVICE_ADMIN_APK, /* grantPermssions= */true,
+ /* dontKillApp= */ true, userId);
assertTrue("Failed to set profile owner",
setProfileOwner(DEVICE_ADMIN_PKG + "/" + ADMIN_RECEIVER_TEST_CLASS,
userId, /* expectFailure */ false));
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/HdmiCecVendorCommandsTest.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/HdmiCecVendorCommandsTest.java
index 49c5b3b..d4111d4 100644
--- a/hostsidetests/hdmicec/src/android/hdmicec/cts/HdmiCecVendorCommandsTest.java
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/HdmiCecVendorCommandsTest.java
@@ -52,7 +52,7 @@
/**
* Test 11.2.9-2
- * Tests that the device broadcasts a <DEVICE_VENDOR_ID> message after successfull
+ * Tests that the device broadcasts a <DEVICE_VENDOR_ID> message after successful
* initialisation and address allocation.
*/
@Test
diff --git a/hostsidetests/incident/src/com/android/server/cts/GraphicsStatsValidationTest.java b/hostsidetests/incident/src/com/android/server/cts/GraphicsStatsValidationTest.java
index 90b78fc..1356600 100644
--- a/hostsidetests/incident/src/com/android/server/cts/GraphicsStatsValidationTest.java
+++ b/hostsidetests/incident/src/com/android/server/cts/GraphicsStatsValidationTest.java
@@ -126,8 +126,8 @@
assertTrue(jankyDelta < 25);
int gt150msDelta = countFramesAbove(statsAfter, 150) - countFramesAbove(statsBefore, 150);
- assertTrue(gt150msDelta >= 20); // 10 davey jrs + 10 daveys + maybe first frame
- assertTrue(gt150msDelta <= 21);
+ assertTrue(gt150msDelta >= 20); // 10 davey jrs + 10 daveys + maybe first 2 frames
+ assertTrue(gt150msDelta <= 22);
int gt700msDelta = countFramesAbove(statsAfter, 700) - countFramesAbove(statsBefore, 700);
assertEquals(10, gt700msDelta); // 10 daveys
}
diff --git a/hostsidetests/net/app/src/com/android/cts/net/hostside/VpnTest.java b/hostsidetests/net/app/src/com/android/cts/net/hostside/VpnTest.java
index c43d421..26397ef 100755
--- a/hostsidetests/net/app/src/com/android/cts/net/hostside/VpnTest.java
+++ b/hostsidetests/net/app/src/com/android/cts/net/hostside/VpnTest.java
@@ -20,6 +20,7 @@
import static android.system.OsConstants.*;
import android.annotation.Nullable;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
@@ -33,6 +34,7 @@
import android.net.ProxyInfo;
import android.net.VpnService;
import android.net.wifi.WifiManager;
+import android.provider.Settings;
import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.os.SystemProperties;
@@ -62,8 +64,11 @@
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
+import java.net.SocketException;
+import java.net.UnknownHostException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
+import java.util.Objects;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -95,6 +100,13 @@
*/
public class VpnTest extends InstrumentationTestCase {
+ // These are neither public nor @TestApi.
+ // TODO: add them to @TestApi.
+ private static final String PRIVATE_DNS_MODE_SETTING = "private_dns_mode";
+ private static final String PRIVATE_DNS_MODE_PROVIDER_HOSTNAME = "hostname";
+ private static final String PRIVATE_DNS_MODE_OPPORTUNISTIC = "opportunistic";
+ private static final String PRIVATE_DNS_SPECIFIER_SETTING = "private_dns_specifier";
+
public static String TAG = "VpnTest";
public static int TIMEOUT_MS = 3 * 1000;
public static int SOCKET_TIMEOUT_MS = 100;
@@ -112,6 +124,9 @@
final Object mLock = new Object();
final Object mLockShutdown = new Object();
+ private String mOldPrivateDnsMode;
+ private String mOldPrivateDnsSpecifier;
+
private boolean supportedHardware() {
final PackageManager pm = getInstrumentation().getContext().getPackageManager();
return !pm.hasSystemFeature("android.hardware.type.watch");
@@ -123,6 +138,7 @@
mNetwork = null;
mCallback = null;
+ storePrivateDnsSetting();
mDevice = UiDevice.getInstance(getInstrumentation());
mActivity = launchActivity(getInstrumentation().getTargetContext().getPackageName(),
@@ -137,6 +153,7 @@
@Override
public void tearDown() throws Exception {
+ restorePrivateDnsSetting();
mRemoteSocketFactoryClient.unbind();
if (mCallback != null) {
mCM.unregisterNetworkCallback(mCallback);
@@ -567,6 +584,95 @@
}
}
+ private ContentResolver getContentResolver() {
+ return getInstrumentation().getContext().getContentResolver();
+ }
+
+ private boolean isPrivateDnsInStrictMode() {
+ return PRIVATE_DNS_MODE_PROVIDER_HOSTNAME.equals(
+ Settings.Global.getString(getContentResolver(), PRIVATE_DNS_MODE_SETTING));
+ }
+
+ private void storePrivateDnsSetting() {
+ mOldPrivateDnsMode = Settings.Global.getString(getContentResolver(),
+ PRIVATE_DNS_MODE_SETTING);
+ mOldPrivateDnsSpecifier = Settings.Global.getString(getContentResolver(),
+ PRIVATE_DNS_SPECIFIER_SETTING);
+ }
+
+ private void restorePrivateDnsSetting() {
+ Settings.Global.putString(getContentResolver(), PRIVATE_DNS_MODE_SETTING,
+ mOldPrivateDnsMode);
+ Settings.Global.putString(getContentResolver(), PRIVATE_DNS_SPECIFIER_SETTING,
+ mOldPrivateDnsSpecifier);
+ }
+
+ // TODO: replace with CtsNetUtils.awaitPrivateDnsSetting in Q or above.
+ private void expectPrivateDnsHostname(final String hostname) throws Exception {
+ final NetworkRequest request = new NetworkRequest.Builder()
+ .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
+ .build();
+ final CountDownLatch latch = new CountDownLatch(1);
+ final NetworkCallback callback = new NetworkCallback() {
+ @Override
+ public void onLinkPropertiesChanged(Network network, LinkProperties lp) {
+ if (network.equals(mNetwork) &&
+ Objects.equals(lp.getPrivateDnsServerName(), hostname)) {
+ latch.countDown();
+ }
+ }
+ };
+
+ mCM.registerNetworkCallback(request, callback);
+
+ try {
+ assertTrue("Private DNS hostname was not " + hostname + " after " + TIMEOUT_MS + "ms",
+ latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ } finally {
+ mCM.unregisterNetworkCallback(callback);
+ }
+ }
+
+ private void setAndVerifyPrivateDns(boolean strictMode) throws Exception {
+ final ContentResolver cr = getInstrumentation().getContext().getContentResolver();
+ String privateDnsHostname;
+
+ if (strictMode) {
+ privateDnsHostname = "vpncts-nx.metric.gstatic.com";
+ Settings.Global.putString(cr, PRIVATE_DNS_SPECIFIER_SETTING, privateDnsHostname);
+ Settings.Global.putString(cr, PRIVATE_DNS_MODE_SETTING,
+ PRIVATE_DNS_MODE_PROVIDER_HOSTNAME);
+ } else {
+ Settings.Global.putString(cr, PRIVATE_DNS_MODE_SETTING, PRIVATE_DNS_MODE_OPPORTUNISTIC);
+ privateDnsHostname = null;
+ }
+
+ expectPrivateDnsHostname(privateDnsHostname);
+
+ String randomName = "vpncts-" + new Random().nextInt(1000000000) + "-ds.metric.gstatic.com";
+ if (strictMode) {
+ // Strict mode private DNS is enabled. DNS lookups should fail, because the private DNS
+ // server name is invalid.
+ try {
+ InetAddress.getByName(randomName);
+ fail("VPN DNS lookup should fail with private DNS enabled");
+ } catch (UnknownHostException expected) {
+ }
+ } else {
+ // Strict mode private DNS is disabled. DNS lookup should succeed, because the VPN
+ // provides no DNS servers, and thus DNS falls through to the default network.
+ assertNotNull("VPN DNS lookup should succeed with private DNS disabled",
+ InetAddress.getByName(randomName));
+ }
+ }
+
+ // Tests that strict mode private DNS is used on VPNs.
+ private void checkStrictModePrivateDns() throws Exception {
+ final boolean initialMode = isPrivateDnsInStrictMode();
+ setAndVerifyPrivateDns(!initialMode);
+ setAndVerifyPrivateDns(initialMode);
+ }
+
public void testDefault() throws Exception {
if (!supportedHardware()) return;
// If adb TCP port opened, this test may running by adb over network.
@@ -598,6 +704,9 @@
assertSocketClosed(fd, TEST_HOST);
checkTrafficOnVpn();
+
+ checkStrictModePrivateDns();
+
receiver.unregisterQuietly();
}
@@ -615,6 +724,8 @@
assertSocketClosed(fd, TEST_HOST);
checkTrafficOnVpn();
+
+ checkStrictModePrivateDns();
}
public void testAppDisallowed() throws Exception {
diff --git a/hostsidetests/security/src/android/cts/security/KernelConfigTest.java b/hostsidetests/security/src/android/cts/security/KernelConfigTest.java
index 82518da..cdd87fb 100644
--- a/hostsidetests/security/src/android/cts/security/KernelConfigTest.java
+++ b/hostsidetests/security/src/android/cts/security/KernelConfigTest.java
@@ -228,14 +228,19 @@
*/
@CddTest(requirement="9.7")
public void testConfigHardwareMitigations() throws Exception {
+ String mitigations[];
+
if (PropertyUtil.getFirstApiLevel(mDevice) < 28) {
return;
}
if (CpuFeatures.isArm64(mDevice) && !CpuFeatures.kernelVersionLessThan(mDevice, 4, 4)) {
- for (String mitigation : lookupMitigations()) {
- assertTrue("Linux kernel must have " + mitigation + " enabled.",
- configSet.contains(mitigation));
+ mitigations = lookupMitigations();
+ if (mitigations != null) {
+ for (String mitigation : mitigations) {
+ assertTrue("Linux kernel must have " + mitigation + " enabled.",
+ configSet.contains(mitigation));
+ }
}
} else if (CpuFeatures.isX86(mDevice)) {
assertTrue("Linux kernel must have KPTI enabled: CONFIG_PAGE_TABLE_ISOLATION=y",
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2016-2460/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2016-2460/Android.bp
index af352aa..b31a788 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2016-2460/Android.bp
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2016-2460/Android.bp
@@ -23,7 +23,6 @@
"libutils",
"liblog",
"libmedia",
- "libsoundtrigger",
"libgui",
],
ldflags: [
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2016-5862/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2016-5862/Android.mk
index c368779..d6efe13 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2016-5862/Android.mk
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2016-5862/Android.mk
@@ -7,7 +7,7 @@
LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
-LOCAL_COMPATIBILITY_SUITE := cts sts
+LOCAL_COMPATIBILITY_SUITE := cts sts vts
LOCAL_CTS_TEST_PACKAGE := android.security.cts
LOCAL_ARM_MODE := arm
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2016-5867/Android.mk b/hostsidetests/securitybulletin/securityPatch/CVE-2016-5867/Android.mk
index f7968eb..d7f4ae9 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2016-5867/Android.mk
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2016-5867/Android.mk
@@ -7,7 +7,7 @@
LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
-LOCAL_COMPATIBILITY_SUITE := cts sts
+LOCAL_COMPATIBILITY_SUITE := cts sts vts
LOCAL_CTS_TEST_PACKAGE := android.security.cts
LOCAL_ARM_MODE := arm
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2017-0479/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2017-0479/Android.bp
index e811dd3..2604551 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2017-0479/Android.bp
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2017-0479/Android.bp
@@ -22,5 +22,6 @@
"libbinder",
"libandroid",
"libaudioclient",
+ "libaudiofoundation",
],
}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2017-0479/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2017-0479/poc.cpp
index 3fc6329..0c64210 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2017-0479/poc.cpp
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2017-0479/poc.cpp
@@ -75,10 +75,11 @@
gEffect = NULL;
pthread_t pt;
const sp<IAudioFlinger> &audioFlinger = AudioSystem::get_audio_flinger();
+ AudioDeviceTypeAddr device;
for (i=0; i<100; i++) {
gEffect = audioFlinger->createEffect(&descriptor, effectClient, priority,
- io, sessionId, opPackageName, getpid(),
+ io, sessionId, device, opPackageName, getpid(),
&err, &id, &enabled);
if (gEffect == NULL || err != NO_ERROR) {
return -1;
diff --git a/hostsidetests/securitybulletin/securityPatch/pac/Android.mk b/hostsidetests/securitybulletin/securityPatch/pac/Android.mk
index bd9c07d..1960664 100644
--- a/hostsidetests/securitybulletin/securityPatch/pac/Android.mk
+++ b/hostsidetests/securitybulletin/securityPatch/pac/Android.mk
@@ -27,7 +27,7 @@
LOCAL_SHARED_LIBRARIES := \
libpac \
-LOCAL_COMPATIBILITY_SUITE := cts sts
+LOCAL_COMPATIBILITY_SUITE := cts sts vts
LOCAL_CTS_TEST_PACKAGE := android.security.cts
LOCAL_ARM_MODE := arm
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/AdbUtils.java b/hostsidetests/securitybulletin/src/android/security/cts/AdbUtils.java
index 93b5cd9..3e4f5b3 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/AdbUtils.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/AdbUtils.java
@@ -408,27 +408,12 @@
AdbUtils.runCommandLine("rm /data/local/tmp/" + tempFile, device);
}
}
- if (test_failed == true) {
- Assert.fail("PoC was interrupted");
+ if (test_failed) {
+ fail("PoC was interrupted");
}
}
if (t.isAlive()) {
Assert.fail("PoC not completed within timeout of " + timeout + " ms");
}
}
-
- /**
- * Raises assert exception upon crash/error occurence
- *
- * @param crashPatternList array of crash log patterns to be checked for
- * @param logcat String to be parsed
- */
- public static void checkCrash(String crashPatternList[], String logcat)
- throws Exception {
- for (String crashPattern : crashPatternList) {
- assertFalse("Crash log pattern found!",
- Pattern.compile(crashPattern, Pattern.MULTILINE)
- .matcher(logcat).find());
- }
- }
}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/TestMedia.java b/hostsidetests/securitybulletin/src/android/security/cts/TestMedia.java
index bbfd78e..ecc086c 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/TestMedia.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/TestMedia.java
@@ -45,41 +45,6 @@
* before any existing test methods
****************************************************************/
-
- /**
- * Checks for linker errors
- *
- * @param binaryName name of the binary
- * @param logcat String to be parsed
- */
- public static boolean isLinkerErrorPresent(String binaryName, String logcat)
- throws Exception {
- return Pattern
- .compile("CANNOT LINK EXECUTABLE \"" + TMP_FILE_PATH
- + binaryName + "\"", Pattern.MULTILINE)
- .matcher(logcat).find();
- }
-
- /**
- * Checks for crash
- *
- * @param binaryName Name of the binary
- * @param errPattern error patterns to be checked for
- * @param logcat String to be parsed
- */
- public static void checkCrash(String binaryName, String errPattern[],
- String logcat) throws Exception {
- String genericCrashPattern[] = {
- "name: " + binaryName + " >>> " + TMP_FILE_PATH + binaryName
- + " <<<\n.*?SIGABRT",
- "name: " + binaryName + " >>> " + TMP_FILE_PATH + binaryName
- + " <<<\n.*?SIGSEGV"};
- AdbUtils.checkCrash(genericCrashPattern, logcat);
- if (errPattern != null) {
- AdbUtils.checkCrash(errPattern, logcat);
- }
- }
-
/**
* Pushes input files, runs the PoC and checks for crash and hang
*
@@ -91,7 +56,7 @@
*/
public static void runMediaTest(String binaryName,
String inputFiles[], String arguments, ITestDevice device,
- String errPattern[]) throws Exception {
+ String processPatternStrings[]) throws Exception {
if (inputFiles != null) {
for (String tempFile : inputFiles) {
AdbUtils.pushResource(RESOURCE_ROOT + tempFile,
@@ -110,10 +75,10 @@
}
}
}, TIMEOUT_SEC * 1000, device, inputFiles);
- String logcatOut = AdbUtils.runCommandLine("logcat -d", device);
- boolean linkerErrorFound = isLinkerErrorPresent(binaryName, logcatOut);
- if (!linkerErrorFound) {
- checkCrash(binaryName, errPattern, logcatOut);
+
+ AdbUtils.assertNoCrashes(device, binaryName);
+ if (processPatternStrings != null) {
+ AdbUtils.assertNoCrashes(device, processPatternStrings);
}
}
}
diff --git a/hostsidetests/stagedinstall/app/src/com/android/tests/stagedinstall/StagedInstallTest.java b/hostsidetests/stagedinstall/app/src/com/android/tests/stagedinstall/StagedInstallTest.java
index 2117543..5af74b4 100644
--- a/hostsidetests/stagedinstall/app/src/com/android/tests/stagedinstall/StagedInstallTest.java
+++ b/hostsidetests/stagedinstall/app/src/com/android/tests/stagedinstall/StagedInstallTest.java
@@ -274,7 +274,17 @@
public void testGetActiveStagedSessions() throws Exception {
PackageInstaller packageInstaller = getPackageInstaller();
int firstSessionId = stageSingleApk(TestApp.A1).assertSuccessful().getSessionId();
+ // Currently abandoning a session before pre-reboot verification finishes might result in
+ // a system_server crash. Before that issue is resolved we need to manually wait for
+ // pre-reboot verification to finish before abandoning sessions.
+ // TODO(b/145925842): remove following two lines after fixing the bug.
+ waitForIsReadyBroadcast(firstSessionId);
int secondSessionId = stageSingleApk(TestApp.B1).assertSuccessful().getSessionId();
+ // Currently abandoning a session before pre-reboot verification finishes might result in
+ // a system_server crash. Before that issue is resolved we need to manually wait for
+ // pre-reboot verification to finish before abandoning sessions.
+ // TODO(b/145925842): remove following two lines after fixing the bug.
+ waitForIsReadyBroadcast(secondSessionId);
List<Integer> stagedSessionIds = packageInstaller.getActiveStagedSessions()
.stream().map(s -> s.getSessionId()).collect(Collectors.toList());
assertThat(stagedSessionIds).hasSize(2);
@@ -293,8 +303,17 @@
public void testGetActiveStagedSessions_MultiApkSession() throws Exception {
int firstSessionId = stageMultipleApks(TestApp.A1, TestApp.B1)
.assertSuccessful().getSessionId();
+ // Currently abandoning a session before pre-reboot verification finishes might result in
+ // a system_server crash. Before that issue is resolved we need to manually wait for
+ // pre-reboot verification to finish before abandoning sessions.
+ // TODO(b/145925842): remove following two lines after fixing the bug.
+ waitForIsReadyBroadcast(firstSessionId);
int secondSessionId = stageMultipleApks(TestApp.C1)
.assertSuccessful().getSessionId();
+ // Currently abandoning a session before pre-reboot verification finishes might result in
+ // a system_server crash. Before that issue is resolved we need to manually wait for
+ // pre-reboot verification to finish before abandoning sessions.
+ waitForIsReadyBroadcast(secondSessionId);
List<Integer> stagedSessionIds = getPackageInstaller().getActiveStagedSessions()
.stream().map(s -> s.getSessionId()).collect(Collectors.toList());
assertThat(stagedSessionIds).hasSize(2);
@@ -684,8 +703,7 @@
public void testRejectsApexDifferentCertificate() throws Exception {
int sessionId = stageSingleApk(Apex2DifferentCertificate)
.assertSuccessful().getSessionId();
- PackageInstaller.SessionInfo info =
- SessionUpdateBroadcastReceiver.sessionBroadcasts.poll(60, TimeUnit.SECONDS);
+ PackageInstaller.SessionInfo info = waitForBroadcast(sessionId);
assertThat(info.getSessionId()).isEqualTo(sessionId);
assertThat(info).isStagedSessionFailed();
assertThat(info.getStagedSessionErrorMessage()).contains("is not compatible with the one "
@@ -776,33 +794,59 @@
// Should fail to stage multiple sessions when check-point is not available
@Test
public void testFailStagingMultipleSessionsIfNoCheckPoint() throws Exception {
- stageSingleApk(TestApp.A1).assertSuccessful();
+ int sessionId = stageSingleApk(TestApp.A1).assertSuccessful().getSessionId();
StageSessionResult failedSessionResult = stageSingleApk(TestApp.B1);
assertThat(failedSessionResult.getErrorMessage()).contains(
"Cannot stage multiple sessions without checkpoint support");
+ // Currently abandoning a session before pre-reboot verification finishes might result in
+ // a system_server crash. Before that issue is resolved we need to manually wait for
+ // pre-reboot verification to finish before abandoning sessions.
+ // TODO(b/145925842): remove following two lines after fixing the bug.
+ waitForIsReadyBroadcast(sessionId);
}
@Test
public void testFailOverlappingMultipleStagedInstall_BothSinglePackage_Apk() throws Exception {
- stageSingleApk(TestApp.A1).assertSuccessful();
+ int sessionId = stageSingleApk(TestApp.A1).assertSuccessful().getSessionId();
StageSessionResult failedSessionResult = stageSingleApk(TestApp.A1);
assertThat(failedSessionResult.getErrorMessage()).contains(
"has been staged already by session");
+ // Currently abandoning a session before pre-reboot verification finishes might result in
+ // a system_server crash. Before that issue is resolved we need to manually wait for
+ // pre-reboot verification to finish before abandoning sessions.
+ // TODO(b/145925842): remove following two lines after fixing the bug.
+ waitForIsReadyBroadcast(sessionId);
}
@Test
public void testAllowNonOverlappingMultipleStagedInstall_MultiPackageSinglePackage_Apk()
throws Exception {
- stageMultipleApks(TestApp.A1, TestApp.B1).assertSuccessful();
- stageSingleApk(TestApp.C1).assertSuccessful();
+ int firstSessionId = stageMultipleApks(TestApp.A1, TestApp.B1).assertSuccessful()
+ .getSessionId();
+ // Currently abandoning a session before pre-reboot verification finishes might result in
+ // a system_server crash. Before that issue is resolved we need to manually wait for
+ // pre-reboot verification to finish before abandoning sessions.
+ // TODO(b/145925842): remove following two lines after fixing the bug.
+ waitForIsReadyBroadcast(firstSessionId);
+ int secondSessionId = stageSingleApk(TestApp.C1).assertSuccessful().getSessionId();
+ // Currently abandoning a session before pre-reboot verification finishes might result in
+ // a system_server crash. Before that issue is resolved we need to manually wait for
+ // pre-reboot verification to finish before abandoning sessions.
+ // TODO(b/145925842): remove following two lines after fixing the bug.
+ waitForIsReadyBroadcast(secondSessionId);
}
@Test
public void testFailOverlappingMultipleStagedInstall_BothMultiPackage_Apk() throws Exception {
- stageMultipleApks(TestApp.A1, TestApp.B1).assertSuccessful();
+ int sessionId = stageMultipleApks(TestApp.A1, TestApp.B1).assertSuccessful().getSessionId();
StageSessionResult failedSessionResult = stageMultipleApks(TestApp.A2, TestApp.C1);
assertThat(failedSessionResult.getErrorMessage()).contains(
"has been staged already by session");
+ // Currently abandoning a session before pre-reboot verification finishes might result in
+ // a system_server crash. Before that issue is resolved we need to manually wait for
+ // pre-reboot verification to finish before abandoning sessions.
+ // TODO(b/145925842): remove following two lines after fixing the bug.
+ waitForIsReadyBroadcast(sessionId);
}
@Test
diff --git a/hostsidetests/stagedinstall/testdata/apex/com.android.apex.cts.shim.v1.apex b/hostsidetests/stagedinstall/testdata/apex/com.android.apex.cts.shim.v1.apex
index 6b838dd..e3bdbdd 100644
--- a/hostsidetests/stagedinstall/testdata/apex/com.android.apex.cts.shim.v1.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/com.android.apex.cts.shim.v1.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/com.android.apex.cts.shim.v2.apex b/hostsidetests/stagedinstall/testdata/apex/com.android.apex.cts.shim.v2.apex
index 91096d5..5f05659 100644
--- a/hostsidetests/stagedinstall/testdata/apex/com.android.apex.cts.shim.v2.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/com.android.apex.cts.shim.v2.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/com.android.apex.cts.shim.v2_additional_file.apex b/hostsidetests/stagedinstall/testdata/apex/com.android.apex.cts.shim.v2_additional_file.apex
index 23ae628..680dfb2 100644
--- a/hostsidetests/stagedinstall/testdata/apex/com.android.apex.cts.shim.v2_additional_file.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/com.android.apex.cts.shim.v2_additional_file.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/com.android.apex.cts.shim.v2_additional_folder.apex b/hostsidetests/stagedinstall/testdata/apex/com.android.apex.cts.shim.v2_additional_folder.apex
index 0438269..6103b50 100644
--- a/hostsidetests/stagedinstall/testdata/apex/com.android.apex.cts.shim.v2_additional_folder.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/com.android.apex.cts.shim.v2_additional_folder.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/com.android.apex.cts.shim.v2_different_certificate.apex b/hostsidetests/stagedinstall/testdata/apex/com.android.apex.cts.shim.v2_different_certificate.apex
index 8f38f3f..cf0e800 100644
--- a/hostsidetests/stagedinstall/testdata/apex/com.android.apex.cts.shim.v2_different_certificate.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/com.android.apex.cts.shim.v2_different_certificate.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/com.android.apex.cts.shim.v2_signed_bob.apex b/hostsidetests/stagedinstall/testdata/apex/com.android.apex.cts.shim.v2_signed_bob.apex
index b43ad69..0af717c 100644
--- a/hostsidetests/stagedinstall/testdata/apex/com.android.apex.cts.shim.v2_signed_bob.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/com.android.apex.cts.shim.v2_signed_bob.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/com.android.apex.cts.shim.v2_signed_bob_rot.apex b/hostsidetests/stagedinstall/testdata/apex/com.android.apex.cts.shim.v2_signed_bob_rot.apex
index 81f0ee9..d3f7014 100644
--- a/hostsidetests/stagedinstall/testdata/apex/com.android.apex.cts.shim.v2_signed_bob_rot.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/com.android.apex.cts.shim.v2_signed_bob_rot.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/com.android.apex.cts.shim.v2_signed_bob_rot_rollback.apex b/hostsidetests/stagedinstall/testdata/apex/com.android.apex.cts.shim.v2_signed_bob_rot_rollback.apex
index 4b7ae32..05f1cbb 100644
--- a/hostsidetests/stagedinstall/testdata/apex/com.android.apex.cts.shim.v2_signed_bob_rot_rollback.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/com.android.apex.cts.shim.v2_signed_bob_rot_rollback.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/com.android.apex.cts.shim.v2_with_post_install_hook.apex b/hostsidetests/stagedinstall/testdata/apex/com.android.apex.cts.shim.v2_with_post_install_hook.apex
index 1bc260d..37acf43 100644
--- a/hostsidetests/stagedinstall/testdata/apex/com.android.apex.cts.shim.v2_with_post_install_hook.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/com.android.apex.cts.shim.v2_with_post_install_hook.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/com.android.apex.cts.shim.v2_with_pre_install_hook.apex b/hostsidetests/stagedinstall/testdata/apex/com.android.apex.cts.shim.v2_with_pre_install_hook.apex
index 0066f3a..c82c1e0 100644
--- a/hostsidetests/stagedinstall/testdata/apex/com.android.apex.cts.shim.v2_with_pre_install_hook.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/com.android.apex.cts.shim.v2_with_pre_install_hook.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/com.android.apex.cts.shim.v2_wrong_sha.apex b/hostsidetests/stagedinstall/testdata/apex/com.android.apex.cts.shim.v2_wrong_sha.apex
index afd33f9..d9905a8 100644
--- a/hostsidetests/stagedinstall/testdata/apex/com.android.apex.cts.shim.v2_wrong_sha.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/com.android.apex.cts.shim.v2_wrong_sha.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/com.android.apex.cts.shim.v3.apex b/hostsidetests/stagedinstall/testdata/apex/com.android.apex.cts.shim.v3.apex
index 71fa484..dfb6757 100644
--- a/hostsidetests/stagedinstall/testdata/apex/com.android.apex.cts.shim.v3.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/com.android.apex.cts.shim.v3.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/com.android.apex.cts.shim.v3_signed_bob.apex b/hostsidetests/stagedinstall/testdata/apex/com.android.apex.cts.shim.v3_signed_bob.apex
index 77c5679..ca32c0d 100644
--- a/hostsidetests/stagedinstall/testdata/apex/com.android.apex.cts.shim.v3_signed_bob.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/com.android.apex.cts.shim.v3_signed_bob.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/com.android.apex.cts.shim.v3_signed_bob_rot.apex b/hostsidetests/stagedinstall/testdata/apex/com.android.apex.cts.shim.v3_signed_bob_rot.apex
index 124f769..befa6b2 100644
--- a/hostsidetests/stagedinstall/testdata/apex/com.android.apex.cts.shim.v3_signed_bob_rot.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/com.android.apex.cts.shim.v3_signed_bob_rot.apex
Binary files differ
diff --git a/hostsidetests/stagedinstall/testdata/apex/com.android.apex.cts.shim_not_pre_installed.apex b/hostsidetests/stagedinstall/testdata/apex/com.android.apex.cts.shim_not_pre_installed.apex
index b9abc3d..6e5b1c6 100644
--- a/hostsidetests/stagedinstall/testdata/apex/com.android.apex.cts.shim_not_pre_installed.apex
+++ b/hostsidetests/stagedinstall/testdata/apex/com.android.apex.cts.shim_not_pre_installed.apex
Binary files differ
diff --git a/hostsidetests/statsd/src/android/cts/statsd/alert/AnomalyDetectionTests.java b/hostsidetests/statsd/src/android/cts/statsd/alert/AnomalyDetectionTests.java
index 5e9eac6..b1705ad 100644
--- a/hostsidetests/statsd/src/android/cts/statsd/alert/AnomalyDetectionTests.java
+++ b/hostsidetests/statsd/src/android/cts/statsd/alert/AnomalyDetectionTests.java
@@ -72,6 +72,23 @@
}
}
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ if (PERFETTO_TESTS_ENABLED) {
+ //Deadline to finish trace collection
+ final long deadLine = System.currentTimeMillis() + 10000;
+ while (isSystemTracingEnabled()) {
+ if (System.currentTimeMillis() > deadLine) {
+ CLog.w("/sys/kernel/debug/tracing/tracing_on is still 1 after 10 secs : " + isSystemTracingEnabled());
+ break;
+ }
+ CLog.d("Waiting to finish collecting traces. ");
+ Thread.sleep(WAIT_TIME_SHORT);
+ }
+ }
+ }
+
// Tests that anomaly detection for count works.
// Also tests that anomaly detection works when spanning multiple buckets.
public void testCountAnomalyDetection() throws Exception {
diff --git a/hostsidetests/statsd/src/android/cts/statsd/atom/ProcStateAtomTests.java b/hostsidetests/statsd/src/android/cts/statsd/atom/ProcStateAtomTests.java
index 070d3f4..ff65335 100644
--- a/hostsidetests/statsd/src/android/cts/statsd/atom/ProcStateAtomTests.java
+++ b/hostsidetests/statsd/src/android/cts/statsd/atom/ProcStateAtomTests.java
@@ -40,7 +40,7 @@
private static final int WAIT_TIME_FOR_CONFIG_UPDATE_MS = 200;
// ActivityManager can take a while to register screen state changes, mandating an extra delay.
private static final int WAIT_TIME_FOR_CONFIG_AND_SCREEN_MS = 1_000;
- private static final int EXTRA_WAIT_TIME_MS = 1_000; // as buffer when proc state changing.
+ private static final int EXTRA_WAIT_TIME_MS = 5_000; // as buffer when proc state changing.
private static final int STATSD_REPORT_WAIT_TIME_MS = 500; // make sure statsd finishes log.
private static final String FEATURE_WATCH = "android.hardware.type.watch";
diff --git a/hostsidetests/statsd/src/android/cts/statsd/atom/UidAtomTests.java b/hostsidetests/statsd/src/android/cts/statsd/atom/UidAtomTests.java
index fd77425..540ff9b 100644
--- a/hostsidetests/statsd/src/android/cts/statsd/atom/UidAtomTests.java
+++ b/hostsidetests/statsd/src/android/cts/statsd/atom/UidAtomTests.java
@@ -635,6 +635,12 @@
if (!hasFeature(FEATURE_WATCH, false)) return;
final int atomTag = Atom.MEDIA_CODEC_STATE_CHANGED_FIELD_NUMBER;
+ // 5 seconds. Starting video tends to be much slower than most other
+ // tests on slow devices. This is unfortunate, because it leaves a
+ // really big slop in assertStatesOccurred. It would be better if
+ // assertStatesOccurred had a tighter range on large timeouts.
+ final int waitTime = 5000;
+
Set<Integer> onState = new HashSet<>(
Arrays.asList(MediaCodecStateChanged.State.ON_VALUE));
Set<Integer> offState = new HashSet<>(
@@ -646,13 +652,14 @@
createAndUploadConfig(atomTag, true); // True: uses attribution.
Thread.sleep(WAIT_TIME_SHORT);
- runActivity("VideoPlayerActivity", "action", "action.play_video");
+ runActivity("VideoPlayerActivity", "action", "action.play_video",
+ waitTime);
// Sorted list of events in order in which they occurred.
List<EventMetricData> data = getEventMetricDataList();
// Assert that the events happened in the expected order.
- assertStatesOccurred(stateSet, data, WAIT_TIME_LONG,
+ assertStatesOccurred(stateSet, data, waitTime,
atom -> atom.getMediaCodecStateChanged().getState().getNumber());
}
@@ -674,7 +681,7 @@
createAndUploadConfig(atomTag, false);
runActivity("StatsdCtsForegroundActivity", "action", "action.show_application_overlay",
- 3_000);
+ 5_000);
// Sorted list of events in order in which they occurred.
List<EventMetricData> data = getEventMetricDataList();
@@ -1134,7 +1141,7 @@
// Start test app.
try (AutoCloseable a = withActivity("StatsdCtsForegroundActivity", "action",
"action.show_notification")) {
- Thread.sleep(WAIT_TIME_SHORT);
+ Thread.sleep(WAIT_TIME_LONG);
// Trigger a pull and wait for new pull before killing the process.
setAppBreadcrumbPredicate();
Thread.sleep(WAIT_TIME_LONG);
diff --git a/hostsidetests/statsd/src/android/cts/statsd/validation/BatteryStatsValidationTests.java b/hostsidetests/statsd/src/android/cts/statsd/validation/BatteryStatsValidationTests.java
index 889763b..9aafbad 100644
--- a/hostsidetests/statsd/src/android/cts/statsd/validation/BatteryStatsValidationTests.java
+++ b/hostsidetests/statsd/src/android/cts/statsd/validation/BatteryStatsValidationTests.java
@@ -53,6 +53,7 @@
plugInUsb();
}
+ /*
public void testConnectivityStateChange() throws Exception {
if (!hasFeature(FEATURE_WIFI, true)) return;
if (!hasFeature(FEATURE_WATCH, false)) return;
@@ -77,6 +78,7 @@
assertThat(countMetricData.get(0).getBucketInfo(0).getCount()).isEqualTo(
(long) batterystatsProto.getSystem().getMisc().getNumConnectivityChanges());
}
+ */
public void testPowerUse() throws Exception {
if (statsdDisabled()) {
@@ -117,67 +119,6 @@
assertThat(bsPowerNas).isGreaterThan(ALLOWED_FRACTIONAL_DIFFERENCE * statsdPowerNas);
}
- public void testPowerBlameUid() throws Exception {
- if (statsdDisabled()) {
- return;
- }
- if (!hasFeature(FEATURE_LEANBACK_ONLY, false)) return;
- resetBatteryStats();
- unplugDevice();
-
- final double ALLOWED_FRACTIONAL_DIFFERENCE = 0.8; // ratio that statsd and bs can differ
-
- StatsdConfig.Builder config = getPulledConfig();
- addGaugeAtomWithDimensions(config, Atom.DEVICE_CALCULATED_POWER_BLAME_UID_FIELD_NUMBER,
- null);
- uploadConfig(config);
- unplugDevice();
-
- Thread.sleep(WAIT_TIME_LONG);
- runDeviceTests(DEVICE_SIDE_TEST_PACKAGE, ".AtomTests", "testSimpleCpu");
- Thread.sleep(WAIT_TIME_LONG);
-
- setAppBreadcrumbPredicate();
- BatteryStatsProto batterystatsProto = getBatteryStatsProto();
- Thread.sleep(WAIT_TIME_LONG);
- List<Atom> atomList = getGaugeMetricDataList();
-
- // Extract statsd data
- boolean uidFound = false;
- int uid = getUid();
- long statsdUidPowerNas = 0;
- for (Atom atom : atomList) {
- DeviceCalculatedPowerBlameUid item = atom.getDeviceCalculatedPowerBlameUid();
- if (item.getUid() == uid) {
- assertWithMessage("Found multiple power values for uid %s", uid)
- .that(uidFound).isFalse();
- uidFound = true;
- statsdUidPowerNas = item.getPowerNanoAmpSecs();
- }
- }
- assertWithMessage("Statsd: No power value for uid %s", uid).that(uidFound).isTrue();
- assertWithMessage("Statsd: Non-positive power value for uid %s", uid)
- .that(statsdUidPowerNas).isGreaterThan(0L);
-
- // Extract batterystats data
- double bsUidPowerNas = -1;
- boolean hadUid = false;
- for (UidProto uidProto : batterystatsProto.getUidsList()) {
- if (uidProto.getUid() == uid) {
- hadUid = true;
- bsUidPowerNas = uidProto.getPowerUseItem().getComputedPowerMah()
- * 1_000_000L * 3600L; /* mAh to nAs */;
- }
- }
- assertWithMessage("Batterystats: No power value for uid %s", uid).that(hadUid).isTrue();
- assertWithMessage("BatteryStats: Non-positive power value for uid %s", uid)
- .that(bsUidPowerNas).isGreaterThan(0d);
-
- assertThat((double) statsdUidPowerNas)
- .isGreaterThan(ALLOWED_FRACTIONAL_DIFFERENCE * bsUidPowerNas);
- assertThat(bsUidPowerNas).isGreaterThan(ALLOWED_FRACTIONAL_DIFFERENCE * statsdUidPowerNas);
- }
-
public void testServiceStartCount() throws Exception {
final String fileName = "BATTERYSTATS_SERVICE_START_COUNT.pbtxt";
StatsdConfig config = createValidationUtil().getConfig(fileName);
diff --git a/tests/AlarmManager/AndroidTest.xml b/tests/AlarmManager/AndroidTest.xml
index f44ae93..4369acc 100644
--- a/tests/AlarmManager/AndroidTest.xml
+++ b/tests/AlarmManager/AndroidTest.xml
@@ -19,6 +19,7 @@
<option name="config-descriptor:metadata" key="component" value="framework" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
<option name="config-descriptor:metadata" key="parameter" value="instant_app" />
+ <option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
diff --git a/tests/accessibility/AndroidManifest.xml b/tests/accessibility/AndroidManifest.xml
index d4cea0f..c9e0c71 100644
--- a/tests/accessibility/AndroidManifest.xml
+++ b/tests/accessibility/AndroidManifest.xml
@@ -57,11 +57,31 @@
android:resource="@xml/speaking_and_vibrating_accessibilityservice" />
</service>
+ <service android:name=".AccessibilityButtonService"
+ android:label="@string/title_accessibility_button_service"
+ android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
+ <intent-filter>
+ <action android:name="android.accessibilityservice.AccessibilityService"/>
+ </intent-filter>
+ <meta-data android:name="android.accessibilityservice"
+ android:resource="@xml/accessibility_button_service" />
+ </service>
+
<activity
android:label="@string/some_description"
android:name=".DummyActivity"
android:screenOrientation="locked"/>
+ <activity android:name=".AccessibilityShortcutTargetActivity"
+ android:label="@string/shortcut_target_title">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.ACCESSIBILITY_SHORTCUT_TARGET" />
+ </intent-filter>
+ <meta-data android:name="android.accessibilityshortcut.target"
+ android:resource="@xml/shortcut_target_activity"/>
+ </activity>
+
</application>
<instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
diff --git a/tests/accessibility/res/layout/shortcut_target.xml b/tests/accessibility/res/layout/shortcut_target.xml
new file mode 100644
index 0000000..42d10a0
--- /dev/null
+++ b/tests/accessibility/res/layout/shortcut_target.xml
@@ -0,0 +1,28 @@
+<?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
+ -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ android:orientation="vertical">
+ <Button
+ android:id="@+id/targetActionBtn"
+ android:text="@string/shortcut_button_title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"/>
+</LinearLayout>
diff --git a/tests/accessibility/res/values/strings.xml b/tests/accessibility/res/values/strings.xml
index 7bd62af..de1539a 100644
--- a/tests/accessibility/res/values/strings.xml
+++ b/tests/accessibility/res/values/strings.xml
@@ -26,6 +26,9 @@
<!-- String title for the vibrating accessibility service -->
<string name="title_speaking_and_vibrating_accessibility_service">Speaking and Vibrating Accessibility Service</string>
+ <!-- String title for the accessibility button service -->
+ <string name="title_accessibility_button_service">Accessibility Button Service</string>
+
<!-- Description of the speaking accessibility service -->
<string name="some_description">Some description</string>
@@ -35,4 +38,10 @@
<!-- Summary of the speaking accessibility service -->
<string name="some_summary">Some summary</string>
+ <!-- String title for the button of shortcut target activity -->
+ <string name="shortcut_button_title">Action</string>
+
+ <!-- String title for the shortcut target activity -->
+ <string name="shortcut_target_title">Shortcut Target</string>
+
</resources>
diff --git a/tests/accessibility/res/xml/accessibility_button_service.xml b/tests/accessibility/res/xml/accessibility_button_service.xml
new file mode 100644
index 0000000..d475266
--- /dev/null
+++ b/tests/accessibility/res/xml/accessibility_button_service.xml
@@ -0,0 +1,21 @@
+<?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.
+-->
+<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
+ android:description="@string/some_description"
+ android:accessibilityEventTypes="typeAllMask"
+ android:accessibilityFeedbackType="feedbackGeneric"
+ android:accessibilityFlags="flagRequestAccessibilityButton"
+ android:notificationTimeout="0" />
\ No newline at end of file
diff --git a/tests/tests/graphics/res/drawable/gradientdrawable_stroke_tint.xml b/tests/accessibility/res/xml/shortcut_target_activity.xml
similarity index 72%
rename from tests/tests/graphics/res/drawable/gradientdrawable_stroke_tint.xml
rename to tests/accessibility/res/xml/shortcut_target_activity.xml
index 13404bc..b258d3f 100644
--- a/tests/tests/graphics/res/drawable/gradientdrawable_stroke_tint.xml
+++ b/tests/accessibility/res/xml/shortcut_target_activity.xml
@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
+
<!--
~ Copyright (C) 2019 The Android Open Source Project
~
@@ -14,11 +15,8 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-<shape
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="rectangle" >
- <corners android:radius="5dp" />
- <stroke
- android:width="20dp"
- android:color="@android:color/white"/>
-</shape>
\ No newline at end of file
+
+<accessibility-shortcut-target xmlns:android="http://schemas.android.com/apk/res/android"
+ android:description="@string/some_description"
+ android:summary="@string/some_summary"
+/>
\ No newline at end of file
diff --git a/tests/accessibility/src/android/view/accessibility/cts/AccessibilityButtonService.java b/tests/accessibility/src/android/view/accessibility/cts/AccessibilityButtonService.java
new file mode 100644
index 0000000..3b4b8fd
--- /dev/null
+++ b/tests/accessibility/src/android/view/accessibility/cts/AccessibilityButtonService.java
@@ -0,0 +1,25 @@
+/*
+ * 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 android.view.accessibility.cts;
+
+import android.accessibility.cts.common.InstrumentedAccessibilityService;
+
+/**
+ * An accessibility service that requests accessibility button.
+ */
+public class AccessibilityButtonService extends InstrumentedAccessibilityService {
+}
diff --git a/tests/accessibility/src/android/view/accessibility/cts/AccessibilityManagerTest.java b/tests/accessibility/src/android/view/accessibility/cts/AccessibilityManagerTest.java
index 274d13c..f1eab6c 100644
--- a/tests/accessibility/src/android/view/accessibility/cts/AccessibilityManagerTest.java
+++ b/tests/accessibility/src/android/view/accessibility/cts/AccessibilityManagerTest.java
@@ -17,10 +17,6 @@
package android.view.accessibility.cts;
import static android.accessibility.cts.common.InstrumentedAccessibilityService.TIMEOUT_SERVICE_ENABLE;
-import static android.accessibility.cts.common.ServiceControlUtils.getEnabledServices;
-import static android.accessibility.cts.common.ServiceControlUtils.waitForConditionWithServiceStateChange;
-
-import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -38,9 +34,6 @@
import android.content.Context;
import android.content.pm.ServiceInfo;
import android.os.Handler;
-import android.platform.test.annotations.AppModeFull;
-import android.provider.Settings;
-import android.text.TextUtils;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener;
@@ -444,64 +437,6 @@
}
}
- @AppModeFull
- @Test
- public void performShortcut_withoutPermission_fails() {
- UiAutomation uiAutomation = sInstrumentation.getUiAutomation(
- UiAutomation.FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES);
-
- String originalShortcut = configureShortcut(
- uiAutomation, SpeakingAccessibilityService.COMPONENT_NAME.flattenToString());
- try {
- mAccessibilityManager.performAccessibilityShortcut();
- fail("No security exception thrown when performing shortcut without permission");
- } catch (SecurityException e) {
- // Expected
- } finally {
- configureShortcut(uiAutomation, originalShortcut);
- uiAutomation.destroy();
- }
- assertTrue(TextUtils.isEmpty(getEnabledServices(mTargetContext.getContentResolver())));
- }
-
- @AppModeFull
- @Test
- public void performShortcut_withPermission_succeeds() {
- UiAutomation uiAutomation = sInstrumentation.getUiAutomation(
- UiAutomation.FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES);
-
- String originalShortcut = configureShortcut(
- uiAutomation, SpeakingAccessibilityService.COMPONENT_NAME.flattenToString());
- try {
- runWithShellPermissionIdentity(uiAutomation,
- () -> mAccessibilityManager.performAccessibilityShortcut());
- // Make sure the service starts up
- final SpeakingAccessibilityService service =
- SpeakingAccessibilityService.getInstanceForClass(
- SpeakingAccessibilityService.class, TIMEOUT_SERVICE_ENABLE);
- assertTrue("Speaking accessibility service starts up", service != null);
- } finally {
- configureShortcut(uiAutomation, originalShortcut);
- uiAutomation.destroy();
- }
- }
-
- private String configureShortcut(UiAutomation uiAutomation, String shortcutService) {
- String currentService = Settings.Secure.getString(mTargetContext.getContentResolver(),
- Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE);
- putSecureSetting(uiAutomation, Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE,
- shortcutService);
- if (shortcutService != null) {
- runWithShellPermissionIdentity(uiAutomation, () ->
- waitForConditionWithServiceStateChange(mTargetContext, () -> TextUtils.equals(
- mAccessibilityManager.getAccessibilityShortcutService(),
- shortcutService),
- TIMEOUT_SERVICE_ENABLE,
- "accessibility shortcut set to test service"));
- }
- return currentService;
- }
-
private void assertAtomicBooleanBecomes(AtomicBoolean atomicBoolean,
boolean expectedValue, Object waitObject, String message)
throws Exception {
diff --git a/tests/accessibility/src/android/view/accessibility/cts/AccessibilityShortcutTargetActivity.java b/tests/accessibility/src/android/view/accessibility/cts/AccessibilityShortcutTargetActivity.java
new file mode 100644
index 0000000..921a769
--- /dev/null
+++ b/tests/accessibility/src/android/view/accessibility/cts/AccessibilityShortcutTargetActivity.java
@@ -0,0 +1,34 @@
+/*
+ * 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 android.view.accessibility.cts;
+
+import android.app.Activity;
+import android.app.KeyguardManager;
+import android.content.Context;
+import android.os.Bundle;
+import android.view.accessibility.cts.R;
+
+/**
+ * The accessibility shortcut target activity.
+ */
+public class AccessibilityShortcutTargetActivity extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.shortcut_target);
+ }
+}
diff --git a/tests/accessibility/src/android/view/accessibility/cts/AccessibilityShortcutTest.java b/tests/accessibility/src/android/view/accessibility/cts/AccessibilityShortcutTest.java
new file mode 100644
index 0000000..5f61cd2
--- /dev/null
+++ b/tests/accessibility/src/android/view/accessibility/cts/AccessibilityShortcutTest.java
@@ -0,0 +1,458 @@
+/*
+ * 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 android.view.accessibility.cts;
+
+import static android.accessibility.cts.common.InstrumentedAccessibilityService.TIMEOUT_SERVICE_ENABLE;
+import static android.accessibility.cts.common.ServiceControlUtils.waitForConditionWithServiceStateChange;
+import static android.app.UiAutomation.FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES;
+import static android.provider.Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE;
+
+import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import android.accessibility.cts.common.AccessibilityDumpOnFailureRule;
+import android.accessibility.cts.common.InstrumentedAccessibilityServiceTestRule;
+import android.accessibility.cts.common.ShellCommandBuilder;
+import android.accessibilityservice.AccessibilityButtonController;
+import android.accessibilityservice.AccessibilityButtonController.AccessibilityButtonCallback;
+import android.accessibilityservice.AccessibilityService;
+import android.app.Activity;
+import android.app.Instrumentation;
+import android.app.Instrumentation.ActivityMonitor;
+import android.app.Service;
+import android.app.UiAutomation;
+import android.content.ComponentName;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.platform.test.annotations.AppModeFull;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.view.accessibility.AccessibilityManager;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.compatibility.common.util.TestUtils;
+
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.RuleChain;
+import org.junit.runner.RunWith;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * Tests accessibility shortcut related functionality
+ */
+@AppModeFull
+@RunWith(AndroidJUnit4.class)
+public class AccessibilityShortcutTest {
+ private static final int ACCESSIBILITY_BUTTON = 0;
+ private static final int ACCESSIBILITY_SHORTCUT_KEY = 1;
+
+ private static final String ACCESSIBILITY_BUTTON_TARGET_COMPONENT =
+ "accessibility_button_target_component";
+
+ private static final char DELIMITER = ':';
+ private static final String[] EMPTY_STRING_ARRAY = new String[0];
+
+ private static Instrumentation sInstrumentation;
+ private static UiAutomation sUiAutomation;
+
+ private final InstrumentedAccessibilityServiceTestRule<SpeakingAccessibilityService>
+ mServiceRule = new InstrumentedAccessibilityServiceTestRule<>(
+ SpeakingAccessibilityService.class, false);
+
+ private final InstrumentedAccessibilityServiceTestRule<AccessibilityButtonService>
+ mA11yButtonServiceRule = new InstrumentedAccessibilityServiceTestRule<>(
+ AccessibilityButtonService.class, false);
+
+ private final AccessibilityDumpOnFailureRule mDumpOnFailureRule =
+ new AccessibilityDumpOnFailureRule();
+
+ @Rule
+ public final RuleChain mRuleChain = RuleChain
+ .outerRule(mServiceRule)
+ .around(mA11yButtonServiceRule)
+ .around(mDumpOnFailureRule);
+
+ private Context mTargetContext;
+ private ContentResolver mContentResolver;
+ private AccessibilityManager mAccessibilityManager;
+
+ private ActivityMonitor mActivityMonitor;
+ private Activity mShortcutTargetActivity;
+
+ private String mSpeakingA11yServiceName;
+ private String mShortcutTargetActivityName;
+ private String mA11yButtonServiceName;
+
+ // These are the current shortcut states before doing the tests. Roll back them after the tests.
+ private String[] mA11yShortcutTargets;
+ private String[] mA11yButtonTargets;
+ private List<String> mA11yShortcutTargetList;
+ private List<String> mA11yButtonTargetList;
+
+ @BeforeClass
+ public static void oneTimeSetup() {
+ sInstrumentation = InstrumentationRegistry.getInstrumentation();
+ sUiAutomation = sInstrumentation.getUiAutomation(FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES);
+ }
+
+ @AfterClass
+ public static void postTestTearDown() {
+ sUiAutomation.destroy();
+ }
+
+ @Before
+ public void setUp() {
+ mTargetContext = sInstrumentation.getTargetContext();
+ mContentResolver = mTargetContext.getContentResolver();
+ mAccessibilityManager = (AccessibilityManager) mTargetContext.getSystemService(
+ Service.ACCESSIBILITY_SERVICE);
+ mSpeakingA11yServiceName = new ComponentName(mTargetContext,
+ SpeakingAccessibilityService.class).flattenToString();
+ mShortcutTargetActivityName = new ComponentName(mTargetContext,
+ AccessibilityShortcutTargetActivity.class).flattenToString();
+ mA11yButtonServiceName = new ComponentName(mTargetContext,
+ AccessibilityButtonService.class).flattenToString();
+ mActivityMonitor = new ActivityMonitor(
+ AccessibilityShortcutTargetActivity.class.getName(), null, false);
+ sInstrumentation.addMonitor(mActivityMonitor);
+
+ // Reads current shortcut states.
+ readShortcutStates();
+ }
+
+ @After
+ public void tearDown() {
+ if (mActivityMonitor != null) {
+ sInstrumentation.removeMonitor(mActivityMonitor);
+ }
+ if (mShortcutTargetActivity != null) {
+ sInstrumentation.runOnMainSync(() -> mShortcutTargetActivity.finish());
+ }
+
+ // Rollback default shortcut states.
+ if (configureShortcut(ACCESSIBILITY_SHORTCUT_KEY, mA11yShortcutTargets)) {
+ waitForShortcutStateChange(ACCESSIBILITY_SHORTCUT_KEY, mA11yShortcutTargetList);
+ }
+ if (configureShortcut(ACCESSIBILITY_BUTTON, mA11yButtonTargets)) {
+ waitForShortcutStateChange(ACCESSIBILITY_BUTTON, mA11yButtonTargetList);
+ }
+ }
+
+ @Test
+ public void performAccessibilityShortcut_withoutPermission_throwsSecurityException() {
+ try {
+ mAccessibilityManager.performAccessibilityShortcut();
+ fail("No security exception thrown when performing shortcut without permission");
+ } catch (SecurityException e) {
+ // Expected
+ }
+ }
+
+ @Test
+ public void performAccessibilityShortcut_launchAccessibilityService() {
+ configureShortcut(ACCESSIBILITY_SHORTCUT_KEY, mSpeakingA11yServiceName);
+ waitForShortcutStateChange(ACCESSIBILITY_SHORTCUT_KEY,
+ Arrays.asList(mSpeakingA11yServiceName));
+
+ runWithShellPermissionIdentity(sUiAutomation,
+ () -> mAccessibilityManager.performAccessibilityShortcut());
+
+ // Make sure the service starts up
+ final SpeakingAccessibilityService service = mServiceRule.getService();
+ assertTrue("Speaking accessibility service starts up", service != null);
+ }
+
+ @Test
+ public void performAccessibilityShortcut_launchShortcutTargetActivity() {
+ configureShortcut(ACCESSIBILITY_SHORTCUT_KEY, mShortcutTargetActivityName);
+ waitForShortcutStateChange(ACCESSIBILITY_SHORTCUT_KEY,
+ Arrays.asList(mShortcutTargetActivityName));
+
+ runWithShellPermissionIdentity(sUiAutomation,
+ () -> mAccessibilityManager.performAccessibilityShortcut());
+
+ // Make sure the activity starts up
+ mShortcutTargetActivity = mActivityMonitor.waitForActivityWithTimeout(
+ TIMEOUT_SERVICE_ENABLE);
+ assertTrue("Accessibility shortcut target starts up",
+ mShortcutTargetActivity != null);
+ }
+
+ @Test
+ public void performAccessibilityShortcut_withReqA11yButtonService_a11yButtonCallback() {
+ mA11yButtonServiceRule.enableService();
+ configureShortcut(ACCESSIBILITY_SHORTCUT_KEY, mA11yButtonServiceName);
+ waitForShortcutStateChange(ACCESSIBILITY_SHORTCUT_KEY,
+ Arrays.asList(mA11yButtonServiceName));
+
+ performShortcutAndWaitForA11yButtonClicked(mA11yButtonServiceRule.getService());
+ }
+
+ @Test
+ public void getAccessibilityShortcut_withoutPermission_throwsSecurityException() {
+ try {
+ mAccessibilityManager.getAccessibilityShortcutTargets(ACCESSIBILITY_BUTTON);
+ fail("No security exception thrown when get shortcut without permission");
+ } catch (SecurityException e) {
+ // Expected
+ }
+ }
+
+ @Test
+ public void getAccessibilityShortcut_assignedShortcutTarget_returnAssignedTarget() {
+ configureShortcut(ACCESSIBILITY_BUTTON, mSpeakingA11yServiceName);
+ waitForShortcutStateChange(ACCESSIBILITY_BUTTON, Arrays.asList(mSpeakingA11yServiceName));
+ }
+
+ @Test
+ public void getAccessibilityShortcut_multipleTargets_returnMultipleTargets() {
+ configureShortcut(ACCESSIBILITY_BUTTON,
+ mSpeakingA11yServiceName, mShortcutTargetActivityName);
+ waitForShortcutStateChange(ACCESSIBILITY_BUTTON,
+ Arrays.asList(mSpeakingA11yServiceName, mShortcutTargetActivityName));
+ }
+
+ /**
+ * Reads current shortcut states.
+ */
+ private void readShortcutStates() {
+ mA11yShortcutTargets = getComponentIdArray(Settings.Secure.getString(mContentResolver,
+ ACCESSIBILITY_SHORTCUT_TARGET_SERVICE));
+ mA11yButtonTargets = getComponentIdArray(Settings.Secure.getString(mContentResolver,
+ ACCESSIBILITY_BUTTON_TARGET_COMPONENT));
+ runWithShellPermissionIdentity(sUiAutomation, () -> {
+ mA11yShortcutTargetList = mAccessibilityManager
+ .getAccessibilityShortcutTargets(ACCESSIBILITY_SHORTCUT_KEY);
+ mA11yButtonTargetList = mAccessibilityManager
+ .getAccessibilityShortcutTargets(ACCESSIBILITY_BUTTON);
+ });
+ }
+
+ /**
+ * Returns an array of component names by given colon-separated component name string.
+ *
+ * @param componentIds The colon-separated component name string.
+ * @return The array of component names.
+ */
+ @NonNull
+ private String[] getComponentIdArray(String componentIds) {
+ final List<String> nameList = getComponentIdList(componentIds);
+ if (nameList.isEmpty()) {
+ return EMPTY_STRING_ARRAY;
+ }
+ final String[] result = new String[nameList.size()];
+ return nameList.toArray(result);
+ }
+
+ /**
+ * Return a list of component names by given colon-separated component name string.
+ *
+ * @param componentIds The colon-separated component name string.
+ * @return The list.
+ */
+ @NonNull
+ private List<String> getComponentIdList(String componentIds) {
+ final ArrayList<String> componentIdList = new ArrayList<>();
+ if (TextUtils.isEmpty(componentIds)) {
+ return componentIdList;
+ }
+
+ final TextUtils.SimpleStringSplitter splitter =
+ new TextUtils.SimpleStringSplitter(DELIMITER);
+ splitter.setString(componentIds);
+ for (String name : splitter) {
+ if (TextUtils.isEmpty(name)) {
+ continue;
+ }
+ componentIdList.add(name);
+ }
+ return componentIdList;
+ }
+
+ /**
+ * Return a colon-separated component name string by given string array.
+ *
+ * @param componentIds The array of component names.
+ * @return A colon-separated component name string.
+ */
+ @Nullable
+ private String getComponentIdString(String ... componentIds) {
+ final StringBuilder stringBuilder = new StringBuilder();
+ for (String componentId : componentIds) {
+ if (TextUtils.isEmpty(componentId)) {
+ continue;
+ }
+ if (stringBuilder.length() != 0) {
+ stringBuilder.append(DELIMITER);
+ }
+ stringBuilder.append(componentId);
+ }
+
+ if (stringBuilder.length() == 0) {
+ return null;
+ }
+ return stringBuilder.toString();
+ }
+
+ /**
+ * Update the shortcut settings.
+ *
+ * @param shortcutType The shortcut type.
+ * @param newUseShortcutList The component names which use the shortcut.
+ * @return true if the new states updated.
+ */
+ private boolean configureShortcut(int shortcutType, String ... newUseShortcutList) {
+ final String useShortcutList = getComponentIdString(newUseShortcutList);
+ if (shortcutType == ACCESSIBILITY_SHORTCUT_KEY) {
+ return updateAccessibilityShortcut(useShortcutList);
+ } else {
+ return updateAccessibilityButton(useShortcutList);
+ }
+ }
+
+ /**
+ * Update the setting keys of the accessibility shortcut.
+ *
+ * @param newUseShortcutList The value of ACCESSIBILITY_SHORTCUT_TARGET_SERVICE
+ * @return true if the new states updated.
+ */
+ private boolean updateAccessibilityShortcut(String newUseShortcutList) {
+ final ShellCommandBuilder command = ShellCommandBuilder.create(sUiAutomation);
+ final String useShortcutList = Settings.Secure.getString(mContentResolver,
+ ACCESSIBILITY_SHORTCUT_TARGET_SERVICE);
+ boolean changes = false;
+ if (!TextUtils.equals(useShortcutList, newUseShortcutList)) {
+ if (TextUtils.isEmpty(newUseShortcutList)) {
+ command.deleteSecureSetting(ACCESSIBILITY_SHORTCUT_TARGET_SERVICE);
+ } else {
+ command.putSecureSetting(ACCESSIBILITY_SHORTCUT_TARGET_SERVICE, newUseShortcutList);
+ }
+ changes = true;
+ }
+ if (changes) {
+ command.run();
+ }
+ return changes;
+ }
+
+ /**
+ * Update the setting keys of the accessibility button.
+ *
+ * @param newUseShortcutList The value of ACCESSIBILITY_BUTTON_TARGET_COMPONENT
+ * @return true if the new states updated.
+ */
+ private boolean updateAccessibilityButton(String newUseShortcutList) {
+ final ShellCommandBuilder command = ShellCommandBuilder.create(sUiAutomation);
+ final String useShortcutList = Settings.Secure.getString(mContentResolver,
+ ACCESSIBILITY_BUTTON_TARGET_COMPONENT);
+ boolean changes = false;
+ if (!TextUtils.equals(useShortcutList, newUseShortcutList)) {
+ if (TextUtils.isEmpty(newUseShortcutList)) {
+ command.deleteSecureSetting(ACCESSIBILITY_BUTTON_TARGET_COMPONENT);
+ } else {
+ command.putSecureSetting(ACCESSIBILITY_BUTTON_TARGET_COMPONENT, newUseShortcutList);
+ }
+ changes = true;
+ }
+ if (changes) {
+ command.run();
+ }
+ return changes;
+ }
+
+ /**
+ * Waits for the shortcut state changed, and gets current shortcut list is the same with
+ * expected one.
+ *
+ * @param shortcutType The shortcut type.
+ * @param expectedList The expected shortcut targets returned from
+ * {@link AccessibilityManager#getAccessibilityShortcutTargets(int)}.
+ */
+ private void waitForShortcutStateChange(int shortcutType, List<String> expectedList) {
+ final StringBuilder message = new StringBuilder();
+ if (shortcutType == ACCESSIBILITY_SHORTCUT_KEY) {
+ message.append("Accessibility Shortcut, ");
+ } else {
+ message.append("Accessibility Button, ");
+ }
+ message.append("expect:").append(expectedList);
+ runWithShellPermissionIdentity(sUiAutomation, () ->
+ waitForConditionWithServiceStateChange(mTargetContext, () -> {
+ final List<String> currentShortcuts =
+ mAccessibilityManager.getAccessibilityShortcutTargets(shortcutType);
+ if (currentShortcuts.size() != expectedList.size()) {
+ return false;
+ }
+ for (String expect : expectedList) {
+ if (!currentShortcuts.contains(expect)) {
+ return false;
+ }
+ }
+ return true;
+ }, TIMEOUT_SERVICE_ENABLE, message.toString()));
+ }
+
+ /**
+ * Perform shortcut and wait for accessibility button clicked call back.
+ *
+ * @param service The accessibility service
+ */
+ private void performShortcutAndWaitForA11yButtonClicked(AccessibilityService service) {
+ final AtomicBoolean clicked = new AtomicBoolean();
+ final AccessibilityButtonCallback callback = new AccessibilityButtonCallback() {
+ @Override
+ public void onClicked(AccessibilityButtonController controller) {
+ synchronized (clicked) {
+ clicked.set(true);
+ clicked.notifyAll();
+ }
+ }
+
+ @Override
+ public void onAvailabilityChanged(AccessibilityButtonController controller,
+ boolean available) {
+ /* do nothing */
+ }
+ };
+ try {
+ service.getAccessibilityButtonController()
+ .registerAccessibilityButtonCallback(callback);
+ runWithShellPermissionIdentity(sUiAutomation,
+ () -> mAccessibilityManager.performAccessibilityShortcut());
+ TestUtils.waitOn(clicked, () -> clicked.get(), TIMEOUT_SERVICE_ENABLE,
+ "Wait for a11y button clicked");
+ } finally {
+ service.getAccessibilityButtonController()
+ .unregisterAccessibilityButtonCallback(callback);
+ }
+ }
+}
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityWindowQueryTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityWindowQueryTest.java
index f32871b..b37358f 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityWindowQueryTest.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityWindowQueryTest.java
@@ -17,6 +17,7 @@
package android.accessibilityservice.cts;
import static android.accessibilityservice.cts.utils.AccessibilityEventFilterUtils.filterForEventType;
+import static android.accessibilityservice.cts.utils.AccessibilityEventFilterUtils.filterWindowsChangTypesAndWindowId;
import static android.accessibilityservice.cts.utils.AccessibilityEventFilterUtils.filterWindowsChangedWithChangeTypes;
import static android.accessibilityservice.cts.utils.ActivityLaunchUtils.launchActivityAndWaitForItToBeOnscreen;
import static android.accessibilityservice.cts.utils.ActivityLaunchUtils.launchActivityOnSpecifiedDisplayAndWaitForItToBeOnscreen;
@@ -768,7 +769,8 @@
final AccessibilityWindowInfo finalFocusTarget = focusTarget;
sUiAutomation.executeAndWaitForEvent(() -> assertTrue(finalFocusTarget.getRoot()
.performAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS)),
- filterWindowsChangedWithChangeTypes(WINDOWS_CHANGE_ACCESSIBILITY_FOCUSED),
+ filterWindowsChangTypesAndWindowId(finalFocusTarget.getId(),
+ WINDOWS_CHANGE_ACCESSIBILITY_FOCUSED),
DEFAULT_TIMEOUT_MS);
windows = sUiAutomation.getWindows();
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityWindowReportingTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityWindowReportingTest.java
index 35ad056..eb5e2b4 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityWindowReportingTest.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityWindowReportingTest.java
@@ -49,8 +49,12 @@
import android.app.Activity;
import android.app.Instrumentation;
import android.app.UiAutomation;
+import android.os.SystemClock;
+import android.util.DisplayMetrics;
import android.view.Display;
import android.view.Gravity;
+import android.view.InputDevice;
+import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityNodeInfo;
@@ -254,6 +258,26 @@
sUiAutomation,
AccessibilityEmbeddedDisplayTest.EmbeddedDisplayActivity.class,
virtualDisplayId);
+ // Window manager changed the behavior of focused window at a virtual display. A window
+ // at virtual display needs to be touched then it becomes to be focused one. Adding this
+ // touch event on the activity window of the virtual display to pass this test case.
+ final DisplayMetrics displayMetrics = mActivity.getResources().getDisplayMetrics();
+ final int xOnScreen = displayMetrics.widthPixels / 2;
+ final int yOnScreen = displayMetrics.heightPixels / 2;
+ final long downEventTime = SystemClock.uptimeMillis();
+ final MotionEvent downEvent = MotionEvent.obtain(downEventTime, downEventTime,
+ MotionEvent.ACTION_DOWN, xOnScreen, yOnScreen, 0);
+ downEvent.setSource(InputDevice.SOURCE_TOUCHSCREEN);
+ downEvent.setDisplayId(virtualDisplayId);
+ sUiAutomation.injectInputEvent(downEvent, true);
+
+ final long upEventTime = downEventTime + 10;
+ final MotionEvent upEvent = MotionEvent.obtain(downEventTime, upEventTime,
+ MotionEvent.ACTION_UP, xOnScreen, yOnScreen, 0);
+ upEvent.setSource(InputDevice.SOURCE_TOUCHSCREEN);
+ upEvent.setDisplayId(virtualDisplayId);
+ sUiAutomation.injectInputEvent(upEvent, true);
+
final CharSequence activityTitle = getActivityTitle(sInstrumentation,
activityOnVirtualDisplay);
// Make sure activityWindow on virtual display is focused.
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/utils/AccessibilityEventFilterUtils.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/utils/AccessibilityEventFilterUtils.java
index 790246e..0fd9477 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/utils/AccessibilityEventFilterUtils.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/utils/AccessibilityEventFilterUtils.java
@@ -59,6 +59,13 @@
new WindowTitleMatcher(uiAutomation, title))::matches;
}
+ public static AccessibilityEventFilter filterWindowsChangTypesAndWindowId(int windowId,
+ int changeTypes) {
+ return allOf(new AccessibilityEventTypeMatcher(AccessibilityEvent.TYPE_WINDOWS_CHANGED),
+ new WindowChangesMatcher(changeTypes),
+ new WindowIdMatcher(windowId))::matches;
+ }
+
public static class AccessibilityEventTypeMatcher extends TypeSafeMatcher<AccessibilityEvent> {
private int mType;
@@ -167,4 +174,23 @@
description.appendText("With window title " + mTitle);
}
}
+
+ public static class WindowIdMatcher extends TypeSafeMatcher<AccessibilityEvent> {
+ private int mWindowId;
+
+ public WindowIdMatcher(int windowId) {
+ super();
+ mWindowId = windowId;
+ }
+
+ @Override
+ protected boolean matchesSafely(AccessibilityEvent event) {
+ return event.getWindowId() == mWindowId;
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText("With window Id " + mWindowId);
+ }
+ }
}
diff --git a/tests/app/NotificationDelegator/src/com/android/test/notificationdelegator/NotificationRevoker.java b/tests/app/NotificationDelegator/src/com/android/test/notificationdelegator/NotificationRevoker.java
index b2b106e..750549a 100644
--- a/tests/app/NotificationDelegator/src/com/android/test/notificationdelegator/NotificationRevoker.java
+++ b/tests/app/NotificationDelegator/src/com/android/test/notificationdelegator/NotificationRevoker.java
@@ -32,6 +32,7 @@
NotificationManager nm = getSystemService(NotificationManager.class);
nm.setNotificationDelegate(null);
Log.d(TAG, "Removed delegate: " + nm.getNotificationDelegate());
+ nm.cancelAll();
finish();
}
}
diff --git a/tests/app/src/android/app/cts/ActivityManagerProcessStateTest.java b/tests/app/src/android/app/cts/ActivityManagerProcessStateTest.java
index 7434354..ac50181 100644
--- a/tests/app/src/android/app/cts/ActivityManagerProcessStateTest.java
+++ b/tests/app/src/android/app/cts/ActivityManagerProcessStateTest.java
@@ -1947,6 +1947,11 @@
WAITFOR_MSEC);
uid3Listener.register();
+ UidImportanceListener uid3ServiceListener = new UidImportanceListener(mContext,
+ app3Info.uid, IMPORTANCE_CACHED,
+ WAITFOR_MSEC);
+ uid3ServiceListener.register();
+
Activity activity = null;
try {
@@ -2014,7 +2019,8 @@
uid2ServiceListener.waitForValue(
IMPORTANCE_CACHED,
IMPORTANCE_CACHED);
- uid3Listener.waitForValue(
+
+ uid3ServiceListener.waitForValue(
IMPORTANCE_CACHED,
IMPORTANCE_CACHED);
} finally {
@@ -2031,6 +2037,7 @@
uid2Listener.unregister();
uid2ServiceListener.unregister();
uid3Listener.unregister();
+ uid3ServiceListener.unregister();
if (activity != null) {
activity.finish();
}
diff --git a/tests/appsearch/OWNERS b/tests/appsearch/OWNERS
new file mode 100644
index 0000000..cf3ad8a
--- /dev/null
+++ b/tests/appsearch/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 755061
+adorokhine@google.com
diff --git a/tests/autofillservice/res/layout/list_item_cancel.xml b/tests/autofillservice/res/layout/list_item_cancel.xml
index 4a3c7d8..e9863e7 100644
--- a/tests/autofillservice/res/layout/list_item_cancel.xml
+++ b/tests/autofillservice/res/layout/list_item_cancel.xml
@@ -30,7 +30,7 @@
android:minHeight="?android:attr/listPreferredItemHeightSmall"/>
<Button
- android:id="@+id/cancel"
+ android:id="@+id/cancel_fill"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
diff --git a/tests/autofillservice/src/android/autofillservice/cts/AutoFillServiceTestCase.java b/tests/autofillservice/src/android/autofillservice/cts/AutoFillServiceTestCase.java
index ecdf90a..a5ac282 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/AutoFillServiceTestCase.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/AutoFillServiceTestCase.java
@@ -53,7 +53,6 @@
import org.junit.Rule;
import org.junit.rules.RuleChain;
import org.junit.rules.TestRule;
-import org.junit.rules.TestWatcher;
import org.junit.runner.Description;
import org.junit.runner.RunWith;
import org.junit.runners.model.Statement;
@@ -199,9 +198,15 @@
protected static final RequiredFeatureRule sRequiredFeatureRule =
new RequiredFeatureRule(PackageManager.FEATURE_AUTOFILL);
- private final TestWatcher mTestWatcher = new AutofillTestWatcher();
+ private final AutofillTestWatcher mTestWatcher = new AutofillTestWatcher();
- private final RetryRule mRetryRule = new RetryRule(getNumberRetries());
+ private final RetryRule mRetryRule =
+ new RetryRule(getNumberRetries(), () -> {
+ // Between testing and retries, clean all launched activities to avoid
+ // exception:
+ // Could not launch intent Intent { ... } within 45 seconds.
+ mTestWatcher.cleanAllActivities();
+ });
private final AutofillLoggingTestRule mLoggingRule = new AutofillLoggingTestRule(TAG);
diff --git a/tests/autofillservice/src/android/autofillservice/cts/AutofillTestWatcher.java b/tests/autofillservice/src/android/autofillservice/cts/AutofillTestWatcher.java
index 6879a8c..6c29197 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/AutofillTestWatcher.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/AutofillTestWatcher.java
@@ -36,6 +36,18 @@
*/
public final class AutofillTestWatcher extends TestWatcher {
+ /**
+ * Cleans up all launched activities between the tests and retries.
+ */
+ public void cleanAllActivities() {
+ try {
+ finishActivities();
+ waitUntilAllDestroyed();
+ } finally {
+ resetStaticState();
+ }
+ }
+
private static final String TAG = "AutofillTestWatcher";
@GuardedBy("sUnfinishedBusiness")
@@ -55,12 +67,7 @@
@Override
protected void finished(Description description) {
final String testName = description.getDisplayName();
- try {
- finishActivities();
- waitUntilAllDestroyed();
- } finally {
- resetStaticState();
- }
+ cleanAllActivities();
Log.i(TAG, "Finished " + testName);
TestNameUtils.setCurrentTestName(null);
}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/Helper.java b/tests/autofillservice/src/android/autofillservice/cts/Helper.java
index 4684924..74f9fd9 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/Helper.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/Helper.java
@@ -98,7 +98,7 @@
public static final String ID_OUTPUT = "output";
public static final String ID_STATIC_TEXT = "static_text";
public static final String ID_EMPTY = "empty";
- public static final String ID_CANCEL = "cancel";
+ public static final String ID_CANCEL_FILL = "cancel_fill";
public static final String NULL_DATASET_ID = null;
diff --git a/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java
index 1ab1b06..165d0b0 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java
@@ -20,7 +20,7 @@
import static android.autofillservice.cts.CannedFillResponse.FAIL;
import static android.autofillservice.cts.CannedFillResponse.NO_MOAR_RESPONSES;
import static android.autofillservice.cts.CannedFillResponse.NO_RESPONSE;
-import static android.autofillservice.cts.Helper.ID_CANCEL;
+import static android.autofillservice.cts.Helper.ID_CANCEL_FILL;
import static android.autofillservice.cts.Helper.ID_EMPTY;
import static android.autofillservice.cts.Helper.ID_PASSWORD;
import static android.autofillservice.cts.Helper.ID_PASSWORD_LABEL;
@@ -2839,7 +2839,7 @@
.setField(ID_PASSWORD, "sweet")
.setPresentation(createPresentationWithCancel("The Dude"))
.build())
- .setCancelTargetIds(new int[]{R.id.cancel});
+ .setCancelTargetIds(new int[]{R.id.cancel_fill});
sReplier.addResponse(builder.build());
// Trigger auto-fill.
@@ -2848,8 +2848,8 @@
mUiBot.assertDatasetsContains("The Dude");
- // Tap cancel button
- mUiBot.selectByRelativeId(ID_CANCEL);
+ // Tap cancel button on fill UI
+ mUiBot.selectByRelativeId(ID_CANCEL_FILL);
mUiBot.waitForIdle();
mUiBot.assertNoDatasets();
diff --git a/tests/camera/Android.mk b/tests/camera/Android.mk
index 083359a..df9e106 100644
--- a/tests/camera/Android.mk
+++ b/tests/camera/Android.mk
@@ -50,9 +50,9 @@
androidx.test.rules
LOCAL_SRC_FILES := \
- src/android/hardware/camera2/cts/testcases/Camera2AndroidBasicTestCase.java \
+ src/android/hardware/camera2/cts/testcases/Camera2AndroidTestRule.java \
src/android/hardware/camera2/cts/PerformanceTest.java \
- src/android/hardware/cts/CameraTestCase.java \
+ src/android/hardware/cts/CameraPerformanceTestHelper.java \
src/android/hardware/cts/LegacyCameraPerformanceTest.java
LOCAL_SDK_VERSION := test_current
diff --git a/tests/camera/src/android/hardware/camera2/cts/BurstCaptureTest.java b/tests/camera/src/android/hardware/camera2/cts/BurstCaptureTest.java
index 6616942..cfe1db3 100644
--- a/tests/camera/src/android/hardware/camera2/cts/BurstCaptureTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/BurstCaptureTest.java
@@ -26,7 +26,7 @@
import android.hardware.camera2.CameraMetadata;
import android.hardware.camera2.cts.helpers.StaticMetadata;
import android.hardware.camera2.cts.testcases.Camera2SurfaceViewTestCase;
-import android.hardware.camera2.params.CapabilityAndMaxSize;
+import android.hardware.camera2.params.Capability;
import android.hardware.camera2.params.StreamConfigurationMap;
import android.media.Image;
import android.util.Log;
@@ -104,9 +104,9 @@
continue;
}
- CapabilityAndMaxSize[] bokehCaps = staticInfo.getAvailableBokehCapsChecked();
+ Capability[] bokehCaps = staticInfo.getAvailableBokehCapsChecked();
boolean supportStillBokeh = false;
- for (CapabilityAndMaxSize bokehCap : bokehCaps) {
+ for (Capability bokehCap : bokehCaps) {
if (bokehCap.getMode() == CameraMetadata.CONTROL_BOKEH_MODE_STILL_CAPTURE) {
supportStillBokeh = true;
break;
diff --git a/tests/camera/src/android/hardware/camera2/cts/CaptureRequestTest.java b/tests/camera/src/android/hardware/camera2/cts/CaptureRequestTest.java
index 35c7da6..961e7c6 100644
--- a/tests/camera/src/android/hardware/camera2/cts/CaptureRequestTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/CaptureRequestTest.java
@@ -33,7 +33,7 @@
import android.hardware.camera2.cts.helpers.StaticMetadata;
import android.hardware.camera2.cts.testcases.Camera2SurfaceViewTestCase;
import android.hardware.camera2.params.BlackLevelPattern;
-import android.hardware.camera2.params.CapabilityAndMaxSize;
+import android.hardware.camera2.params.Capability;
import android.hardware.camera2.params.ColorSpaceTransform;
import android.hardware.camera2.params.Face;
import android.hardware.camera2.params.LensShadingMap;
@@ -823,6 +823,27 @@
}
/**
+ * Test zoom using CONTROL_ZOOM_RATIO, validate the returned crop regions and zoom ratio.
+ * The max preview size is used for each camera.
+ */
+ @Test
+ public void testZoomRatio() throws Exception {
+ for (String id : mCameraIdsUnderTest) {
+ try {
+ if (!mAllStaticInfo.get(id).isColorOutputSupported()) {
+ Log.i(TAG, "Camera " + id + " does not support color outputs, skipping");
+ continue;
+ }
+ openDevice(id);
+ Size maxPreviewSize = mOrderedPreviewSizes.get(0);
+ zoomRatioTestByCamera(maxPreviewSize);
+ } finally {
+ closeDevice();
+ }
+ }
+ }
+
+ /**
* Test digital zoom and all preview size combinations.
* TODO: this and above test should all be moved to preview test class.
*/
@@ -2589,6 +2610,8 @@
}
final Rect activeArraySize = mStaticInfo.getActiveArraySizeChecked();
+ final Rect defaultCropRegion = new Rect(0, 0,
+ activeArraySize.width(), activeArraySize.height());
Rect[] cropRegions = new Rect[ZOOM_STEPS];
MeteringRectangle[][] expectRegions = new MeteringRectangle[ZOOM_STEPS][];
CaptureRequest.Builder requestBuilder =
@@ -2634,7 +2657,8 @@
* Submit capture request
*/
float zoomFactor = (float) (1.0f + (maxZoom - 1.0) * i / ZOOM_STEPS);
- cropRegions[i] = getCropRegionForZoom(zoomFactor, center, maxZoom, activeArraySize);
+ cropRegions[i] = getCropRegionForZoom(zoomFactor, center,
+ maxZoom, defaultCropRegion);
if (VERBOSE) {
Log.v(TAG, "Testing Zoom for factor " + zoomFactor + " and center " +
center + " The cropRegion is " + cropRegions[i] +
@@ -2695,7 +2719,7 @@
// Verify Output 3A region is intersection of input 3A region and crop region
for (int algo = 0; algo < NUM_ALGORITHMS; algo++) {
- validate3aRegion(result, algo, expectRegions[i]);
+ validate3aRegion(result, algo, expectRegions[i], false/*scaleByZoomRatio*/);
}
previousCrop = cropRegion;
@@ -2713,6 +2737,120 @@
}
}
+ private void zoomRatioTestByCamera(Size previewSize) throws Exception {
+ final int ZOOM_STEPS = 15;
+ final Range<Float> zoomRatioRange = mStaticInfo.getZoomRatioRangeChecked();
+ // The error margin is derive from a VGA size camera zoomed all the way to 10x, in which
+ // case the cropping error can be as large as 480/46 - 480/48 = 0.435.
+ final float ZOOM_ERROR_MARGIN = 0.05f;
+
+ final Rect activeArraySize = mStaticInfo.getActiveArraySizeChecked();
+ final Rect defaultCropRegion =
+ new Rect(0, 0, activeArraySize.width(), activeArraySize.height());
+ MeteringRectangle[][] expectRegions = new MeteringRectangle[ZOOM_STEPS][];
+ CaptureRequest.Builder requestBuilder =
+ mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
+ requestBuilder.set(CaptureRequest.SCALER_CROP_REGION, defaultCropRegion);
+ SimpleCaptureCallback listener = new SimpleCaptureCallback();
+
+ updatePreviewSurface(previewSize);
+ configurePreviewOutput(requestBuilder);
+
+ // Set algorithm regions to full active region
+ final MeteringRectangle[] defaultMeteringRect = new MeteringRectangle[] {
+ new MeteringRectangle (
+ /*x*/0, /*y*/0, activeArraySize.width(), activeArraySize.height(),
+ /*meteringWeight*/1)
+ };
+
+ for (int algo = 0; algo < NUM_ALGORITHMS; algo++) {
+ update3aRegion(requestBuilder, algo, defaultMeteringRect);
+ }
+
+ final int captureSubmitRepeat;
+ {
+ int maxLatency = mStaticInfo.getSyncMaxLatency();
+ if (maxLatency == CameraMetadata.SYNC_MAX_LATENCY_UNKNOWN) {
+ captureSubmitRepeat = NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY + 1;
+ } else {
+ captureSubmitRepeat = maxLatency + 1;
+ }
+ }
+
+ float previousRatio = zoomRatioRange.getLower();
+ for (int i = 0; i < ZOOM_STEPS; i++) {
+ /*
+ * Submit capture request
+ */
+ float zoomFactor = zoomRatioRange.getLower() + (zoomRatioRange.getUpper() -
+ zoomRatioRange.getLower()) * i / ZOOM_STEPS;
+ if (VERBOSE) {
+ Log.v(TAG, "Testing Zoom ratio " + zoomFactor + " Preview size is " + previewSize);
+ }
+ requestBuilder.set(CaptureRequest.CONTROL_ZOOM_RATIO, zoomFactor);
+ CaptureRequest request = requestBuilder.build();
+ for (int j = 0; j < captureSubmitRepeat; ++j) {
+ mSession.capture(request, listener, mHandler);
+ }
+
+ /*
+ * Validate capture result
+ */
+ waitForNumResults(listener, captureSubmitRepeat - 1); // Drop first few frames
+ CaptureResult result = listener.getCaptureResultForRequest(
+ request, NUM_RESULTS_WAIT_TIMEOUT);
+ float resultZoomRatio = getValueNotNull(result, CaptureResult.CONTROL_ZOOM_RATIO);
+ Rect cropRegion = getValueNotNull(result, CaptureResult.SCALER_CROP_REGION);
+
+ /*
+ * Validate resulting crop regions and zoom ratio
+ */
+ mCollector.expectTrue(String.format(
+ "Zoom ratio should increase or stay the same " +
+ "(previous = %f, current = %f)",
+ previousRatio, resultZoomRatio),
+ Math.abs(previousRatio - resultZoomRatio) < ZOOM_ERROR_MARGIN ||
+ (previousRatio < resultZoomRatio));
+
+ mCollector.expectTrue(String.format(
+ "Request and result zoom ratio should be similar " +
+ "(requested = %f, result = %f", zoomFactor, resultZoomRatio),
+ Math.abs(zoomFactor - resultZoomRatio)/zoomFactor <= ZOOM_ERROR_MARGIN);
+
+ //In case zoom ratio is converted to crop region at HAL, due to error magnification
+ //when converting to post-zoom crop region, scale the error threshold for crop region
+ //check.
+ float errorMultiplier = Math.max(1.0f, zoomFactor);
+ if (mStaticInfo.isHardwareLevelAtLeastLimited()) {
+ mCollector.expectRectsAreSimilar(
+ "Request and result crop region should be similar",
+ activeArraySize, cropRegion,
+ CROP_REGION_ERROR_PERCENT_DELTA * errorMultiplier);
+ }
+
+ mCollector.expectRectCentered(
+ "Result crop region should be centered inside the active array",
+ new Size(activeArraySize.width(), activeArraySize.height()),
+ cropRegion, CROP_REGION_ERROR_PERCENT_CENTERED * errorMultiplier);
+
+ /*
+ * Validate resulting metering regions
+ */
+ // Use the actual reported crop region to calculate the resulting metering region
+ expectRegions[i] = getExpectedOutputRegion(
+ /*requestRegion*/defaultMeteringRect,
+ /*cropRect*/ cropRegion);
+
+ // Verify Output 3A region is intersection of input 3A region and crop region
+ boolean scaleByZoomRatio = zoomFactor > 1.0f;
+ for (int algo = 0; algo < NUM_ALGORITHMS; algo++) {
+ validate3aRegion(result, algo, expectRegions[i], scaleByZoomRatio);
+ }
+
+ previousRatio = resultZoomRatio;
+ }
+ }
+
private void digitalZoomPreviewCombinationTestByCamera() throws Exception {
final double ASPECT_RATIO_THRESHOLD = 0.001;
List<Double> aspectRatiosTested = new ArrayList<Double>();
@@ -2798,7 +2936,7 @@
}
private void bokehModeTestByCamera(List<Range<Integer>> fpsRanges) throws Exception {
- CapabilityAndMaxSize[] bokehCaps = mStaticInfo.getAvailableBokehCapsChecked();
+ Capability[] bokehCaps = mStaticInfo.getAvailableBokehCapsChecked();
if (bokehCaps.length == 0) {
return;
}
@@ -2807,7 +2945,7 @@
CaptureRequest.Builder requestBuilder =
mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
- for (CapabilityAndMaxSize bokehCap : bokehCaps) {
+ for (Capability bokehCap : bokehCaps) {
int mode = bokehCap.getMode();
requestBuilder.set(CaptureRequest.CONTROL_BOKEH_MODE, mode);
@@ -2817,13 +2955,19 @@
verifyFpsNotSlowDown(requestBuilder, NUM_FRAMES_VERIFIED, fpsRanges);
}
- SimpleCaptureCallback listener = new SimpleCaptureCallback();
- startPreview(requestBuilder, maxPreviewSize, listener);
- mSession.setRepeatingRequest(requestBuilder.build(), listener, mHandler);
- waitForSettingsApplied(listener, NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY);
+ Range<Float> zoomRange = bokehCap.getZoomRatioRange();
+ float[] zoomRatios = new float[]{zoomRange.getLower(), zoomRange.getUpper()};
+ for (float ratio : zoomRatios) {
+ SimpleCaptureCallback listener = new SimpleCaptureCallback();
+ requestBuilder.set(CaptureRequest.CONTROL_ZOOM_RATIO, ratio);
+ startPreview(requestBuilder, maxPreviewSize, listener);
+ waitForSettingsApplied(listener, NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY);
- verifyCaptureResultForKey(CaptureResult.CONTROL_BOKEH_MODE,
- mode, listener, NUM_FRAMES_VERIFIED);
+ verifyCaptureResultForKey(CaptureResult.CONTROL_BOKEH_MODE,
+ mode, listener, NUM_FRAMES_VERIFIED);
+ verifyCaptureResultForKey(CaptureResult.CONTROL_ZOOM_RATIO,
+ ratio, listener, NUM_FRAMES_VERIFIED);
+ }
}
}
@@ -3241,7 +3385,8 @@
* @param expectRegions The 3A regions expected in capture result
*/
private void validate3aRegion(
- CaptureResult result, int algoIdx, MeteringRectangle[] expectRegions)
+ CaptureResult result, int algoIdx, MeteringRectangle[] expectRegions,
+ boolean scaleByZoomRatio)
{
final int maxCorrectionDist = 2;
int maxRegions;
@@ -3269,30 +3414,35 @@
boolean correctionEnabled =
distortionCorrectionMode != null &&
distortionCorrectionMode != CaptureResult.DISTORTION_CORRECTION_MODE_OFF;
+ Float zoomRatio = result.get(CaptureResult.CONTROL_ZOOM_RATIO);
+ int maxDist = correctionEnabled ? maxCorrectionDist : 1;
+ if (scaleByZoomRatio) {
+ maxDist = (int)Math.ceil(maxDist * zoomRatio);
+ }
if (maxRegions > 0)
{
actualRegion = getValueNotNull(result, key);
- if (correctionEnabled) {
+ if (correctionEnabled || scaleByZoomRatio) {
for(int i = 0; i < actualRegion.length; i++) {
Rect a = actualRegion[i].getRect();
Rect e = expectRegions[i].getRect();
if (!mCollector.expectLessOrEqual(
"Expected 3A regions: " + Arrays.toString(expectRegions) +
" are not close enough to the actual one: " + Arrays.toString(actualRegion),
- maxCorrectionDist, Math.abs(a.left - e.left))) continue;
+ maxDist, Math.abs(a.left - e.left))) continue;
if (!mCollector.expectLessOrEqual(
"Expected 3A regions: " + Arrays.toString(expectRegions) +
" are not close enough to the actual one: " + Arrays.toString(actualRegion),
- maxCorrectionDist, Math.abs(a.right - e.right))) continue;
+ maxDist, Math.abs(a.right - e.right))) continue;
if (!mCollector.expectLessOrEqual(
"Expected 3A regions: " + Arrays.toString(expectRegions) +
" are not close enough to the actual one: " + Arrays.toString(actualRegion),
- maxCorrectionDist, Math.abs(a.top - e.top))) continue;
+ maxDist, Math.abs(a.top - e.top))) continue;
if (!mCollector.expectLessOrEqual(
"Expected 3A regions: " + Arrays.toString(expectRegions) +
" are not close enough to the actual one: " + Arrays.toString(actualRegion),
- maxCorrectionDist, Math.abs(a.bottom - e.bottom))) continue;
+ maxDist, Math.abs(a.bottom - e.bottom))) continue;
}
} else {
mCollector.expectEquals(
diff --git a/tests/camera/src/android/hardware/camera2/cts/CaptureResultTest.java b/tests/camera/src/android/hardware/camera2/cts/CaptureResultTest.java
index 247308e..da0c32e 100644
--- a/tests/camera/src/android/hardware/camera2/cts/CaptureResultTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/CaptureResultTest.java
@@ -806,6 +806,7 @@
waiverKeys.add(CaptureResult.CONTROL_AF_MODE);
waiverKeys.add(CaptureResult.CONTROL_AWB_MODE);
waiverKeys.add(CaptureResult.CONTROL_AWB_LOCK);
+ waiverKeys.add(CaptureResult.CONTROL_ZOOM_RATIO);
waiverKeys.add(CaptureResult.STATISTICS_FACE_DETECT_MODE);
waiverKeys.add(CaptureResult.FLASH_MODE);
waiverKeys.add(CaptureResult.SCALER_CROP_REGION);
@@ -946,6 +947,7 @@
resultKeys.add(CaptureResult.CONTROL_ENABLE_ZSL);
resultKeys.add(CaptureResult.CONTROL_AF_SCENE_CHANGE);
resultKeys.add(CaptureResult.CONTROL_BOKEH_MODE);
+ resultKeys.add(CaptureResult.CONTROL_ZOOM_RATIO);
resultKeys.add(CaptureResult.EDGE_MODE);
resultKeys.add(CaptureResult.FLASH_MODE);
resultKeys.add(CaptureResult.FLASH_STATE);
diff --git a/tests/camera/src/android/hardware/camera2/cts/PerformanceTest.java b/tests/camera/src/android/hardware/camera2/cts/PerformanceTest.java
index 0616433..af254b1 100644
--- a/tests/camera/src/android/hardware/camera2/cts/PerformanceTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/PerformanceTest.java
@@ -22,6 +22,7 @@
import static org.junit.Assert.assertTrue;
import android.app.Instrumentation;
+import android.content.Context;
import android.graphics.ImageFormat;
import android.graphics.SurfaceTexture;
import android.hardware.camera2.CameraAccessException;
@@ -36,7 +37,7 @@
import android.hardware.camera2.cts.CameraTestUtils.SimpleImageReaderListener;
import android.hardware.camera2.cts.helpers.StaticMetadata;
import android.hardware.camera2.cts.helpers.StaticMetadata.CheckLevel;
-import android.hardware.camera2.cts.testcases.Camera2AndroidBasicTestCase;
+import android.hardware.camera2.cts.testcases.Camera2AndroidTestRule;
import android.hardware.camera2.params.InputConfiguration;
import android.hardware.camera2.params.StreamConfigurationMap;
import android.media.Image;
@@ -59,7 +60,10 @@
import com.android.ex.camera2.blocking.BlockingSessionCallback;
import com.android.ex.camera2.exceptions.TimeoutRuntimeException;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
import java.util.ArrayList;
import java.util.Arrays;
@@ -71,7 +75,8 @@
* Test camera2 API use case performance KPIs, such as camera open time, session creation time,
* shutter lag etc. The KPI data will be reported in cts results.
*/
-public class PerformanceTest extends Camera2AndroidBasicTestCase {
+@RunWith(JUnit4.class)
+public class PerformanceTest {
private static final String TAG = "PerformanceTest";
private static final String REPORT_LOG_NAME = "CtsCameraTestCases";
private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
@@ -102,21 +107,15 @@
private ImageWriter mWriter;
private SimpleCaptureCallback mZslResultListener;
- private Instrumentation mInstrumentation;
-
private Surface mPreviewSurface;
private SurfaceTexture mPreviewSurfaceTexture;
- @Override
- public void setUp() throws Exception {
- super.setUp();
- mInstrumentation = InstrumentationRegistry.getInstrumentation();
- }
+ private static final Instrumentation mInstrumentation =
+ InstrumentationRegistry.getInstrumentation();
+ private static final Context mContext = InstrumentationRegistry.getTargetContext();
- @Override
- public void tearDown() throws Exception {
- super.tearDown();
- }
+ @Rule
+ public final Camera2AndroidTestRule mTestRule = new Camera2AndroidTestRule(mContext);
/**
* Test camera launch KPI: the time duration between a camera device is
@@ -132,11 +131,12 @@
* For depth-only devices, timing is done with the DEPTH16 format instead.
* </p>
*/
+ @Test
public void testCameraLaunch() throws Exception {
- double[] avgCameraLaunchTimes = new double[mCameraIdsUnderTest.length];
+ double[] avgCameraLaunchTimes = new double[mTestRule.getCameraIdsUnderTest().length];
int counter = 0;
- for (String id : mCameraIdsUnderTest) {
+ for (String id : mTestRule.getCameraIdsUnderTest()) {
// Do NOT move these variables to outer scope
// They will be passed to DeviceReportLog and their references will be stored
String streamName = "test_camera_launch";
@@ -149,12 +149,13 @@
double[] cameraCloseTimes = new double[NUM_TEST_LOOPS];
double[] cameraLaunchTimes = new double[NUM_TEST_LOOPS];
try {
- mStaticInfo = new StaticMetadata(mCameraManager.getCameraCharacteristics(id));
- if (mStaticInfo.isColorOutputSupported()) {
+ mTestRule.setStaticInfo(new StaticMetadata(
+ mTestRule.getCameraManager().getCameraCharacteristics(id)));
+ if (mTestRule.getStaticInfo().isColorOutputSupported()) {
initializeImageReader(id, ImageFormat.YUV_420_888);
} else {
assertTrue("Depth output must be supported if regular output isn't!",
- mStaticInfo.isDepthOutputSupported());
+ mTestRule.getStaticInfo().isDepthOutputSupported());
initializeImageReader(id, ImageFormat.DEPTH16);
}
@@ -165,7 +166,8 @@
// Need create a new listener every iteration to be able to wait
// for the first image comes out.
imageListener = new SimpleImageListener();
- mReader.setOnImageAvailableListener(imageListener, mHandler);
+ mTestRule.getReader().setOnImageAvailableListener(
+ imageListener, mTestRule.getHandler());
startTimeMs = SystemClock.elapsedRealtime();
// Blocking open camera
@@ -198,7 +200,7 @@
finally {
// Blocking camera close
startTimeMs = SystemClock.elapsedRealtime();
- closeDevice(id);
+ mTestRule.closeDevice(id);
cameraCloseTimes[i] = SystemClock.elapsedRealtime() - startTimeMs;
}
}
@@ -220,7 +222,7 @@
ResultType.LOWER_BETTER, ResultUnit.MS);
}
finally {
- closeDefaultImageReader();
+ mTestRule.closeDefaultImageReader();
closePreviewSurface();
}
counter++;
@@ -259,7 +261,7 @@
+ ". Max(ms): " + Stat.getMax(cameraLaunchTimes));
}
}
- if (mCameraIdsUnderTest.length != 0) {
+ if (mTestRule.getCameraIdsUnderTest().length != 0) {
String streamName = "test_camera_launch_average";
mReportLog = new DeviceReportLog(REPORT_LOG_NAME, streamName);
mReportLog.setSummary("camera_launch_average_time_for_all_cameras",
@@ -281,6 +283,7 @@
* out the capture request and getting the full capture result.
* </p>
*/
+ @Test
public void testSingleCapture() throws Exception {
int[] YUV_FORMAT = {ImageFormat.YUV_420_888};
testSingleCaptureForFormat(YUV_FORMAT, null, /*addPreviewDelay*/ false);
@@ -309,10 +312,10 @@
private void testSingleCaptureForFormat(int[] formats, String formatDescription,
boolean addPreviewDelay) throws Exception {
- double[] avgResultTimes = new double[mCameraIdsUnderTest.length];
+ double[] avgResultTimes = new double[mTestRule.getCameraIdsUnderTest().length];
int counter = 0;
- for (String id : mCameraIdsUnderTest) {
+ for (String id : mTestRule.getCameraIdsUnderTest()) {
// Do NOT move these variables to outer scope
// They will be passed to DeviceReportLog and their references will be stored
String streamName = appendFormatDescription("test_single_capture", formatDescription);
@@ -323,12 +326,13 @@
double[] getResultTimes = new double[NUM_TEST_LOOPS];
ImageReader[] readers = null;
try {
- if (!mAllStaticInfo.get(id).isColorOutputSupported()) {
+ if (!mTestRule.getAllStaticInfo().get(id).isColorOutputSupported()) {
Log.i(TAG, "Camera " + id + " does not support color outputs, skipping");
continue;
}
- StreamConfigurationMap configMap = mAllStaticInfo.get(id).getCharacteristics().get(
+ StreamConfigurationMap configMap = mTestRule.getAllStaticInfo().get(
+ id).getCharacteristics().get(
CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
boolean formatsSupported = true;
for (int format : formats) {
@@ -343,18 +347,20 @@
continue;
}
- openDevice(id);
+ mTestRule.openDevice(id);
- boolean partialsExpected = mStaticInfo.getPartialResultCount() > 1;
+ boolean partialsExpected = mTestRule.getStaticInfo().getPartialResultCount() > 1;
long startTimeMs;
boolean isPartialTimingValid = partialsExpected;
for (int i = 0; i < NUM_TEST_LOOPS; i++) {
// setup builders and listeners
CaptureRequest.Builder previewBuilder =
- mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
+ mTestRule.getCamera().createCaptureRequest(
+ CameraDevice.TEMPLATE_PREVIEW);
CaptureRequest.Builder captureBuilder =
- mCamera.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
+ mTestRule.getCamera().createCaptureRequest(
+ CameraDevice.TEMPLATE_STILL_CAPTURE);
SimpleCaptureCallback previewResultListener =
new SimpleCaptureCallback();
SimpleTimingResultListener captureResultListener =
@@ -363,12 +369,15 @@
Size[] imageSizes = new Size[formats.length];
for (int j = 0; j < formats.length; j++) {
imageSizes[j] = CameraTestUtils.getSortedSizesForFormat(
- id, mCameraManager, formats[j], /*bound*/null).get(0);
+ id,
+ mTestRule.getCameraManager(),
+ formats[j],
+ /*bound*/null).get(0);
imageListeners[j] = new SimpleImageListener();
}
readers = prepareStillCaptureAndStartPreview(previewBuilder, captureBuilder,
- mOrderedPreviewSizes.get(0), imageSizes, formats,
+ mTestRule.getOrderedPreviewSizes().get(0), imageSizes, formats,
previewResultListener, NUM_MAX_IMAGES, imageListeners,
false /*isHeic*/);
@@ -379,12 +388,13 @@
// Capture an image and get image data
startTimeMs = SystemClock.elapsedRealtime();
CaptureRequest request = captureBuilder.build();
- mCameraSession.capture(request, captureResultListener, mHandler);
+ mTestRule.getCameraSession().capture(
+ request, captureResultListener, mTestRule.getHandler());
Pair<CaptureResult, Long> partialResultNTime = null;
if (partialsExpected) {
partialResultNTime = captureResultListener.getPartialResultNTimeForRequest(
- request, NUM_RESULTS_WAIT);
+ request, NUM_RESULTS_WAIT);
// Even if maxPartials > 1, may not see partials for some devices
if (partialResultNTime == null) {
partialsExpected = false;
@@ -440,7 +450,7 @@
finally {
CameraTestUtils.closeImageReaders(readers);
readers = null;
- closeDevice(id);
+ mTestRule.closeDevice(id);
closePreviewSurface();
}
counter++;
@@ -448,7 +458,7 @@
}
// Result will not be reported in CTS report if no summary is printed.
- if (mCameraIdsUnderTest.length != 0) {
+ if (mTestRule.getCameraIdsUnderTest().length != 0) {
String streamName = appendFormatDescription("test_single_capture_average",
formatDescription);
mReportLog = new DeviceReportLog(REPORT_LOG_NAME, streamName);
@@ -469,9 +479,10 @@
* gap between results.
* </p>
*/
+ @Test
public void testMultipleCapture() throws Exception {
- double[] avgResultTimes = new double[mCameraIdsUnderTest.length];
- double[] avgDurationMs = new double[mCameraIdsUnderTest.length];
+ double[] avgResultTimes = new double[mTestRule.getCameraIdsUnderTest().length];
+ double[] avgDurationMs = new double[mTestRule.getCameraIdsUnderTest().length];
// A simple CaptureSession StateCallback to handle onCaptureQueueEmpty
class MultipleCaptureStateCallback extends CameraCaptureSession.StateCallback {
@@ -493,7 +504,7 @@
captureQueueEmptied++;
if (VERBOSE) {
Log.v(TAG, "onCaptureQueueEmpty received. captureQueueEmptied = "
- + captureQueueEmptied);
+ + captureQueueEmptied);
}
captureQueueEmptyCond.open();
@@ -512,7 +523,7 @@
captureQueueEmptied = 0;
} else {
throw new TimeoutRuntimeException("Unable to receive onCaptureQueueEmpty after "
- + timeout + "ms");
+ + timeout + "ms");
}
}
}
@@ -520,7 +531,7 @@
final MultipleCaptureStateCallback sessionListener = new MultipleCaptureStateCallback();
int counter = 0;
- for (String id : mCameraIdsUnderTest) {
+ for (String id : mTestRule.getCameraIdsUnderTest()) {
// Do NOT move these variables to outer scope
// They will be passed to DeviceReportLog and their references will be stored
String streamName = "test_multiple_capture";
@@ -530,19 +541,21 @@
double[] getResultTimes = new double[NUM_MAX_IMAGES];
double[] frameDurationMs = new double[NUM_MAX_IMAGES-1];
try {
- if (!mAllStaticInfo.get(id).isColorOutputSupported()) {
+ if (!mTestRule.getAllStaticInfo().get(id).isColorOutputSupported()) {
Log.i(TAG, "Camera " + id + " does not support color outputs, skipping");
continue;
}
- openDevice(id);
+ mTestRule.openDevice(id);
for (int i = 0; i < NUM_TEST_LOOPS; i++) {
// setup builders and listeners
CaptureRequest.Builder previewBuilder =
- mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
+ mTestRule.getCamera().createCaptureRequest(
+ CameraDevice.TEMPLATE_PREVIEW);
CaptureRequest.Builder captureBuilder =
- mCamera.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
+ mTestRule.getCamera().createCaptureRequest(
+ CameraDevice.TEMPLATE_STILL_CAPTURE);
SimpleCaptureCallback previewResultListener =
new SimpleCaptureCallback();
SimpleTimingResultListener captureResultListener =
@@ -551,37 +564,39 @@
new SimpleImageReaderListener(/*asyncMode*/true, NUM_MAX_IMAGES);
Size maxYuvSize = CameraTestUtils.getSortedSizesForFormat(
- id, mCameraManager, ImageFormat.YUV_420_888, /*bound*/null).get(0);
+ id, mTestRule.getCameraManager(),
+ ImageFormat.YUV_420_888, /*bound*/null).get(0);
// Find minimum frame duration for YUV_420_888
- StreamConfigurationMap config = mStaticInfo.getCharacteristics().get(
+ StreamConfigurationMap config =
+ mTestRule.getStaticInfo().getCharacteristics().get(
CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
final long minStillFrameDuration =
config.getOutputMinFrameDuration(ImageFormat.YUV_420_888, maxYuvSize);
if (minStillFrameDuration > 0) {
Range<Integer> targetRange =
- CameraTestUtils.getSuitableFpsRangeForDuration(id,
- minStillFrameDuration, mStaticInfo);
+ CameraTestUtils.getSuitableFpsRangeForDuration(id,
+ minStillFrameDuration, mTestRule.getStaticInfo());
previewBuilder.set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, targetRange);
captureBuilder.set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, targetRange);
}
prepareCaptureAndStartPreview(previewBuilder, captureBuilder,
- mOrderedPreviewSizes.get(0), maxYuvSize,
+ mTestRule.getOrderedPreviewSizes().get(0), maxYuvSize,
ImageFormat.YUV_420_888, previewResultListener,
sessionListener, NUM_MAX_IMAGES, imageListener);
// Converge AE
CameraTestUtils.waitForAeStable(previewResultListener,
- NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY, mStaticInfo,
+ NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY, mTestRule.getStaticInfo(),
WAIT_FOR_RESULT_TIMEOUT_MS, NUM_RESULTS_WAIT_TIMEOUT);
- if (mStaticInfo.isAeLockSupported()) {
+ if (mTestRule.getStaticInfo().isAeLockSupported()) {
// Lock AE if possible to improve stability
previewBuilder.set(CaptureRequest.CONTROL_AE_LOCK, true);
- mCameraSession.setRepeatingRequest(previewBuilder.build(),
- previewResultListener, mHandler);
- if (mStaticInfo.isHardwareLevelAtLeastLimited()) {
+ mTestRule.getCameraSession().setRepeatingRequest(previewBuilder.build(),
+ previewResultListener, mTestRule.getHandler());
+ if (mTestRule.getStaticInfo().isHardwareLevelAtLeastLimited()) {
// Legacy mode doesn't output AE state
CameraTestUtils.waitForResultValue(previewResultListener,
CaptureResult.CONTROL_AE_STATE,
@@ -596,7 +611,8 @@
// Capture an image and get image data
startTimes[j] = SystemClock.elapsedRealtime();
CaptureRequest request = captureBuilder.build();
- mCameraSession.capture(request, captureResultListener, mHandler);
+ mTestRule.getCameraSession().capture(
+ request, captureResultListener, mTestRule.getHandler());
// Wait for capture queue empty for the current request
sessionListener.waitForCaptureQueueEmpty(
@@ -614,10 +630,12 @@
(double)(captureResultNTime.second - startTimes[j])/NUM_TEST_LOOPS;
// Collect inter-frame timestamp
- long timestamp = captureResultNTime.first.get(CaptureResult.SENSOR_TIMESTAMP);
+ long timestamp = captureResultNTime.first.get(
+ CaptureResult.SENSOR_TIMESTAMP);
if (prevTimestamp != -1) {
frameDurationMs[j-1] +=
- (double)(timestamp - prevTimestamp)/(NUM_TEST_LOOPS * 1000000.0);
+ (double)(timestamp - prevTimestamp)/(
+ NUM_TEST_LOOPS * 1000000.0);
}
prevTimestamp = timestamp;
}
@@ -648,8 +666,8 @@
avgDurationMs[counter] = Stat.getAverage(frameDurationMs);
}
finally {
- closeDefaultImageReader();
- closeDevice(id);
+ mTestRule.closeDefaultImageReader();
+ mTestRule.closeDevice(id);
closePreviewSurface();
}
counter++;
@@ -657,7 +675,7 @@
}
// Result will not be reported in CTS report if no summary is printed.
- if (mCameraIdsUnderTest.length != 0) {
+ if (mTestRule.getCameraIdsUnderTest().length != 0) {
String streamName = "test_multiple_capture_average";
mReportLog = new DeviceReportLog(REPORT_LOG_NAME, streamName);
mReportLog.setSummary("camera_multiple_capture_result_average_latency_for_all_cameras",
@@ -674,15 +692,16 @@
* Test reprocessing shot-to-shot latency with default NR and edge options, i.e., from the time
* a reprocess request is issued to the time the reprocess image is returned.
*/
+ @Test
public void testReprocessingLatency() throws Exception {
- for (String id : mCameraIdsUnderTest) {
+ for (String id : mTestRule.getCameraIdsUnderTest()) {
for (int format : REPROCESS_FORMATS) {
if (!isReprocessSupported(id, format)) {
continue;
}
try {
- openDevice(id);
+ mTestRule.openDevice(id);
String streamName = "test_reprocessing_latency";
mReportLog = new DeviceReportLog(REPORT_LOG_NAME, streamName);
mReportLog.addValue("camera_id", id, ResultType.NEUTRAL, ResultUnit.NONE);
@@ -691,7 +710,7 @@
/*highQuality*/false);
} finally {
closeReaderWriters();
- closeDevice(id);
+ mTestRule.closeDevice(id);
closePreviewSurface();
mReportLog.submit(mInstrumentation);
}
@@ -700,19 +719,20 @@
}
/**
- * Test reprocessing throughput with default NR and edge options, i.e., how many frames can be reprocessed
- * during a given amount of time.
+ * Test reprocessing throughput with default NR and edge options,
+ * i.e., how many frames can be reprocessed during a given amount of time.
*
*/
+ @Test
public void testReprocessingThroughput() throws Exception {
- for (String id : mCameraIdsUnderTest) {
+ for (String id : mTestRule.getCameraIdsUnderTest()) {
for (int format : REPROCESS_FORMATS) {
if (!isReprocessSupported(id, format)) {
continue;
}
try {
- openDevice(id);
+ mTestRule.openDevice(id);
String streamName = "test_reprocessing_throughput";
mReportLog = new DeviceReportLog(REPORT_LOG_NAME, streamName);
mReportLog.addValue("camera_id", id, ResultType.NEUTRAL, ResultUnit.NONE);
@@ -721,7 +741,7 @@
/*highQuality*/false);
} finally {
closeReaderWriters();
- closeDevice(id);
+ mTestRule.closeDevice(id);
closePreviewSurface();
mReportLog.submit(mInstrumentation);
}
@@ -733,15 +753,16 @@
* Test reprocessing shot-to-shot latency with High Quality NR and edge options, i.e., from the
* time a reprocess request is issued to the time the reprocess image is returned.
*/
+ @Test
public void testHighQualityReprocessingLatency() throws Exception {
- for (String id : mCameraIdsUnderTest) {
+ for (String id : mTestRule.getCameraIdsUnderTest()) {
for (int format : REPROCESS_FORMATS) {
if (!isReprocessSupported(id, format)) {
continue;
}
try {
- openDevice(id);
+ mTestRule.openDevice(id);
String streamName = "test_high_quality_reprocessing_latency";
mReportLog = new DeviceReportLog(REPORT_LOG_NAME, streamName);
mReportLog.addValue("camera_id", id, ResultType.NEUTRAL, ResultUnit.NONE);
@@ -750,7 +771,7 @@
/*requireHighQuality*/true);
} finally {
closeReaderWriters();
- closeDevice(id);
+ mTestRule.closeDevice(id);
closePreviewSurface();
mReportLog.submit(mInstrumentation);
}
@@ -763,15 +784,16 @@
* be reprocessed during a given amount of time.
*
*/
+ @Test
public void testHighQualityReprocessingThroughput() throws Exception {
- for (String id : mCameraIdsUnderTest) {
+ for (String id : mTestRule.getCameraIdsUnderTest()) {
for (int format : REPROCESS_FORMATS) {
if (!isReprocessSupported(id, format)) {
continue;
}
try {
- openDevice(id);
+ mTestRule.openDevice(id);
String streamName = "test_high_quality_reprocessing_throughput";
mReportLog = new DeviceReportLog(REPORT_LOG_NAME, streamName);
mReportLog.addValue("camera_id", id, ResultType.NEUTRAL, ResultUnit.NONE);
@@ -780,7 +802,7 @@
/*requireHighQuality*/true);
} finally {
closeReaderWriters();
- closeDevice(id);
+ mTestRule.closeDevice(id);
closePreviewSurface();
mReportLog.submit(mInstrumentation);
}
@@ -791,15 +813,16 @@
/**
* Testing reprocessing caused preview stall (frame drops)
*/
+ @Test
public void testReprocessingCaptureStall() throws Exception {
- for (String id : mCameraIdsUnderTest) {
+ for (String id : mTestRule.getCameraIdsUnderTest()) {
for (int format : REPROCESS_FORMATS) {
if (!isReprocessSupported(id, format)) {
continue;
}
try {
- openDevice(id);
+ mTestRule.openDevice(id);
String streamName = "test_reprocessing_capture_stall";
mReportLog = new DeviceReportLog(REPORT_LOG_NAME, streamName);
mReportLog.addValue("camera_id", id, ResultType.NEUTRAL, ResultUnit.NONE);
@@ -807,7 +830,7 @@
reprocessingCaptureStallTestByCamera(format);
} finally {
closeReaderWriters();
- closeDevice(id);
+ mTestRule.closeDevice(id);
closePreviewSurface();
mReportLog.submit(mInstrumentation);
}
@@ -832,7 +855,7 @@
TotalCaptureResult zslResult =
mZslResultListener.getCaptureResult(
WAIT_FOR_RESULT_TIMEOUT_MS, inputImages[i].getTimestamp());
- reprocessReqs[i] = mCamera.createReprocessCaptureRequest(zslResult);
+ reprocessReqs[i] = mTestRule.getCamera().createReprocessCaptureRequest(zslResult);
reprocessReqs[i].addTarget(mJpegReader.getSurface());
reprocessReqs[i].set(CaptureRequest.NOISE_REDUCTION_MODE,
CaptureRequest.NOISE_REDUCTION_MODE_HIGH_QUALITY);
@@ -849,14 +872,15 @@
for (int i = 0; i < NUM_REPROCESS_TESTED; i++) {
mZslResultListener.drain();
CaptureRequest reprocessRequest = reprocessReqs[i].build();
- mCameraSession.capture(reprocessRequest, reprocessResultListener, mHandler);
+ mTestRule.getCameraSession().capture(
+ reprocessRequest, reprocessResultListener, mTestRule.getHandler());
// Wait for reprocess output jpeg and result come back.
reprocessResultListener.getCaptureResultForRequest(reprocessRequest,
CameraTestUtils.CAPTURE_RESULT_TIMEOUT_MS);
mJpegListener.getImage(CameraTestUtils.CAPTURE_IMAGE_TIMEOUT_MS).close();
long numFramesMaybeStalled = mZslResultListener.getTotalNumFrames();
assertTrue("Reprocess capture result should be returned in "
- + MAX_REPROCESS_RETURN_FRAME_COUNT + " frames",
+ + MAX_REPROCESS_RETURN_FRAME_COUNT + " frames",
numFramesMaybeStalled <= MAX_REPROCESS_RETURN_FRAME_COUNT);
// Need look longer time, as the stutter could happen after the reprocessing
@@ -910,7 +934,7 @@
// The max timestamp gap should be less than (captureStall + 1) x average frame
// duration * (1 + error margin).
- int maxCaptureStallFrames = mStaticInfo.getMaxCaptureStallOrDefault();
+ int maxCaptureStallFrames = mTestRule.getStaticInfo().getMaxCaptureStallOrDefault();
for (int i = 0; i < maxCaptureGapsMs.length; i++) {
double stallDurationBound = averageFrameDurationMs[i] *
(maxCaptureStallFrames + 1) * (1 + REPROCESS_STALL_MARGIN);
@@ -939,7 +963,7 @@
TotalCaptureResult zslResult =
mZslResultListener.getCaptureResult(
WAIT_FOR_RESULT_TIMEOUT_MS, inputImages[i].getTimestamp());
- reprocessReqs[i] = mCamera.createReprocessCaptureRequest(zslResult);
+ reprocessReqs[i] = mTestRule.getCamera().createReprocessCaptureRequest(zslResult);
if (requireHighQuality) {
// Reprocessing should support high quality for NR and edge modes.
reprocessReqs[i].set(CaptureRequest.NOISE_REDUCTION_MODE,
@@ -960,7 +984,7 @@
// Submit the requests
for (int i = 0; i < MAX_REPROCESS_IMAGES; i++) {
- mCameraSession.capture(reprocessReqs[i].build(), null, null);
+ mTestRule.getCameraSession().capture(reprocessReqs[i].build(), null, null);
}
// Get images
@@ -982,7 +1006,7 @@
for (int i = 0; i < MAX_REPROCESS_IMAGES; i++) {
startTimeMs = SystemClock.elapsedRealtime();
mWriter.queueInputImage(inputImages[i]);
- mCameraSession.capture(reprocessReqs[i].build(), null, null);
+ mTestRule.getCameraSession().capture(reprocessReqs[i].build(), null, null);
jpegImages[i] = mJpegListener.getImage(CameraTestUtils.CAPTURE_IMAGE_TIMEOUT_MS);
getImageLatenciesMs[i] = SystemClock.elapsedRealtime() - startTimeMs;
}
@@ -1034,16 +1058,17 @@
*/
private void startZslStreaming() throws Exception {
CaptureRequest.Builder zslBuilder =
- mCamera.createCaptureRequest(CameraDevice.TEMPLATE_ZERO_SHUTTER_LAG);
+ mTestRule.getCamera().createCaptureRequest(CameraDevice.TEMPLATE_ZERO_SHUTTER_LAG);
zslBuilder.addTarget(mPreviewSurface);
zslBuilder.addTarget(mCameraZslReader.getSurface());
- mCameraSession.setRepeatingRequest(zslBuilder.build(), mZslResultListener, mHandler);
+ mTestRule.getCameraSession().setRepeatingRequest(
+ zslBuilder.build(), mZslResultListener, mTestRule.getHandler());
}
private void stopZslStreaming() throws Exception {
- mCameraSession.stopRepeating();
- mCameraSessionListener.getStateWaiter().waitForState(
- BlockingSessionCallback.SESSION_READY, CameraTestUtils.CAMERA_IDLE_TIMEOUT_MS);
+ mTestRule.getCameraSession().stopRepeating();
+ mTestRule.getCameraSessionListener().getStateWaiter().waitForState(
+ BlockingSessionCallback.SESSION_READY, CameraTestUtils.CAMERA_IDLE_TIMEOUT_MS);
}
/**
@@ -1076,14 +1101,14 @@
}
private void prepareReprocessCapture(int inputFormat)
- throws CameraAccessException {
+ throws CameraAccessException {
// 1. Find the right preview and capture sizes.
- Size maxPreviewSize = mOrderedPreviewSizes.get(0);
+ Size maxPreviewSize = mTestRule.getOrderedPreviewSizes().get(0);
Size[] supportedInputSizes =
- mStaticInfo.getAvailableSizesForFormatChecked(inputFormat,
- StaticMetadata.StreamDirection.Input);
+ mTestRule.getStaticInfo().getAvailableSizesForFormatChecked(inputFormat,
+ StaticMetadata.StreamDirection.Input);
Size maxInputSize = CameraTestUtils.getMaxSize(supportedInputSizes);
- Size maxJpegSize = mOrderedStillSizes.get(0);
+ Size maxJpegSize = mTestRule.getOrderedStillSizes().get(0);
updatePreviewSurface(maxPreviewSize);
mZslResultListener = new SimpleCaptureCallback();
@@ -1092,11 +1117,13 @@
mCameraZslImageListener = new SimpleImageReaderListener(
/*asyncMode*/true, MAX_ZSL_IMAGES - MAX_REPROCESS_IMAGES);
mCameraZslReader = CameraTestUtils.makeImageReader(
- maxInputSize, inputFormat, MAX_ZSL_IMAGES, mCameraZslImageListener, mHandler);
+ maxInputSize, inputFormat, MAX_ZSL_IMAGES,
+ mCameraZslImageListener, mTestRule.getHandler());
// Jpeg reprocess output
mJpegListener = new SimpleImageReaderListener();
mJpegReader = CameraTestUtils.makeImageReader(
- maxJpegSize, ImageFormat.JPEG, MAX_JPEG_IMAGES, mJpegListener, mHandler);
+ maxJpegSize, ImageFormat.JPEG, MAX_JPEG_IMAGES,
+ mJpegListener, mTestRule.getHandler());
// create camera reprocess session
List<Surface> outSurfaces = new ArrayList<Surface>();
@@ -1105,35 +1132,37 @@
outSurfaces.add(mJpegReader.getSurface());
InputConfiguration inputConfig = new InputConfiguration(maxInputSize.getWidth(),
maxInputSize.getHeight(), inputFormat);
- mCameraSessionListener = new BlockingSessionCallback();
- mCameraSession = CameraTestUtils.configureReprocessableCameraSession(
- mCamera, inputConfig, outSurfaces, mCameraSessionListener, mHandler);
+ mTestRule.setCameraSessionListener(new BlockingSessionCallback());
+ mTestRule.setCameraSession(CameraTestUtils.configureReprocessableCameraSession(
+ mTestRule.getCamera(), inputConfig, outSurfaces,
+ mTestRule.getCameraSessionListener(), mTestRule.getHandler()));
// 3. Create ImageWriter for input
mWriter = CameraTestUtils.makeImageWriter(
- mCameraSession.getInputSurface(), MAX_INPUT_IMAGES, /*listener*/null, /*handler*/null);
-
+ mTestRule.getCameraSession().getInputSurface(), MAX_INPUT_IMAGES,
+ /*listener*/null, /*handler*/null);
}
private void blockingStopPreview() throws Exception {
stopPreview();
- mCameraSessionListener.getStateWaiter().waitForState(SESSION_CLOSED,
- CameraTestUtils.SESSION_CLOSE_TIMEOUT_MS);
+ mTestRule.getCameraSessionListener().getStateWaiter().waitForState(
+ BlockingSessionCallback.SESSION_CLOSED, CameraTestUtils.SESSION_CLOSE_TIMEOUT_MS);
}
private void blockingStartPreview(CaptureCallback listener, SimpleImageListener imageListener)
throws Exception {
- if (mPreviewSurface == null || mReaderSurface == null) {
+ if (mPreviewSurface == null || mTestRule.getReaderSurface() == null) {
throw new IllegalStateException("preview and reader surface must be initilized first");
}
CaptureRequest.Builder previewBuilder =
- mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
- if (mStaticInfo.isColorOutputSupported()) {
+ mTestRule.getCamera().createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
+ if (mTestRule.getStaticInfo().isColorOutputSupported()) {
previewBuilder.addTarget(mPreviewSurface);
}
- previewBuilder.addTarget(mReaderSurface);
- mCameraSession.setRepeatingRequest(previewBuilder.build(), listener, mHandler);
+ previewBuilder.addTarget(mTestRule.getReaderSurface());
+ mTestRule.getCameraSession().setRepeatingRequest(
+ previewBuilder.build(), listener, mTestRule.getHandler());
imageListener.waitForImageAvailable(CameraTestUtils.CAPTURE_IMAGE_TIMEOUT_MS);
}
@@ -1176,13 +1205,14 @@
outputSurfaces.add(mPreviewSurface);
for (int i = 0; i < captureSizes.length; i++) {
readers[i] = CameraTestUtils.makeImageReader(captureSizes[i], formats[i], maxNumImages,
- imageListeners[i], mHandler);
+ imageListeners[i], mTestRule.getHandler());
outputSurfaces.add(readers[i].getSurface());
}
- mCameraSessionListener = new BlockingSessionCallback();
- mCameraSession = CameraTestUtils.configureCameraSession(mCamera, outputSurfaces,
- mCameraSessionListener, mHandler);
+ mTestRule.setCameraSessionListener(new BlockingSessionCallback());
+ mTestRule.setCameraSession(CameraTestUtils.configureCameraSession(
+ mTestRule.getCamera(), outputSurfaces,
+ mTestRule.getCameraSessionListener(), mTestRule.getHandler()));
// Configure the requests.
previewRequest.addTarget(mPreviewSurface);
@@ -1192,7 +1222,8 @@
}
// Start preview.
- mCameraSession.setRepeatingRequest(previewRequest.build(), resultListener, mHandler);
+ mTestRule.getCameraSession().setRepeatingRequest(
+ previewRequest.build(), resultListener, mTestRule.getHandler());
return readers;
}
@@ -1227,27 +1258,29 @@
updatePreviewSurface(previewSz);
// Create ImageReader.
- createDefaultImageReader(captureSz, format, maxNumImages, imageListener);
+ mTestRule.createDefaultImageReader(captureSz, format, maxNumImages, imageListener);
// Configure output streams with preview and jpeg streams.
List<Surface> outputSurfaces = new ArrayList<Surface>();
outputSurfaces.add(mPreviewSurface);
- outputSurfaces.add(mReaderSurface);
+ outputSurfaces.add(mTestRule.getReaderSurface());
if (sessionListener == null) {
- mCameraSessionListener = new BlockingSessionCallback();
+ mTestRule.setCameraSessionListener(new BlockingSessionCallback());
} else {
- mCameraSessionListener = new BlockingSessionCallback(sessionListener);
+ mTestRule.setCameraSessionListener(new BlockingSessionCallback(sessionListener));
}
- mCameraSession = CameraTestUtils.configureCameraSession(mCamera, outputSurfaces,
- mCameraSessionListener, mHandler);
+ mTestRule.setCameraSession(CameraTestUtils.configureCameraSession(
+ mTestRule.getCamera(), outputSurfaces,
+ mTestRule.getCameraSessionListener(), mTestRule.getHandler()));
// Configure the requests.
previewRequest.addTarget(mPreviewSurface);
stillRequest.addTarget(mPreviewSurface);
- stillRequest.addTarget(mReaderSurface);
+ stillRequest.addTarget(mTestRule.getReaderSurface());
// Start preview.
- mCameraSession.setRepeatingRequest(previewRequest.build(), resultListener, mHandler);
+ mTestRule.getCameraSession().setRepeatingRequest(
+ previewRequest.build(), resultListener, mTestRule.getHandler());
}
/**
@@ -1288,7 +1321,7 @@
}
StaticMetadata info = new StaticMetadata(
- mCameraManager.getCameraCharacteristics(cameraId), CheckLevel.ASSERT,
+ mTestRule.getCameraManager().getCameraCharacteristics(cameraId), CheckLevel.ASSERT,
/*collector*/ null);
int cap = CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING;
if (format == ImageFormat.PRIVATE) {
@@ -1303,9 +1336,9 @@
*/
private void stopPreview() throws Exception {
// Stop repeat, wait for captures to complete, and disconnect from surfaces
- if (mCameraSession != null) {
+ if (mTestRule.getCameraSession() != null) {
if (VERBOSE) Log.v(TAG, "Stopping preview");
- mCameraSession.close();
+ mTestRule.getCameraSession().close();
}
}
@@ -1315,10 +1348,10 @@
*/
private void stopPreviewAndDrain() throws Exception {
// Stop repeat, wait for captures to complete, and disconnect from surfaces
- if (mCameraSession != null) {
+ if (mTestRule.getCameraSession() != null) {
if (VERBOSE) Log.v(TAG, "Stopping preview and waiting for idle");
- mCameraSession.close();
- mCameraSessionListener.getStateWaiter().waitForState(
+ mTestRule.getCameraSession().close();
+ mTestRule.getCameraSessionListener().getStateWaiter().waitForState(
BlockingSessionCallback.SESSION_CLOSED,
/*timeoutMs*/WAIT_FOR_RESULT_TIMEOUT_MS);
}
@@ -1328,17 +1361,18 @@
* Configure reader and preview outputs and wait until done.
*/
private void configureReaderAndPreviewOutputs() throws Exception {
- if (mPreviewSurface == null || mReaderSurface == null) {
+ if (mPreviewSurface == null || mTestRule.getReaderSurface() == null) {
throw new IllegalStateException("preview and reader surface must be initilized first");
}
- mCameraSessionListener = new BlockingSessionCallback();
+ mTestRule.setCameraSessionListener(new BlockingSessionCallback());
List<Surface> outputSurfaces = new ArrayList<>();
- if (mStaticInfo.isColorOutputSupported()) {
+ if (mTestRule.getStaticInfo().isColorOutputSupported()) {
outputSurfaces.add(mPreviewSurface);
}
- outputSurfaces.add(mReaderSurface);
- mCameraSession = CameraTestUtils.configureCameraSession(mCamera, outputSurfaces,
- mCameraSessionListener, mHandler);
+ outputSurfaces.add(mTestRule.getReaderSurface());
+ mTestRule.setCameraSession(CameraTestUtils.configureCameraSession(
+ mTestRule.getCamera(), outputSurfaces,
+ mTestRule.getCameraSessionListener(), mTestRule.getHandler()));
}
/**
@@ -1347,21 +1381,24 @@
* @param format The format used to create ImageReader instance.
*/
private void initializeImageReader(String cameraId, int format) throws Exception {
- mOrderedPreviewSizes = CameraTestUtils.getSortedSizesForFormat(
- cameraId, mCameraManager, format,
- CameraTestUtils.getPreviewSizeBound(mWindowManager,
- CameraTestUtils.PREVIEW_SIZE_BOUND));
- Size maxPreviewSize = mOrderedPreviewSizes.get(0);
- createDefaultImageReader(maxPreviewSize, format, NUM_MAX_IMAGES, /*listener*/null);
+ mTestRule.setOrderedPreviewSizes(CameraTestUtils.getSortedSizesForFormat(
+ cameraId, mTestRule.getCameraManager(), format,
+ CameraTestUtils.getPreviewSizeBound(mTestRule.getWindowManager(),
+ CameraTestUtils.PREVIEW_SIZE_BOUND)));
+ Size maxPreviewSize = mTestRule.getOrderedPreviewSizes().get(0);
+ mTestRule.createDefaultImageReader(
+ maxPreviewSize, format, NUM_MAX_IMAGES, /*listener*/null);
updatePreviewSurface(maxPreviewSize);
}
private void simpleOpenCamera(String cameraId) throws Exception {
- mCamera = CameraTestUtils.openCamera(
- mCameraManager, cameraId, mCameraListener, mHandler);
- mCollector.setCameraId(cameraId);
- mStaticInfo = new StaticMetadata(mCameraManager.getCameraCharacteristics(cameraId),
- CheckLevel.ASSERT, /*collector*/null);
+ mTestRule.setCamera(CameraTestUtils.openCamera(
+ mTestRule.getCameraManager(), cameraId,
+ mTestRule.getCameraListener(), mTestRule.getHandler()));
+ mTestRule.getCollector().setCameraId(cameraId);
+ mTestRule.setStaticInfo(new StaticMetadata(
+ mTestRule.getCameraManager().getCameraCharacteristics(cameraId),
+ CheckLevel.ASSERT, /*collector*/null));
}
/**
@@ -1514,4 +1551,4 @@
}
}
-}
+}
\ No newline at end of file
diff --git a/tests/camera/src/android/hardware/camera2/cts/RobustnessTest.java b/tests/camera/src/android/hardware/camera2/cts/RobustnessTest.java
index e2bbb9c..918daeb 100644
--- a/tests/camera/src/android/hardware/camera2/cts/RobustnessTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/RobustnessTest.java
@@ -17,6 +17,7 @@
package android.hardware.camera2.cts;
import static android.hardware.camera2.cts.CameraTestUtils.*;
+import static android.hardware.camera2.cts.RobustnessTest.MaxStreamSizes.*;
import android.content.Context;
import android.graphics.ImageFormat;
@@ -38,12 +39,16 @@
import android.hardware.camera2.params.MandatoryStreamCombination.MandatoryStreamInformation;
import android.hardware.camera2.params.SessionConfiguration;
import android.hardware.camera2.params.StreamConfigurationMap;
+import android.media.CamcorderProfile;
import android.media.Image;
import android.media.ImageReader;
import android.media.ImageWriter;
import android.util.Log;
+import android.util.Pair;
import android.util.Size;
+import android.view.Display;
import android.view.Surface;
+import android.view.WindowManager;
import com.android.ex.camera2.blocking.BlockingSessionCallback;
@@ -1807,4 +1812,810 @@
return precaptureComplete;
}
+ /**
+ * Test for making sure that all expected mandatory stream combinations are present and
+ * advertised accordingly.
+ */
+ @Test
+ public void testVerifyMandatoryOutputCombinationTables() throws Exception {
+ final int[][] LEGACY_COMBINATIONS = {
+ // Simple preview, GPU video processing, or no-preview video recording
+ {PRIV, MAXIMUM},
+ // No-viewfinder still image capture
+ {JPEG, MAXIMUM},
+ // In-application video/image processing
+ {YUV, MAXIMUM},
+ // Standard still imaging.
+ {PRIV, PREVIEW, JPEG, MAXIMUM},
+ // In-app processing plus still capture.
+ {YUV, PREVIEW, JPEG, MAXIMUM},
+ // Standard recording.
+ {PRIV, PREVIEW, PRIV, PREVIEW},
+ // Preview plus in-app processing.
+ {PRIV, PREVIEW, YUV, PREVIEW},
+ // Still capture plus in-app processing.
+ {PRIV, PREVIEW, YUV, PREVIEW, JPEG, MAXIMUM}
+ };
+
+ final int[][] LIMITED_COMBINATIONS = {
+ // High-resolution video recording with preview.
+ {PRIV, PREVIEW, PRIV, RECORD },
+ // High-resolution in-app video processing with preview.
+ {PRIV, PREVIEW, YUV , RECORD },
+ // Two-input in-app video processing.
+ {YUV , PREVIEW, YUV , RECORD },
+ // High-resolution recording with video snapshot.
+ {PRIV, PREVIEW, PRIV, RECORD, JPEG, RECORD },
+ // High-resolution in-app processing with video snapshot.
+ {PRIV, PREVIEW, YUV, RECORD, JPEG, RECORD },
+ // Two-input in-app processing with still capture.
+ {YUV , PREVIEW, YUV, PREVIEW, JPEG, MAXIMUM }
+ };
+
+ final int[][] BURST_COMBINATIONS = {
+ // Maximum-resolution GPU processing with preview.
+ {PRIV, PREVIEW, PRIV, MAXIMUM },
+ // Maximum-resolution in-app processing with preview.
+ {PRIV, PREVIEW, YUV, MAXIMUM },
+ // Maximum-resolution two-input in-app processing.
+ {YUV, PREVIEW, YUV, MAXIMUM },
+ };
+
+ final int[][] FULL_COMBINATIONS = {
+ // Video recording with maximum-size video snapshot.
+ {PRIV, PREVIEW, PRIV, PREVIEW, JPEG, MAXIMUM },
+ // Standard video recording plus maximum-resolution in-app processing.
+ {YUV, VGA, PRIV, PREVIEW, YUV, MAXIMUM },
+ // Preview plus two-input maximum-resolution in-app processing.
+ {YUV, VGA, YUV, PREVIEW, YUV, MAXIMUM }
+ };
+
+ final int[][] RAW_COMBINATIONS = {
+ // No-preview DNG capture.
+ {RAW, MAXIMUM },
+ // Standard DNG capture.
+ {PRIV, PREVIEW, RAW, MAXIMUM },
+ // In-app processing plus DNG capture.
+ {YUV, PREVIEW, RAW, MAXIMUM },
+ // Video recording with DNG capture.
+ {PRIV, PREVIEW, PRIV, PREVIEW, RAW, MAXIMUM},
+ // Preview with in-app processing and DNG capture.
+ {PRIV, PREVIEW, YUV, PREVIEW, RAW, MAXIMUM},
+ // Two-input in-app processing plus DNG capture.
+ {YUV, PREVIEW, YUV, PREVIEW, RAW, MAXIMUM},
+ // Still capture with simultaneous JPEG and DNG.
+ {PRIV, PREVIEW, JPEG, MAXIMUM, RAW, MAXIMUM},
+ // In-app processing with simultaneous JPEG and DNG.
+ {YUV, PREVIEW, JPEG, MAXIMUM, RAW, MAXIMUM}
+ };
+
+ final int[][] LEVEL_3_COMBINATIONS = {
+ // In-app viewfinder analysis with dynamic selection of output format
+ {PRIV, PREVIEW, PRIV, VGA, YUV, MAXIMUM, RAW, MAXIMUM},
+ // In-app viewfinder analysis with dynamic selection of output format
+ {PRIV, PREVIEW, PRIV, VGA, JPEG, MAXIMUM, RAW, MAXIMUM}
+ };
+
+ final int[][][] TABLES =
+ { LEGACY_COMBINATIONS, LIMITED_COMBINATIONS, BURST_COMBINATIONS, FULL_COMBINATIONS,
+ RAW_COMBINATIONS, LEVEL_3_COMBINATIONS };
+
+ sanityCheckConfigurationTables(TABLES);
+
+ for (String id : mCameraIdsUnderTest) {
+ openDevice(id);
+ MandatoryStreamCombination[] combinations =
+ mStaticInfo.getCharacteristics().get(
+ CameraCharacteristics.SCALER_MANDATORY_STREAM_COMBINATIONS);
+ if ((combinations == null) || (combinations.length == 0)) {
+ Log.i(TAG, "No mandatory stream combinations for camera: " + id + " skip test");
+ closeDevice(id);
+ continue;
+ }
+
+ MaxStreamSizes maxSizes = new MaxStreamSizes(mStaticInfo, id, mContext);
+ try {
+ if (mStaticInfo.isColorOutputSupported()) {
+ for (int[] c : LEGACY_COMBINATIONS) {
+ assertTrue(String.format("Expected static stream combination: %s not " +
+ "found among the available mandatory combinations",
+ maxSizes.combinationToString(c)),
+ isMandatoryCombinationAvailable(c, maxSizes, combinations));
+ }
+ }
+
+ if (!mStaticInfo.isHardwareLevelLegacy()) {
+ if (mStaticInfo.isColorOutputSupported()) {
+ for (int[] c : LIMITED_COMBINATIONS) {
+ assertTrue(String.format("Expected static stream combination: %s not " +
+ "found among the available mandatory combinations",
+ maxSizes.combinationToString(c)),
+ isMandatoryCombinationAvailable(c, maxSizes, combinations));
+ }
+ }
+
+ if (mStaticInfo.isCapabilitySupported(
+ CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE)) {
+ for (int[] c : BURST_COMBINATIONS) {
+ assertTrue(String.format("Expected static stream combination: %s not " +
+ "found among the available mandatory combinations",
+ maxSizes.combinationToString(c)),
+ isMandatoryCombinationAvailable(c, maxSizes, combinations));
+ }
+ }
+
+ if (mStaticInfo.isHardwareLevelAtLeastFull()) {
+ for (int[] c : FULL_COMBINATIONS) {
+ assertTrue(String.format("Expected static stream combination: %s not " +
+ "found among the available mandatory combinations",
+ maxSizes.combinationToString(c)),
+ isMandatoryCombinationAvailable(c, maxSizes, combinations));
+ }
+ }
+
+ if (mStaticInfo.isCapabilitySupported(
+ CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_RAW)) {
+ for (int[] c : RAW_COMBINATIONS) {
+ assertTrue(String.format("Expected static stream combination: %s not " +
+ "found among the available mandatory combinations",
+ maxSizes.combinationToString(c)),
+ isMandatoryCombinationAvailable(c, maxSizes, combinations));
+ }
+ }
+
+ if (mStaticInfo.isHardwareLevelAtLeast(
+ CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_3)) {
+ for (int[] c: LEVEL_3_COMBINATIONS) {
+ assertTrue(String.format("Expected static stream combination: %s not " +
+ "found among the available mandatory combinations",
+ maxSizes.combinationToString(c)),
+ isMandatoryCombinationAvailable(c, maxSizes, combinations));
+ }
+ }
+ }
+ } finally {
+ closeDevice(id);
+ }
+ }
+ }
+
+ /**
+ * Test for making sure that all expected reprocessable mandatory stream combinations are
+ * present and advertised accordingly.
+ */
+ @Test
+ public void testVerifyReprocessMandatoryOutputCombinationTables() throws Exception {
+ final int[][] LIMITED_COMBINATIONS = {
+ // Input Outputs
+ {PRIV, MAXIMUM, JPEG, MAXIMUM},
+ {YUV , MAXIMUM, JPEG, MAXIMUM},
+ {PRIV, MAXIMUM, PRIV, PREVIEW, JPEG, MAXIMUM},
+ {YUV , MAXIMUM, PRIV, PREVIEW, JPEG, MAXIMUM},
+ {PRIV, MAXIMUM, YUV , PREVIEW, JPEG, MAXIMUM},
+ {YUV , MAXIMUM, YUV , PREVIEW, JPEG, MAXIMUM},
+ {PRIV, MAXIMUM, YUV , PREVIEW, YUV , PREVIEW, JPEG, MAXIMUM},
+ {YUV, MAXIMUM, YUV , PREVIEW, YUV , PREVIEW, JPEG, MAXIMUM},
+ };
+
+ final int[][] FULL_COMBINATIONS = {
+ // Input Outputs
+ {YUV , MAXIMUM, PRIV, PREVIEW},
+ {YUV , MAXIMUM, YUV , PREVIEW},
+ {PRIV, MAXIMUM, PRIV, PREVIEW, YUV , RECORD},
+ {YUV , MAXIMUM, PRIV, PREVIEW, YUV , RECORD},
+ {PRIV, MAXIMUM, PRIV, PREVIEW, YUV , MAXIMUM},
+ {PRIV, MAXIMUM, YUV , PREVIEW, YUV , MAXIMUM},
+ {PRIV, MAXIMUM, PRIV, PREVIEW, YUV , PREVIEW, JPEG, MAXIMUM},
+ {YUV , MAXIMUM, PRIV, PREVIEW, YUV , PREVIEW, JPEG, MAXIMUM},
+ };
+
+ final int[][] RAW_COMBINATIONS = {
+ // Input Outputs
+ {PRIV, MAXIMUM, YUV , PREVIEW, RAW , MAXIMUM},
+ {YUV , MAXIMUM, YUV , PREVIEW, RAW , MAXIMUM},
+ {PRIV, MAXIMUM, PRIV, PREVIEW, YUV , PREVIEW, RAW , MAXIMUM},
+ {YUV , MAXIMUM, PRIV, PREVIEW, YUV , PREVIEW, RAW , MAXIMUM},
+ {PRIV, MAXIMUM, YUV , PREVIEW, YUV , PREVIEW, RAW , MAXIMUM},
+ {YUV , MAXIMUM, YUV , PREVIEW, YUV , PREVIEW, RAW , MAXIMUM},
+ {PRIV, MAXIMUM, PRIV, PREVIEW, JPEG, MAXIMUM, RAW , MAXIMUM},
+ {YUV , MAXIMUM, PRIV, PREVIEW, JPEG, MAXIMUM, RAW , MAXIMUM},
+ {PRIV, MAXIMUM, YUV , PREVIEW, JPEG, MAXIMUM, RAW , MAXIMUM},
+ {YUV , MAXIMUM, YUV , PREVIEW, JPEG, MAXIMUM, RAW , MAXIMUM},
+ };
+
+ final int[][] LEVEL_3_COMBINATIONS = {
+ // Input Outputs
+ // In-app viewfinder analysis with YUV->YUV ZSL and RAW
+ {YUV , MAXIMUM, PRIV, PREVIEW, PRIV, VGA, RAW, MAXIMUM},
+ // In-app viewfinder analysis with PRIV->JPEG ZSL and RAW
+ {PRIV, MAXIMUM, PRIV, PREVIEW, PRIV, VGA, RAW, MAXIMUM, JPEG, MAXIMUM},
+ // In-app viewfinder analysis with YUV->JPEG ZSL and RAW
+ {YUV , MAXIMUM, PRIV, PREVIEW, PRIV, VGA, RAW, MAXIMUM, JPEG, MAXIMUM},
+ };
+
+ final int[][][] TABLES =
+ { LIMITED_COMBINATIONS, FULL_COMBINATIONS, RAW_COMBINATIONS, LEVEL_3_COMBINATIONS };
+
+ sanityCheckConfigurationTables(TABLES);
+
+ for (String id : mCameraIdsUnderTest) {
+ openDevice(id);
+ MandatoryStreamCombination[] cs = mStaticInfo.getCharacteristics().get(
+ CameraCharacteristics.SCALER_MANDATORY_STREAM_COMBINATIONS);
+ if ((cs == null) || (cs.length == 0)) {
+ Log.i(TAG, "No mandatory stream combinations for camera: " + id + " skip test");
+ closeDevice(id);
+ continue;
+ }
+
+ boolean supportYuvReprocess = mStaticInfo.isCapabilitySupported(
+ CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING);
+ boolean supportOpaqueReprocess = mStaticInfo.isCapabilitySupported(
+ CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_PRIVATE_REPROCESSING);
+ if (!supportYuvReprocess && !supportOpaqueReprocess) {
+ Log.i(TAG, "No reprocess support for camera: " + id + " skip test");
+ closeDevice(id);
+ continue;
+ }
+
+ MaxStreamSizes maxSizes = new MaxStreamSizes(mStaticInfo, id, mContext);
+ try {
+ for (int[] c : LIMITED_COMBINATIONS) {
+ assertTrue(String.format("Expected static reprocessable stream combination:" +
+ "%s not found among the available mandatory combinations",
+ maxSizes.reprocessCombinationToString(c)),
+ isMandatoryCombinationAvailable(c, maxSizes, /*isInput*/ true, cs));
+ }
+
+ if (mStaticInfo.isHardwareLevelAtLeastFull()) {
+ for (int[] c : FULL_COMBINATIONS) {
+ assertTrue(String.format(
+ "Expected static reprocessable stream combination:" +
+ "%s not found among the available mandatory combinations",
+ maxSizes.reprocessCombinationToString(c)),
+ isMandatoryCombinationAvailable(c, maxSizes, /*isInput*/ true, cs));
+ }
+ }
+
+ if (mStaticInfo.isCapabilitySupported(
+ CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_RAW)) {
+ for (int[] c : RAW_COMBINATIONS) {
+ assertTrue(String.format(
+ "Expected static reprocessable stream combination:" +
+ "%s not found among the available mandatory combinations",
+ maxSizes.reprocessCombinationToString(c)),
+ isMandatoryCombinationAvailable(c, maxSizes, /*isInput*/ true, cs));
+ }
+ }
+
+ if (mStaticInfo.isHardwareLevelAtLeast(
+ CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_3)) {
+ for (int[] c : LEVEL_3_COMBINATIONS) {
+ assertTrue(String.format(
+ "Expected static reprocessable stream combination:" +
+ "%s not found among the available mandatory combinations",
+ maxSizes.reprocessCombinationToString(c)),
+ isMandatoryCombinationAvailable(c, maxSizes, /*isInput*/ true, cs));
+ }
+ }
+ } finally {
+ closeDevice(id);
+ }
+ }
+ }
+
+ private boolean isMandatoryCombinationAvailable(final int[] combination,
+ final MaxStreamSizes maxSizes,
+ final MandatoryStreamCombination[] availableCombinations) {
+ return isMandatoryCombinationAvailable(combination, maxSizes, /*isInput*/ false,
+ availableCombinations);
+ }
+
+ private boolean isMandatoryCombinationAvailable(final int[] combination,
+ final MaxStreamSizes maxSizes, boolean isInput,
+ final MandatoryStreamCombination[] availableCombinations) {
+ // Static combinations to be verified can be composed of multiple entries
+ // that have the following layout (format, size). In case "isInput" is set,
+ // the first stream configuration entry will contain the input format and size
+ // as well as the first matching output.
+ int streamCount = combination.length / 2;
+ ArrayList<Pair<Pair<Integer, Boolean>, Size>> currentCombination =
+ new ArrayList<Pair<Pair<Integer, Boolean>, Size>>(streamCount);
+ for (int i = 0; i < combination.length; i += 2) {
+ if (isInput && (i == 0)) {
+ Size sz = maxSizes.getMaxInputSizeForFormat(combination[i]);
+ currentCombination.add(Pair.create(Pair.create(new Integer(combination[i]),
+ new Boolean(true)), sz));
+ currentCombination.add(Pair.create(Pair.create(new Integer(combination[i]),
+ new Boolean(false)), sz));
+ } else {
+ Size sz = maxSizes.getOutputSizeForFormat(combination[i], combination[i+1]);
+ currentCombination.add(Pair.create(Pair.create(new Integer(combination[i]),
+ new Boolean(false)), sz));
+ }
+ }
+
+ for (MandatoryStreamCombination c : availableCombinations) {
+ List<MandatoryStreamInformation> streamInfoList = c.getStreamsInformation();
+ if ((streamInfoList.size() == currentCombination.size()) &&
+ (isInput == c.isReprocessable())) {
+ ArrayList<Pair<Pair<Integer, Boolean>, Size>> expected =
+ new ArrayList<Pair<Pair<Integer, Boolean>, Size>>(currentCombination);
+
+ for (MandatoryStreamInformation streamInfo : streamInfoList) {
+ Size maxSize = CameraTestUtils.getMaxSize(
+ streamInfo.getAvailableSizes().toArray(new Size[0]));
+ Pair p = Pair.create(Pair.create(new Integer(streamInfo.getFormat()),
+ new Boolean(streamInfo.isInput())), maxSize);
+ if (expected.contains(p)) {
+ expected.remove(p);
+ }
+ }
+
+ if (expected.isEmpty()) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Sanity check the configuration tables.
+ */
+ private void sanityCheckConfigurationTables(final int[][][] tables) throws Exception {
+ int tableIdx = 0;
+ for (int[][] table : tables) {
+ int rowIdx = 0;
+ for (int[] row : table) {
+ assertTrue(String.format("Odd number of entries for table %d row %d: %s ",
+ tableIdx, rowIdx, Arrays.toString(row)),
+ (row.length % 2) == 0);
+ for (int i = 0; i < row.length; i += 2) {
+ int format = row[i];
+ int maxSize = row[i + 1];
+ assertTrue(String.format("table %d row %d index %d format not valid: %d",
+ tableIdx, rowIdx, i, format),
+ format == PRIV || format == JPEG || format == YUV || format == RAW);
+ assertTrue(String.format("table %d row %d index %d max size not valid: %d",
+ tableIdx, rowIdx, i + 1, maxSize),
+ maxSize == PREVIEW || maxSize == RECORD ||
+ maxSize == MAXIMUM || maxSize == VGA);
+ }
+ rowIdx++;
+ }
+ tableIdx++;
+ }
+ }
+
+ /**
+ * Simple holder for resolutions to use for different camera outputs and size limits.
+ */
+ static class MaxStreamSizes {
+ // Format shorthands
+ static final int PRIV = ImageFormat.PRIVATE;
+ static final int JPEG = ImageFormat.JPEG;
+ static final int YUV = ImageFormat.YUV_420_888;
+ static final int RAW = ImageFormat.RAW_SENSOR;
+ static final int Y8 = ImageFormat.Y8;
+ static final int HEIC = ImageFormat.HEIC;
+
+ // Max resolution indices
+ static final int PREVIEW = 0;
+ static final int RECORD = 1;
+ static final int MAXIMUM = 2;
+ static final int VGA = 3;
+ static final int VGA_FULL_FOV = 4;
+ static final int MAX_30FPS = 5;
+ static final int RESOLUTION_COUNT = 6;
+
+ static final long FRAME_DURATION_30FPS_NSEC = (long) 1e9 / 30;
+
+ public MaxStreamSizes(StaticMetadata sm, String cameraId, Context context) {
+ Size[] privSizes = sm.getAvailableSizesForFormatChecked(ImageFormat.PRIVATE,
+ StaticMetadata.StreamDirection.Output);
+ Size[] yuvSizes = sm.getAvailableSizesForFormatChecked(ImageFormat.YUV_420_888,
+ StaticMetadata.StreamDirection.Output);
+ Size[] y8Sizes = sm.getAvailableSizesForFormatChecked(ImageFormat.Y8,
+ StaticMetadata.StreamDirection.Output);
+ Size[] jpegSizes = sm.getJpegOutputSizesChecked();
+ Size[] rawSizes = sm.getRawOutputSizesChecked();
+ Size[] heicSizes = sm.getHeicOutputSizesChecked();
+
+ Size maxPreviewSize = getMaxPreviewSize(context, cameraId);
+
+ maxRawSize = (rawSizes.length != 0) ? CameraTestUtils.getMaxSize(rawSizes) : null;
+
+ StreamConfigurationMap configs = sm.getCharacteristics().get(
+ CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
+ if (sm.isColorOutputSupported()) {
+ maxPrivSizes[PREVIEW] = getMaxSize(privSizes, maxPreviewSize);
+ maxYuvSizes[PREVIEW] = getMaxSize(yuvSizes, maxPreviewSize);
+ maxJpegSizes[PREVIEW] = getMaxSize(jpegSizes, maxPreviewSize);
+
+ if (sm.isExternalCamera()) {
+ maxPrivSizes[RECORD] = getMaxExternalRecordingSize(cameraId, configs);
+ maxYuvSizes[RECORD] = getMaxExternalRecordingSize(cameraId, configs);
+ maxJpegSizes[RECORD] = getMaxExternalRecordingSize(cameraId, configs);
+ } else {
+ maxPrivSizes[RECORD] = getMaxRecordingSize(cameraId);
+ maxYuvSizes[RECORD] = getMaxRecordingSize(cameraId);
+ maxJpegSizes[RECORD] = getMaxRecordingSize(cameraId);
+ }
+
+ maxPrivSizes[MAXIMUM] = CameraTestUtils.getMaxSize(privSizes);
+ maxYuvSizes[MAXIMUM] = CameraTestUtils.getMaxSize(yuvSizes);
+ maxJpegSizes[MAXIMUM] = CameraTestUtils.getMaxSize(jpegSizes);
+
+ // Must always be supported, add unconditionally
+ final Size vgaSize = new Size(640, 480);
+ maxPrivSizes[VGA] = vgaSize;
+ maxYuvSizes[VGA] = vgaSize;
+ maxJpegSizes[VGA] = vgaSize;
+
+ if (sm.isMonochromeWithY8()) {
+ maxY8Sizes[PREVIEW] = getMaxSize(y8Sizes, maxPreviewSize);
+ if (sm.isExternalCamera()) {
+ maxY8Sizes[RECORD] = getMaxExternalRecordingSize(cameraId, configs);
+ } else {
+ maxY8Sizes[RECORD] = getMaxRecordingSize(cameraId);
+ }
+ maxY8Sizes[MAXIMUM] = CameraTestUtils.getMaxSize(y8Sizes);
+ maxY8Sizes[VGA] = vgaSize;
+ }
+
+ if (sm.isHeicSupported()) {
+ maxHeicSizes[PREVIEW] = getMaxSize(heicSizes, maxPreviewSize);
+ maxHeicSizes[RECORD] = getMaxRecordingSize(cameraId);
+ maxHeicSizes[MAXIMUM] = CameraTestUtils.getMaxSize(heicSizes);
+ maxHeicSizes[VGA] = vgaSize;
+ }
+ }
+ if (sm.isColorOutputSupported() && !sm.isHardwareLevelLegacy()) {
+ // VGA resolution, but with aspect ratio matching full res FOV
+ float fullFovAspect = maxYuvSizes[MAXIMUM].getWidth() /
+ (float) maxYuvSizes[MAXIMUM].getHeight();
+ Size vgaFullFovSize = new Size(640, (int) (640 / fullFovAspect));
+
+ maxPrivSizes[VGA_FULL_FOV] = vgaFullFovSize;
+ maxYuvSizes[VGA_FULL_FOV] = vgaFullFovSize;
+ maxJpegSizes[VGA_FULL_FOV] = vgaFullFovSize;
+ if (sm.isMonochromeWithY8()) {
+ maxY8Sizes[VGA_FULL_FOV] = vgaFullFovSize;
+ }
+
+ // Max resolution that runs at 30fps
+
+ Size maxPriv30fpsSize = null;
+ Size maxYuv30fpsSize = null;
+ Size maxY830fpsSize = null;
+ Size maxJpeg30fpsSize = null;
+ Comparator<Size> comparator = new SizeComparator();
+ for (Map.Entry<Size, Long> e :
+ sm.getAvailableMinFrameDurationsForFormatChecked(ImageFormat.PRIVATE).
+ entrySet()) {
+ Size s = e.getKey();
+ Long minDuration = e.getValue();
+ Log.d(TAG, String.format("Priv Size: %s, duration %d limit %d", s, minDuration,
+ FRAME_DURATION_30FPS_NSEC));
+ if (minDuration <= FRAME_DURATION_30FPS_NSEC) {
+ if (maxPriv30fpsSize == null ||
+ comparator.compare(maxPriv30fpsSize, s) < 0) {
+ maxPriv30fpsSize = s;
+ }
+ }
+ }
+ assertTrue("No PRIVATE resolution available at 30fps!", maxPriv30fpsSize != null);
+
+ for (Map.Entry<Size, Long> e :
+ sm.getAvailableMinFrameDurationsForFormatChecked(
+ ImageFormat.YUV_420_888).
+ entrySet()) {
+ Size s = e.getKey();
+ Long minDuration = e.getValue();
+ Log.d(TAG, String.format("YUV Size: %s, duration %d limit %d", s, minDuration,
+ FRAME_DURATION_30FPS_NSEC));
+ if (minDuration <= FRAME_DURATION_30FPS_NSEC) {
+ if (maxYuv30fpsSize == null ||
+ comparator.compare(maxYuv30fpsSize, s) < 0) {
+ maxYuv30fpsSize = s;
+ }
+ }
+ }
+ assertTrue("No YUV_420_888 resolution available at 30fps!",
+ maxYuv30fpsSize != null);
+
+ if (sm.isMonochromeWithY8()) {
+ for (Map.Entry<Size, Long> e :
+ sm.getAvailableMinFrameDurationsForFormatChecked(
+ ImageFormat.Y8).
+ entrySet()) {
+ Size s = e.getKey();
+ Long minDuration = e.getValue();
+ Log.d(TAG, String.format("Y8 Size: %s, duration %d limit %d",
+ s, minDuration, FRAME_DURATION_30FPS_NSEC));
+ if (minDuration <= FRAME_DURATION_30FPS_NSEC) {
+ if (maxY830fpsSize == null ||
+ comparator.compare(maxY830fpsSize, s) < 0) {
+ maxY830fpsSize = s;
+ }
+ }
+ }
+ assertTrue("No Y8 resolution available at 30fps!", maxY830fpsSize != null);
+ }
+
+ for (Map.Entry<Size, Long> e :
+ sm.getAvailableMinFrameDurationsForFormatChecked(ImageFormat.JPEG).
+ entrySet()) {
+ Size s = e.getKey();
+ Long minDuration = e.getValue();
+ Log.d(TAG, String.format("JPEG Size: %s, duration %d limit %d", s, minDuration,
+ FRAME_DURATION_30FPS_NSEC));
+ if (minDuration <= FRAME_DURATION_30FPS_NSEC) {
+ if (maxJpeg30fpsSize == null ||
+ comparator.compare(maxJpeg30fpsSize, s) < 0) {
+ maxJpeg30fpsSize = s;
+ }
+ }
+ }
+ assertTrue("No JPEG resolution available at 30fps!", maxJpeg30fpsSize != null);
+
+ maxPrivSizes[MAX_30FPS] = maxPriv30fpsSize;
+ maxYuvSizes[MAX_30FPS] = maxYuv30fpsSize;
+ maxY8Sizes[MAX_30FPS] = maxY830fpsSize;
+ maxJpegSizes[MAX_30FPS] = maxJpeg30fpsSize;
+ }
+
+ Size[] privInputSizes = configs.getInputSizes(ImageFormat.PRIVATE);
+ maxInputPrivSize = privInputSizes != null ?
+ CameraTestUtils.getMaxSize(privInputSizes) : null;
+ Size[] yuvInputSizes = configs.getInputSizes(ImageFormat.YUV_420_888);
+ maxInputYuvSize = yuvInputSizes != null ?
+ CameraTestUtils.getMaxSize(yuvInputSizes) : null;
+ Size[] y8InputSizes = configs.getInputSizes(ImageFormat.Y8);
+ maxInputY8Size = y8InputSizes != null ?
+ CameraTestUtils.getMaxSize(y8InputSizes) : null;
+ }
+
+ private final Size[] maxPrivSizes = new Size[RESOLUTION_COUNT];
+ private final Size[] maxJpegSizes = new Size[RESOLUTION_COUNT];
+ private final Size[] maxYuvSizes = new Size[RESOLUTION_COUNT];
+ private final Size[] maxY8Sizes = new Size[RESOLUTION_COUNT];
+ private final Size[] maxHeicSizes = new Size[RESOLUTION_COUNT];
+ private final Size maxRawSize;
+ // TODO: support non maximum reprocess input.
+ private final Size maxInputPrivSize;
+ private final Size maxInputYuvSize;
+ private final Size maxInputY8Size;
+
+ public final Size getOutputSizeForFormat(int format, int resolutionIndex) {
+ if (resolutionIndex >= RESOLUTION_COUNT) {
+ return new Size(0, 0);
+ }
+
+ switch (format) {
+ case PRIV:
+ return maxPrivSizes[resolutionIndex];
+ case YUV:
+ return maxYuvSizes[resolutionIndex];
+ case JPEG:
+ return maxJpegSizes[resolutionIndex];
+ case Y8:
+ return maxY8Sizes[resolutionIndex];
+ case HEIC:
+ return maxHeicSizes[resolutionIndex];
+ case RAW:
+ return maxRawSize;
+ default:
+ return new Size(0, 0);
+ }
+ }
+
+ public final Size getMaxInputSizeForFormat(int format) {
+ switch (format) {
+ case PRIV:
+ return maxInputPrivSize;
+ case YUV:
+ return maxInputYuvSize;
+ case Y8:
+ return maxInputY8Size;
+ default:
+ return new Size(0, 0);
+ }
+ }
+
+ static public String combinationToString(int[] combination) {
+ StringBuilder b = new StringBuilder("{ ");
+ for (int i = 0; i < combination.length; i += 2) {
+ int format = combination[i];
+ int sizeLimit = combination[i + 1];
+
+ appendFormatSize(b, format, sizeLimit);
+ b.append(" ");
+ }
+ b.append("}");
+ return b.toString();
+ }
+
+ static public String reprocessCombinationToString(int[] reprocessCombination) {
+ // reprocessConfig[0..1] is the input configuration
+ StringBuilder b = new StringBuilder("Input: ");
+ appendFormatSize(b, reprocessCombination[0], reprocessCombination[1]);
+
+ // reprocessCombnation[0..1] is also output combination to be captured as reprocess
+ // input.
+ b.append(", Outputs: { ");
+ for (int i = 0; i < reprocessCombination.length; i += 2) {
+ int format = reprocessCombination[i];
+ int sizeLimit = reprocessCombination[i + 1];
+
+ appendFormatSize(b, format, sizeLimit);
+ b.append(" ");
+ }
+ b.append("}");
+ return b.toString();
+ }
+
+ static private void appendFormatSize(StringBuilder b, int format, int Size) {
+ switch (format) {
+ case PRIV:
+ b.append("[PRIV, ");
+ break;
+ case JPEG:
+ b.append("[JPEG, ");
+ break;
+ case YUV:
+ b.append("[YUV, ");
+ break;
+ case Y8:
+ b.append("[Y8, ");
+ break;
+ case RAW:
+ b.append("[RAW, ");
+ break;
+ default:
+ b.append("[UNK, ");
+ break;
+ }
+
+ switch (Size) {
+ case PREVIEW:
+ b.append("PREVIEW]");
+ break;
+ case RECORD:
+ b.append("RECORD]");
+ break;
+ case MAXIMUM:
+ b.append("MAXIMUM]");
+ break;
+ case VGA:
+ b.append("VGA]");
+ break;
+ case VGA_FULL_FOV:
+ b.append("VGA_FULL_FOV]");
+ break;
+ case MAX_30FPS:
+ b.append("MAX_30FPS]");
+ break;
+ default:
+ b.append("UNK]");
+ break;
+ }
+ }
+ }
+
+ private static Size getMaxRecordingSize(String cameraId) {
+ int id = Integer.valueOf(cameraId);
+
+ int quality =
+ CamcorderProfile.hasProfile(id, CamcorderProfile.QUALITY_2160P) ?
+ CamcorderProfile.QUALITY_2160P :
+ CamcorderProfile.hasProfile(id, CamcorderProfile.QUALITY_1080P) ?
+ CamcorderProfile.QUALITY_1080P :
+ CamcorderProfile.hasProfile(id, CamcorderProfile.QUALITY_720P) ?
+ CamcorderProfile.QUALITY_720P :
+ CamcorderProfile.hasProfile(id, CamcorderProfile.QUALITY_480P) ?
+ CamcorderProfile.QUALITY_480P :
+ CamcorderProfile.hasProfile(id, CamcorderProfile.QUALITY_QVGA) ?
+ CamcorderProfile.QUALITY_QVGA :
+ CamcorderProfile.hasProfile(id, CamcorderProfile.QUALITY_CIF) ?
+ CamcorderProfile.QUALITY_CIF :
+ CamcorderProfile.hasProfile(id, CamcorderProfile.QUALITY_QCIF) ?
+ CamcorderProfile.QUALITY_QCIF :
+ -1;
+
+ assertTrue("No recording supported for camera id " + cameraId, quality != -1);
+
+ CamcorderProfile maxProfile = CamcorderProfile.get(id, quality);
+ return new Size(maxProfile.videoFrameWidth, maxProfile.videoFrameHeight);
+ }
+
+ private static Size getMaxExternalRecordingSize(
+ String cameraId, StreamConfigurationMap config) {
+ final Size FULLHD = new Size(1920, 1080);
+
+ Size[] videoSizeArr = config.getOutputSizes(android.media.MediaRecorder.class);
+ List<Size> sizes = new ArrayList<Size>();
+ for (Size sz: videoSizeArr) {
+ if (sz.getWidth() <= FULLHD.getWidth() && sz.getHeight() <= FULLHD.getHeight()) {
+ sizes.add(sz);
+ }
+ }
+ List<Size> videoSizes = getAscendingOrderSizes(sizes, /*ascending*/false);
+ for (Size sz : videoSizes) {
+ long minFrameDuration = config.getOutputMinFrameDuration(
+ android.media.MediaRecorder.class, sz);
+ // Give some margin for rounding error
+ if (minFrameDuration > (1e9 / 30.1)) {
+ Log.i(TAG, "External camera " + cameraId + " has max video size:" + sz);
+ return sz;
+ }
+ }
+ fail("Camera " + cameraId + " does not support any 30fps video output");
+ return FULLHD; // doesn't matter what size is returned here
+ }
+
+ /**
+ * Get maximum size in list that's equal or smaller to than the bound.
+ * Returns null if no size is smaller than or equal to the bound.
+ */
+ private static Size getMaxSize(Size[] sizes, Size bound) {
+ if (sizes == null || sizes.length == 0) {
+ throw new IllegalArgumentException("sizes was empty");
+ }
+
+ Size sz = null;
+ for (Size size : sizes) {
+ if (size.getWidth() <= bound.getWidth() && size.getHeight() <= bound.getHeight()) {
+
+ if (sz == null) {
+ sz = size;
+ } else {
+ long curArea = sz.getWidth() * (long) sz.getHeight();
+ long newArea = size.getWidth() * (long) size.getHeight();
+ if ( newArea > curArea ) {
+ sz = size;
+ }
+ }
+ }
+ }
+
+ assertTrue("No size under bound found: " + Arrays.toString(sizes) + " bound " + bound,
+ sz != null);
+
+ return sz;
+ }
+
+ private static Size getMaxPreviewSize(Context context, String cameraId) {
+ try {
+ WindowManager windowManager =
+ (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
+ Display display = windowManager.getDefaultDisplay();
+
+ int width = display.getWidth();
+ int height = display.getHeight();
+
+ if (height > width) {
+ height = width;
+ width = display.getHeight();
+ }
+
+ CameraManager camMgr =
+ (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
+ List<Size> orderedPreviewSizes = CameraTestUtils.getSupportedPreviewSizes(
+ cameraId, camMgr, PREVIEW_SIZE_BOUND);
+
+ if (orderedPreviewSizes != null) {
+ for (Size size : orderedPreviewSizes) {
+ if (width >= size.getWidth() &&
+ height >= size.getHeight())
+ return size;
+ }
+ }
+ } catch (Exception e) {
+ Log.e(TAG, "getMaxPreviewSize Failed. "+e.toString());
+ }
+ return PREVIEW_SIZE_BOUND;
+ }
}
diff --git a/tests/camera/src/android/hardware/camera2/cts/StaticMetadataTest.java b/tests/camera/src/android/hardware/camera2/cts/StaticMetadataTest.java
index 1ffa501..a6c477c 100644
--- a/tests/camera/src/android/hardware/camera2/cts/StaticMetadataTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/StaticMetadataTest.java
@@ -310,6 +310,7 @@
requestKeys.add(CaptureRequest.CONTROL_MODE);
requestKeys.add(CaptureRequest.CONTROL_SCENE_MODE);
requestKeys.add(CaptureRequest.CONTROL_VIDEO_STABILIZATION_MODE);
+ requestKeys.add(CaptureRequest.CONTROL_ZOOM_RATIO);
requestKeys.add(CaptureRequest.FLASH_MODE);
requestKeys.add(CaptureRequest.JPEG_GPS_LOCATION);
requestKeys.add(CaptureRequest.JPEG_ORIENTATION);
diff --git a/tests/camera/src/android/hardware/camera2/cts/StillCaptureTest.java b/tests/camera/src/android/hardware/camera2/cts/StillCaptureTest.java
index 25fde0e..991649e 100644
--- a/tests/camera/src/android/hardware/camera2/cts/StillCaptureTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/StillCaptureTest.java
@@ -1033,6 +1033,9 @@
// stopPreview must be called here to make sure next time a preview stream
// is created with new size.
stopPreview();
+ // Drain the results after each combination. Depending on the device the results
+ // can be relatively big and could accumulate fairly quickly after many iterations.
+ resultListener.drain();
}
}
diff --git a/tests/camera/src/android/hardware/camera2/cts/testcases/Camera2AndroidBasicTestCase.java b/tests/camera/src/android/hardware/camera2/cts/testcases/Camera2AndroidTestRule.java
similarity index 78%
rename from tests/camera/src/android/hardware/camera2/cts/testcases/Camera2AndroidBasicTestCase.java
rename to tests/camera/src/android/hardware/camera2/cts/testcases/Camera2AndroidTestRule.java
index c240065..91f6b80 100644
--- a/tests/camera/src/android/hardware/camera2/cts/testcases/Camera2AndroidBasicTestCase.java
+++ b/tests/camera/src/android/hardware/camera2/cts/testcases/Camera2AndroidTestRule.java
@@ -20,7 +20,6 @@
import static com.android.ex.camera2.blocking.BlockingStateCallback.*;
import android.content.Context;
-import android.graphics.ImageFormat;
import android.graphics.Rect;
import android.hardware.camera2.cts.CameraTestUtils;
@@ -41,7 +40,6 @@
import android.media.ImageReader;
import android.os.Handler;
import android.os.HandlerThread;
-import android.test.AndroidTestCase;
import android.util.Log;
import android.view.Surface;
import android.view.WindowManager;
@@ -49,6 +47,8 @@
import com.android.ex.camera2.blocking.BlockingSessionCallback;
import com.android.ex.camera2.blocking.BlockingStateCallback;
+import org.junit.rules.ExternalResource;
+
import java.io.File;
import java.nio.ByteBuffer;
import java.util.ArrayList;
@@ -56,7 +56,7 @@
import java.util.HashMap;
import java.util.List;
-public class Camera2AndroidBasicTestCase extends AndroidTestCase {
+public class Camera2AndroidTestRule extends ExternalResource {
private static final String TAG = "Camera2AndroidBasicTestCase";
private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
@@ -64,34 +64,115 @@
protected static final Size DEFAULT_CAPTURE_SIZE = new Size(640, 480);
protected static final int CAPTURE_WAIT_TIMEOUT_MS = 5000;
- protected CameraManager mCameraManager;
- protected CameraDevice mCamera;
- protected CameraCaptureSession mCameraSession;
- protected BlockingSessionCallback mCameraSessionListener;
- protected BlockingStateCallback mCameraListener;
- protected String[] mCameraIdsUnderTest;
+ private CameraManager mCameraManager;
+ private CameraDevice mCamera;
+ private CameraCaptureSession mCameraSession;
+ private BlockingSessionCallback mCameraSessionListener;
+ private BlockingStateCallback mCameraListener;
+ private String[] mCameraIdsUnderTest;
// include both standalone camera IDs and "hidden" physical camera IDs
- protected String[] mAllCameraIds;
- protected HashMap<String, StaticMetadata> mAllStaticInfo;
- protected ImageReader mReader;
- protected Surface mReaderSurface;
- protected Handler mHandler;
- protected HandlerThread mHandlerThread;
- protected StaticMetadata mStaticInfo;
- protected CameraErrorCollector mCollector;
- protected List<Size> mOrderedPreviewSizes; // In descending order.
- protected List<Size> mOrderedVideoSizes; // In descending order.
- protected List<Size> mOrderedStillSizes; // In descending order.
- protected String mDebugFileNameBase;
+ private String[] mAllCameraIds;
+ private HashMap<String, StaticMetadata> mAllStaticInfo;
+ private ImageReader mReader;
+ private Surface mReaderSurface;
+ private Handler mHandler;
+ private HandlerThread mHandlerThread;
+ private StaticMetadata mStaticInfo;
+ private CameraErrorCollector mCollector;
+ private List<Size> mOrderedPreviewSizes; // In descending order.
+ private List<Size> mOrderedVideoSizes; // In descending order.
+ private List<Size> mOrderedStillSizes; // In descending order.
+ private String mDebugFileNameBase;
- protected WindowManager mWindowManager;
+ private WindowManager mWindowManager;
+ private Context mContext;
- @Override
- public void setContext(Context context) {
- super.setContext(context);
- mCameraManager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
- assertNotNull("Can't connect to camera manager!", mCameraManager);
- mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
+ public Camera2AndroidTestRule(Context context) {
+ mContext = context;
+ }
+
+ public Context getContext() {
+ return mContext;
+ }
+
+ public String[] getCameraIdsUnderTest() {
+ return mCameraIdsUnderTest;
+ }
+
+ public StaticMetadata getStaticInfo() {
+ return mStaticInfo;
+ }
+
+ public CameraManager getCameraManager() {
+ return mCameraManager;
+ }
+
+ public void setStaticInfo(StaticMetadata staticInfo) {
+ mStaticInfo = staticInfo;
+ }
+
+ public CameraCaptureSession getCameraSession() {
+ return mCameraSession;
+ }
+
+ public CameraDevice getCamera() {
+ return mCamera;
+ }
+
+ public void setCamera(CameraDevice camera) {
+ mCamera = camera;
+ }
+
+ public void setCameraSession(CameraCaptureSession session) {
+ mCameraSession = session;
+ }
+
+ public BlockingStateCallback getCameraListener() {
+ return mCameraListener;
+ }
+
+ public BlockingSessionCallback getCameraSessionListener() {
+ return mCameraSessionListener;
+ }
+
+ public Handler getHandler() {
+ return mHandler;
+ }
+
+ public void setCameraSessionListener(BlockingSessionCallback listener) {
+ mCameraSessionListener = listener;
+ }
+
+ public ImageReader getReader() {
+ return mReader;
+ }
+
+ public HashMap<String, StaticMetadata> getAllStaticInfo() {
+ return mAllStaticInfo;
+ }
+
+ public List<Size> getOrderedPreviewSizes() {
+ return mOrderedPreviewSizes;
+ }
+
+ public List<Size> getOrderedStillSizes() {
+ return mOrderedStillSizes;
+ }
+
+ public Surface getReaderSurface() {
+ return mReaderSurface;
+ }
+
+ public void setOrderedPreviewSizes(List<Size> sizes) {
+ mOrderedPreviewSizes = sizes;
+ }
+
+ public WindowManager getWindowManager() {
+ return mWindowManager;
+ }
+
+ public CameraErrorCollector getCollector() {
+ return mCollector;
}
/**
@@ -99,9 +180,11 @@
* HandlerThread, Camera IDs, and CameraStateCallback etc.
*/
@Override
- protected void setUp() throws Exception {
- super.setUp();
-
+ public void before() throws Exception {
+ Log.v(TAG, "Set up...");
+ mCameraManager = (CameraManager) mContext.getSystemService(Context.CAMERA_SERVICE);
+ assertNotNull("Can't connect to camera manager!", mCameraManager);
+ mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
/**
* Workaround for mockito and JB-MR2 incompatibility
*
@@ -152,27 +235,26 @@
}
@Override
- protected void tearDown() throws Exception {
- String[] cameraIdsPostTest =
- mCameraManager.getCameraIdListNoLazy();
- assertNotNull("Camera ids shouldn't be null", cameraIdsPostTest);
- Log.i(TAG, "Camera ids in setup:" + Arrays.toString(mCameraIdsUnderTest));
- Log.i(TAG, "Camera ids in tearDown:" + Arrays.toString(cameraIdsPostTest));
- assertTrue(
- "Number of cameras changed from " + mCameraIdsUnderTest.length + " to " +
- cameraIdsPostTest.length,
- mCameraIdsUnderTest.length == cameraIdsPostTest.length);
- mHandlerThread.quitSafely();
- mHandler = null;
- closeDefaultImageReader();
-
- try {
- mCollector.verify();
- } catch (Throwable e) {
- // When new Exception(e) is used, exception info will be printed twice.
- throw new Exception(e.getMessage());
- } finally {
- super.tearDown();
+ public void after() {
+ Log.v(TAG, "Tear down...");
+ if (mCameraManager != null) {
+ try {
+ String[] cameraIdsPostTest = mCameraManager.getCameraIdListNoLazy();
+ assertNotNull("Camera ids shouldn't be null", cameraIdsPostTest);
+ Log.i(TAG, "Camera ids in setup:" + Arrays.toString(mCameraIdsUnderTest));
+ Log.i(TAG, "Camera ids in tearDown:" + Arrays.toString(cameraIdsPostTest));
+ assertTrue(
+ "Number of cameras changed from " + mCameraIdsUnderTest.length + " to " +
+ cameraIdsPostTest.length,
+ mCameraIdsUnderTest.length == cameraIdsPostTest.length);
+ mHandlerThread.quitSafely();
+ mHandler = null;
+ closeDefaultImageReader();
+ mCollector.verify();
+ } catch (Throwable e) {
+ // When new Exception(e) is used, exception info will be printed twice.
+ throw new RuntimeException(e.getMessage());
+ }
}
}
@@ -184,7 +266,7 @@
* @param listener The {@link #CaptureCallback} camera device used to notify callbacks.
* @param handler The handler camera device used to post callbacks.
*/
- protected void startCapture(CaptureRequest request, boolean repeating,
+ public void startCapture(CaptureRequest request, boolean repeating,
CaptureCallback listener, Handler handler) throws Exception {
if (VERBOSE) Log.v(TAG, "Starting capture from device");
@@ -201,7 +283,7 @@
* @param fast When it is true, {@link CameraDevice#flush} is called, the stop capture
* could be faster.
*/
- protected void stopCapture(boolean fast) throws Exception {
+ public void stopCapture(boolean fast) throws Exception {
if (VERBOSE) Log.v(TAG, "Stopping capture");
if (fast) {
@@ -225,7 +307,7 @@
*
* @param cameraId The id of the camera device to be opened.
*/
- protected void openDevice(String cameraId) throws Exception {
+ public void openDevice(String cameraId) throws Exception {
openDevice(cameraId, mCameraListener);
}
@@ -235,7 +317,7 @@
* @param cameraId The id of the camera device to be opened.
* @param listener The {@link #BlockingStateCallback} used to wait for states.
*/
- protected void openDevice(String cameraId, BlockingStateCallback listener) throws Exception {
+ public void openDevice(String cameraId, BlockingStateCallback listener) throws Exception {
mCamera = CameraTestUtils.openCamera(
mCameraManager, cameraId, listener, mHandler);
mCollector.setCameraId(cameraId);
@@ -258,7 +340,7 @@
*
* @param outputSurfaces The set of output surfaces to configure for this session
*/
- protected void createSession(List<Surface> outputSurfaces) throws Exception {
+ public void createSession(List<Surface> outputSurfaces) throws Exception {
mCameraSessionListener = new BlockingSessionCallback();
mCameraSession = CameraTestUtils.configureCameraSession(mCamera, outputSurfaces,
mCameraSessionListener, mHandler);
@@ -270,7 +352,7 @@
*
* @param outputSurfaces The set of output surfaces to configure for this session
*/
- protected void createSessionByConfigs(List<OutputConfiguration> outputConfigs) throws Exception {
+ public void createSessionByConfigs(List<OutputConfiguration> outputConfigs) throws Exception {
mCameraSessionListener = new BlockingSessionCallback();
mCameraSession = CameraTestUtils.configureCameraSessionWithConfig(mCamera, outputConfigs,
mCameraSessionListener, mHandler);
@@ -286,7 +368,7 @@
*
* @param cameraId The id of the {@link #CameraDevice camera device} to be closed.
*/
- protected void closeDevice(String cameraId) {
+ public void closeDevice(String cameraId) {
closeDevice(cameraId, mCameraListener);
}
@@ -301,7 +383,7 @@
* @param cameraId The id of the camera device to be closed.
* @param listener The BlockingStateCallback used to wait for states.
*/
- protected void closeDevice(String cameraId, BlockingStateCallback listener) {
+ public void closeDevice(String cameraId, BlockingStateCallback listener) {
if (mCamera != null) {
if (!cameraId.equals(mCamera.getId())) {
throw new IllegalStateException("Try to close a device that is not opened yet");
@@ -337,7 +419,7 @@
* @param listener The listener used by this ImageReader to notify
* callbacks.
*/
- protected void createDefaultImageReader(Size size, int format, int maxNumImages,
+ public void createDefaultImageReader(Size size, int format, int maxNumImages,
ImageReader.OnImageAvailableListener listener) throws Exception {
closeDefaultImageReader();
@@ -362,7 +444,7 @@
* @param listener The listener used by this ImageReader to notify
* callbacks.
*/
- protected void createDefaultImageReader(Size size, int format, int maxNumImages, long usage,
+ public void createDefaultImageReader(Size size, int format, int maxNumImages, long usage,
ImageReader.OnImageAvailableListener listener) throws Exception {
closeDefaultImageReader();
@@ -382,7 +464,7 @@
* @param listener The listener used by this ImageReader to notify callbacks.
*/
- protected ImageReader createImageReader(Size size, int format, int maxNumImages,
+ public ImageReader createImageReader(Size size, int format, int maxNumImages,
ImageReader.OnImageAvailableListener listener) throws Exception {
ImageReader reader = null;
@@ -406,7 +488,7 @@
* @param listener The listener used by this ImageReader to notify callbacks.
*/
- protected ImageReader createImageReader(Size size, int format, int maxNumImages, long usage,
+ public ImageReader createImageReader(Size size, int format, int maxNumImages, long usage,
ImageReader.OnImageAvailableListener listener) throws Exception {
ImageReader reader = null;
reader = ImageReader.newInstance(size.getWidth(), size.getHeight(),
@@ -420,7 +502,7 @@
/**
* Close the pending images then close current default {@link ImageReader} object.
*/
- protected void closeDefaultImageReader() {
+ public void closeDefaultImageReader() {
closeImageReader(mReader);
mReader = null;
mReaderSurface = null;
@@ -431,7 +513,7 @@
*
* @param reader
*/
- protected void closeImageReader(ImageReader reader) {
+ public void closeImageReader(ImageReader reader) {
if (reader != null) {
try {
// Close all possible pending images first.
@@ -446,7 +528,7 @@
}
}
- protected void checkImageReaderSessionConfiguration(String msg) throws Exception {
+ public void checkImageReaderSessionConfiguration(String msg) throws Exception {
List<OutputConfiguration> outputConfigs = new ArrayList<OutputConfiguration>();
outputConfigs.add(new OutputConfiguration(mReaderSurface));
@@ -454,11 +536,11 @@
SessionConfiguration.SESSION_REGULAR, /*expectedResult*/ true, msg);
}
- protected CaptureRequest prepareCaptureRequest() throws Exception {
+ public CaptureRequest prepareCaptureRequest() throws Exception {
return prepareCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
}
- protected CaptureRequest prepareCaptureRequest(int template) throws Exception {
+ public CaptureRequest prepareCaptureRequest(int template) throws Exception {
List<Surface> outputSurfaces = new ArrayList<Surface>();
Surface surface = mReader.getSurface();
assertNotNull("Fail to get surface from ImageReader", surface);
@@ -467,7 +549,7 @@
.build();
}
- protected CaptureRequest.Builder prepareCaptureRequestForSurfaces(List<Surface> surfaces,
+ public CaptureRequest.Builder prepareCaptureRequestForSurfaces(List<Surface> surfaces,
int template)
throws Exception {
createSession(surfaces);
@@ -482,7 +564,7 @@
return captureBuilder;
}
- protected CaptureRequest.Builder prepareCaptureRequestForConfigs(
+ public CaptureRequest.Builder prepareCaptureRequestForConfigs(
List<OutputConfiguration> outputConfigs, int template) throws Exception {
createSessionByConfigs(outputConfigs);
@@ -506,7 +588,7 @@
* @param closedBuffer The ByteBuffer from a closed Image. buffer invalid
* access will be skipped if it is null.
*/
- protected void imageInvalidAccessTestAfterClose(Image closedImage,
+ public void imageInvalidAccessTestAfterClose(Image closedImage,
Plane closedPlane, ByteBuffer closedBuffer) {
if (closedImage == null) {
throw new IllegalArgumentException(" closedImage must be non-null");
@@ -628,4 +710,4 @@
// Expected.
}
}
-}
+}
\ No newline at end of file
diff --git a/tests/camera/src/android/hardware/cts/CameraTestCase.java b/tests/camera/src/android/hardware/cts/CameraPerformanceTestHelper.java
similarity index 72%
rename from tests/camera/src/android/hardware/cts/CameraTestCase.java
rename to tests/camera/src/android/hardware/cts/CameraPerformanceTestHelper.java
index 1b4193b..379fad5 100644
--- a/tests/camera/src/android/hardware/cts/CameraTestCase.java
+++ b/tests/camera/src/android/hardware/cts/CameraPerformanceTestHelper.java
@@ -16,6 +16,10 @@
package android.hardware.cts;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
import android.hardware.Camera;
import android.hardware.Camera.AutoFocusCallback;
import android.hardware.Camera.ErrorCallback;
@@ -28,26 +32,24 @@
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
-import junit.framework.TestCase;
-
-public class CameraTestCase extends TestCase {
+public class CameraPerformanceTestHelper {
private static final String TAG = "CameraTestCase";
private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
- protected static final int NO_ERROR = -1;
- protected static final long WAIT_FOR_COMMAND_TO_COMPLETE_NS = 5000000000L;
- protected static final long WAIT_FOR_FOCUS_TO_COMPLETE_NS = 5000000000L;
- protected static final long WAIT_FOR_SNAPSHOT_TO_COMPLETE_NS = 5000000000L;
- protected Looper mLooper = null;
+ public static final int NO_ERROR = -1;
+ public static final long WAIT_FOR_COMMAND_TO_COMPLETE_NS = 5000000000L;
+ public static final long WAIT_FOR_FOCUS_TO_COMPLETE_NS = 5000000000L;
+ public static final long WAIT_FOR_SNAPSHOT_TO_COMPLETE_NS = 5000000000L;
- protected int mCameraErrorCode;
- protected Camera mCamera;
+ private Looper mLooper = null;
+ private int mCameraErrorCode;
+ private Camera mCamera;
/**
* Initializes the message looper so that the Camera object can
* receive the callback messages.
*/
- protected void initializeMessageLooper(final int cameraId) throws InterruptedException {
+ public void initializeMessageLooper(final int cameraId) throws InterruptedException {
Lock startLock = new ReentrantLock();
Condition startDone = startLock.newCondition();
mCameraErrorCode = NO_ERROR;
@@ -80,9 +82,9 @@
startLock.lock();
try {
- if (startDone.awaitNanos(WAIT_FOR_COMMAND_TO_COMPLETE_NS) <= 0L) {
- fail("initializeMessageLooper: start timeout");
- }
+ assertTrue(
+ "initializeMessageLooper: start timeout",
+ startDone.awaitNanos(WAIT_FOR_COMMAND_TO_COMPLETE_NS) > 0L);
} finally {
startLock.unlock();
}
@@ -93,7 +95,7 @@
/**
* Terminates the message looper thread, optionally allowing evict error
*/
- protected void terminateMessageLooper() throws Exception {
+ public void terminateMessageLooper() throws Exception {
mLooper.quit();
// Looper.quit() is asynchronous. The looper may still has some
// preview callbacks in the queue after quit is called. The preview
@@ -110,7 +112,7 @@
* Start preview and wait for the first preview callback, which indicates the
* preview becomes active.
*/
- protected void startPreview() throws InterruptedException {
+ public void startPreview() throws InterruptedException {
Lock previewLock = new ReentrantLock();
Condition previewDone = previewLock.newCondition();
@@ -126,9 +128,9 @@
previewLock.lock();
try {
- if (previewDone.awaitNanos(WAIT_FOR_COMMAND_TO_COMPLETE_NS) <= 0L) {
- fail("Preview done timeout");
- }
+ assertTrue(
+ "Preview done timeout",
+ previewDone.awaitNanos(WAIT_FOR_COMMAND_TO_COMPLETE_NS) > 0L);
} finally {
previewLock.unlock();
}
@@ -139,7 +141,7 @@
/**
* Trigger and wait for autofocus to complete.
*/
- protected void autoFocus() throws InterruptedException {
+ public void autoFocus() throws InterruptedException {
Lock focusLock = new ReentrantLock();
Condition focusDone = focusLock.newCondition();
@@ -154,9 +156,9 @@
focusLock.lock();
try {
- if (focusDone.awaitNanos(WAIT_FOR_FOCUS_TO_COMPLETE_NS) <= 0L) {
- fail("Autofocus timeout");
- }
+ assertTrue(
+ "Autofocus timeout",
+ focusDone.awaitNanos(WAIT_FOR_FOCUS_TO_COMPLETE_NS) > 0L);
} finally {
focusLock.unlock();
}
@@ -165,34 +167,35 @@
/**
* Trigger and wait for snapshot to finish.
*/
- protected void takePicture() throws InterruptedException {
+ public void takePicture() throws InterruptedException {
Lock snapshotLock = new ReentrantLock();
Condition snapshotDone = snapshotLock.newCondition();
mCamera.takePicture(/*shutterCallback*/ null, /*rawPictureCallback*/ null,
new PictureCallback() {
- @Override
- public void onPictureTaken(byte[] rawData, Camera camera) {
- snapshotLock.lock();
- try {
- if (rawData == null) {
- fail("Empty jpeg data");
+ @Override
+ public void onPictureTaken(byte[] rawData, Camera camera) {
+ snapshotLock.lock();
+ try {
+ assertNotNull("Empty jpeg data", rawData);
+ snapshotDone.signal();
+ } finally {
+ snapshotLock.unlock();
+ }
}
- snapshotDone.signal();
- } finally {
- snapshotLock.unlock();
- }
- }
- });
+ });
snapshotLock.lock();
try {
- if (snapshotDone.awaitNanos(WAIT_FOR_SNAPSHOT_TO_COMPLETE_NS) <= 0L) {
- fail("TakePicture timeout");
- }
+ assertTrue(
+ "TakePicture timeout",
+ snapshotDone.awaitNanos(WAIT_FOR_SNAPSHOT_TO_COMPLETE_NS) > 0L);
} finally {
snapshotLock.unlock();
}
}
-}
+ public Camera getCamera() {
+ return mCamera;
+ }
+}
\ No newline at end of file
diff --git a/tests/camera/src/android/hardware/cts/LegacyCameraPerformanceTest.java b/tests/camera/src/android/hardware/cts/LegacyCameraPerformanceTest.java
index 74ffdff..ac3f6dd 100644
--- a/tests/camera/src/android/hardware/cts/LegacyCameraPerformanceTest.java
+++ b/tests/camera/src/android/hardware/cts/LegacyCameraPerformanceTest.java
@@ -30,33 +30,41 @@
import com.android.compatibility.common.util.ResultUnit;
import com.android.compatibility.common.util.Stat;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
import java.util.Arrays;
/**
* Measure and report legacy camera device performance.
*/
-public class LegacyCameraPerformanceTest extends CameraTestCase {
+@RunWith(JUnit4.class)
+public class LegacyCameraPerformanceTest {
private static final String TAG = "CameraPerformanceTest";
private static final String REPORT_LOG_NAME = "CtsCamera1TestCases";
private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
private Instrumentation mInstrumentation;
+ private CameraPerformanceTestHelper mHelper;
- @Override
- protected void setUp() throws Exception {
- super.setUp();
+ @Before
+ public void setUp() throws Exception {
mInstrumentation = InstrumentationRegistry.getInstrumentation();
+ mHelper = new CameraPerformanceTestHelper();
}
- @Override
- protected void tearDown() throws Exception {
- super.tearDown();
- if (mCamera != null) {
- mCamera.release();
- mCamera = null;
+ @After
+ public void tearDown() throws Exception {
+ if (mHelper.getCamera() != null) {
+ mHelper.getCamera().release();
+
}
}
+ @Test
public void testLegacyApiPerformance() throws Exception {
final int NUM_TEST_LOOPS = 10;
@@ -75,14 +83,14 @@
double[] cameraAutoFocusTimes = new double[NUM_TEST_LOOPS];
boolean afSupported = false;
long openTimeMs, startPreviewTimeMs, stopPreviewTimeMs, closeTimeMs, takePictureTimeMs,
- autofocusTimeMs;
+ autofocusTimeMs;
for (int i = 0; i < NUM_TEST_LOOPS; i++) {
openTimeMs = SystemClock.elapsedRealtime();
- initializeMessageLooper(id);
+ mHelper.initializeMessageLooper(id);
cameraOpenTimes[i] = SystemClock.elapsedRealtime() - openTimeMs;
- Parameters parameters = mCamera.getParameters();
+ Parameters parameters = mHelper.getCamera().getParameters();
if (i == 0) {
for (String focusMode: parameters.getSupportedFocusModes()) {
if (Parameters.FOCUS_MODE_AUTO.equals(focusMode)) {
@@ -94,18 +102,18 @@
if (afSupported) {
parameters.setFocusMode(Parameters.FOCUS_MODE_AUTO);
- mCamera.setParameters(parameters);
+ mHelper.getCamera().setParameters(parameters);
}
SurfaceTexture previewTexture = new SurfaceTexture(/*random int*/ 1);
- mCamera.setPreviewTexture(previewTexture);
+ mHelper.getCamera().setPreviewTexture(previewTexture);
startPreviewTimeMs = SystemClock.elapsedRealtime();
- startPreview();
+ mHelper.startPreview();
startPreviewTimes[i] = SystemClock.elapsedRealtime() - startPreviewTimeMs;
if (afSupported) {
autofocusTimeMs = SystemClock.elapsedRealtime();
- autoFocus();
+ mHelper.autoFocus();
cameraAutoFocusTimes[i] = SystemClock.elapsedRealtime() - autofocusTimeMs;
}
@@ -113,18 +121,18 @@
Thread.sleep(1000);
takePictureTimeMs = SystemClock.elapsedRealtime();
- takePicture();
+ mHelper.takePicture();
cameraTakePictureTimes[i] = SystemClock.elapsedRealtime() - takePictureTimeMs;
//Resume preview after image capture
- startPreview();
+ mHelper.startPreview();
stopPreviewTimeMs = SystemClock.elapsedRealtime();
- mCamera.stopPreview();
+ mHelper.getCamera().stopPreview();
closeTimeMs = SystemClock.elapsedRealtime();
stopPreviewTimes[i] = closeTimeMs - stopPreviewTimeMs;
- terminateMessageLooper();
+ mHelper.terminateMessageLooper();
cameraCloseTimes[i] = SystemClock.elapsedRealtime() - closeTimeMs;
previewTexture.release();
}
@@ -192,4 +200,4 @@
reportLog.submit(mInstrumentation);
}
}
-}
+}
\ No newline at end of file
diff --git a/tests/camera/utils/src/android/hardware/camera2/cts/helpers/StaticMetadata.java b/tests/camera/utils/src/android/hardware/camera2/cts/helpers/StaticMetadata.java
index 33f9346..d9fdcfb 100644
--- a/tests/camera/utils/src/android/hardware/camera2/cts/helpers/StaticMetadata.java
+++ b/tests/camera/utils/src/android/hardware/camera2/cts/helpers/StaticMetadata.java
@@ -25,7 +25,7 @@
import android.hardware.camera2.CaptureResult;
import android.hardware.camera2.cts.CameraTestUtils;
import android.hardware.camera2.params.StreamConfigurationMap;
-import android.hardware.camera2.params.CapabilityAndMaxSize;
+import android.hardware.camera2.params.Capability;
import android.util.Range;
import android.util.Size;
import android.util.Log;
@@ -1816,6 +1816,26 @@
return maxZoom;
}
+ public Range<Float> getZoomRatioRangeChecked() {
+ Key<Range<Float>> key =
+ CameraCharacteristics.CONTROL_ZOOM_RATIO_RANGE;
+
+ Range<Float> zoomRatioRange = getValueFromKeyNonNull(key);
+ if (zoomRatioRange == null) {
+ return new Range<Float>(1.0f, 1.0f);
+ }
+
+ checkTrueForKey(key, String.format(" min zoom ratio %f should be no more than 1",
+ zoomRatioRange.getLower()), zoomRatioRange.getLower() <= 1.0);
+ checkTrueForKey(key, String.format(" max zoom ratio %f should be no less than 1",
+ zoomRatioRange.getUpper()), zoomRatioRange.getUpper() >= 1.0);
+ final float ZOOM_MIN_RANGE = 0.01f;
+ checkTrueForKey(key, " zoom ratio range should be reasonably large",
+ zoomRatioRange.getUpper().equals(zoomRatioRange.getLower()) ||
+ zoomRatioRange.getUpper() - zoomRatioRange.getLower() > ZOOM_MIN_RANGE);
+ return zoomRatioRange;
+ }
+
public int[] getAvailableSceneModesChecked() {
Key<int[]> key =
CameraCharacteristics.CONTROL_AVAILABLE_SCENE_MODES;
@@ -1853,21 +1873,21 @@
return modes;
}
- public CapabilityAndMaxSize[] getAvailableBokehCapsChecked() {
+ public Capability[] getAvailableBokehCapsChecked() {
final Size FULL_HD = new Size(1920, 1080);
Rect activeRect = getValueFromKeyNonNull(
CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE);
- Key<CapabilityAndMaxSize[]> key =
+ Key<Capability[]> key =
CameraCharacteristics.CONTROL_AVAILABLE_BOKEH_CAPABILITIES;
- CapabilityAndMaxSize[] caps = mCharacteristics.get(key);
+ Capability[] caps = mCharacteristics.get(key);
if (caps == null) {
- return new CapabilityAndMaxSize[0];
+ return new Capability[0];
}
Size[] yuvSizes = getAvailableSizesForFormatChecked(ImageFormat.YUV_420_888,
StaticMetadata.StreamDirection.Output);
List<Size> yuvSizesList = Arrays.asList(yuvSizes);
- for (CapabilityAndMaxSize cap : caps) {
+ for (Capability cap : caps) {
int bokehMode = cap.getMode();
Size maxStreamingSize = cap.getMaxStreamingSize();
boolean maxStreamingSizeIsZero =
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/ActivityMetricsLoggerTests.java b/tests/framework/base/windowmanager/src/android/server/wm/ActivityMetricsLoggerTests.java
index 85d0474..7e1e303 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/ActivityMetricsLoggerTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/ActivityMetricsLoggerTests.java
@@ -49,6 +49,7 @@
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
import static org.hamcrest.Matchers.lessThanOrEqualTo;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.fail;
@@ -76,6 +77,7 @@
import java.util.List;
import java.util.Queue;
import java.util.concurrent.TimeUnit;
+import java.util.function.IntConsumer;
/**
* CTS device tests for {@link com.android.server.wm.ActivityMetricsLogger}.
@@ -85,6 +87,7 @@
@Presubmit
public class ActivityMetricsLoggerTests extends ActivityManagerTestBase {
private static final String TAG_ATM = "ActivityTaskManager";
+ private static final int EVENT_WM_ACTIVITY_LAUNCH_TIME = 30009;
private final MetricsReader mMetricsReader = new MetricsReader();
private long mPreUptimeMs;
private LogSeparator mLogSeparator;
@@ -112,7 +115,7 @@
final LogMaker metricsLog = getMetricsLog(TEST_ACTIVITY, APP_TRANSITION);
final String[] deviceLogs = getDeviceLogsForComponents(mLogSeparator, TAG_ATM);
final List<Event> eventLogs = getEventLogsForComponents(mLogSeparator,
- 30009 /* AM_ACTIVITY_LAUNCH_TIME */);
+ EVENT_WM_ACTIVITY_LAUNCH_TIME);
final long postUptimeMs = SystemClock.uptimeMillis();
assertMetricsLogs(TEST_ACTIVITY, APP_TRANSITION, metricsLog, mPreUptimeMs, postUptimeMs);
@@ -158,18 +161,24 @@
private void assertEventLogsContainsLaunchTime(List<Event> events, ComponentName componentName,
int windowsDrawnDelayMs) {
- for (Event event : events) {
- Object[] arr = (Object[]) event.getData();
+ verifyLaunchTimeEventLogs(events, componentName,
+ delay -> assertEquals("Unexpected windows drawn delay for " + componentName,
+ delay, windowsDrawnDelayMs));
+ }
+
+ private void verifyLaunchTimeEventLogs(List<Event> launchTimeEvents,
+ ComponentName componentName, IntConsumer launchTimeVerifier) {
+ for (Event event : launchTimeEvents) {
+ final Object[] arr = (Object[]) event.getData();
assertEquals(4, arr.length);
final String name = (String) arr[2];
- final int delay = (int) arr[3];
+ final int launchTime = (int) arr[3];
if (name.equals(componentName.flattenToShortString())) {
- assertEquals("Unexpected windows drawn delay for " + componentName,
- delay, windowsDrawnDelayMs);
+ launchTimeVerifier.accept(launchTime);
return;
}
}
- fail("Could not find am_activity_launch_time for " + componentName);
+ fail("Could not find wm_activity_launch_time for " + componentName);
}
/**
@@ -403,6 +412,18 @@
postUptimeMs);
}
+ @Test
+ public void testLaunchTimeEventLogNonProcessSwitch() {
+ launchAndWaitForActivity(SINGLE_TASK_ACTIVITY);
+ mLogSeparator = separateLogs();
+
+ // Launch another activity in the same process.
+ launchAndWaitForActivity(TEST_ACTIVITY);
+ final List<Event> eventLogs = getEventLogsForComponents(mLogSeparator,
+ EVENT_WM_ACTIVITY_LAUNCH_TIME);
+ verifyLaunchTimeEventLogs(eventLogs, TEST_ACTIVITY, time -> assertNotEquals(0, time));
+ }
+
private void launchAndWaitForActivity(ComponentName activity) {
getLaunchActivityBuilder()
.setUseInstrumentation()
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/DisplayTests.java b/tests/framework/base/windowmanager/src/android/server/wm/DisplayTests.java
index 01b48b5..6067a13 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/DisplayTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/DisplayTests.java
@@ -29,7 +29,7 @@
import android.content.res.Configuration;
import android.hardware.display.DisplayManager;
import android.platform.test.annotations.Presubmit;
-import android.server.wm.ActivityManagerState.ActivityDisplay;
+import android.server.wm.ActivityManagerState.DisplayContent;
import android.util.Size;
import android.view.Display;
@@ -50,8 +50,8 @@
*/
@Test
public void testDefaultDisplayOverrideConfiguration() throws Exception {
- final List<ActivityDisplay> reportedDisplays = getDisplaysStates();
- final ActivityDisplay primaryDisplay = getDisplayState(reportedDisplays, DEFAULT_DISPLAY);
+ final List<DisplayContent> reportedDisplays = getDisplaysStates();
+ final DisplayContent primaryDisplay = getDisplayState(reportedDisplays, DEFAULT_DISPLAY);
assertEquals("Primary display's configuration should be equal to global configuration.",
primaryDisplay.mOverrideConfiguration, primaryDisplay.mFullConfiguration);
assertEquals("Primary display's configuration should be equal to global configuration.",
@@ -63,7 +63,7 @@
*/
@Test
public void testCreateVirtualDisplayWithCustomConfig() throws Exception {
- final ActivityDisplay newDisplay = createManagedVirtualDisplaySession().createDisplay();
+ final DisplayContent newDisplay = createManagedVirtualDisplaySession().createDisplay();
// Find the density of created display.
final int newDensityDpi = newDisplay.mFullConfiguration.densityDpi;
@@ -99,7 +99,7 @@
assumeFalse(supportsMultiDisplay());
// Create new virtual display.
- final ActivityDisplay newDisplay = createManagedVirtualDisplaySession().createDisplay();
+ final DisplayContent newDisplay = createManagedVirtualDisplaySession().createDisplay();
// Launch activity on new secondary display.
launchActivityOnDisplay(TEST_ACTIVITY, newDisplay.mId);
@@ -121,7 +121,7 @@
@Test
public void testCreateMultipleVirtualDisplays() throws Exception {
- final List<ActivityDisplay> originalDs = getDisplaysStates();
+ final List<DisplayContent> originalDs = getDisplaysStates();
try (final VirtualDisplaySession virtualDisplaySession = new VirtualDisplaySession()) {
// Create new virtual displays
virtualDisplaySession.createDisplays(3);
@@ -179,11 +179,11 @@
(DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
try (final VirtualDisplaySession virtualDisplaySession = new VirtualDisplaySession()) {
- final ActivityDisplay activityDisplay = virtualDisplaySession
+ final DisplayContent displayContent = virtualDisplaySession
.setSimulateDisplay(true)
.setSimulationDisplaySize(displayWidth, displayHeight)
.createDisplay();
- final Display display = displayManager.getDisplay(activityDisplay.mId);
+ final Display display = displayManager.getDisplay(displayContent.mId);
Configuration config = context.createDisplayContext(display)
.getResources().getConfiguration();
return config;
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/KeyguardTests.java b/tests/framework/base/windowmanager/src/android/server/wm/KeyguardTests.java
index 0004b78..32e5ff8 100755
--- a/tests/framework/base/windowmanager/src/android/server/wm/KeyguardTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/KeyguardTests.java
@@ -353,7 +353,7 @@
final int displayId = mAmWmState.getAmState()
.getDisplayByActivity(SHOW_WHEN_LOCKED_ATTR_ROTATION_ACTIVITY);
- ActivityManagerState.ActivityDisplay display = mAmWmState.getAmState()
+ ActivityManagerState.DisplayContent display = mAmWmState.getAmState()
.getDisplay(displayId);
final int origDisplayOrientation = display.mFullConfiguration.orientation;
final int orientation = origDisplayOrientation == Configuration.ORIENTATION_LANDSCAPE
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayActivityLaunchTests.java b/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayActivityLaunchTests.java
index 5f144d7..ef3f2fb 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayActivityLaunchTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayActivityLaunchTests.java
@@ -64,7 +64,7 @@
import android.hardware.display.DisplayManager;
import android.os.Bundle;
import android.platform.test.annotations.Presubmit;
-import android.server.wm.ActivityManagerState.ActivityDisplay;
+import android.server.wm.ActivityManagerState.DisplayContent;
import android.server.wm.ActivityManagerState.ActivityStack;
import android.server.wm.CommandSession.ActivitySession;
import android.server.wm.CommandSession.SizeInfo;
@@ -117,7 +117,7 @@
private void validateActivityLaunchOnNewDisplay(int activityType) {
// Create new virtual display.
- final ActivityDisplay newDisplay = createManagedVirtualDisplaySession()
+ final DisplayContent newDisplay = createManagedVirtualDisplaySession()
.setSimulateDisplay(true).createDisplay();
// Launch activity on new secondary display.
@@ -167,7 +167,7 @@
.setTargetActivity(TEST_ACTIVITY).setNewTask(true)
.setDisplayId(DEFAULT_DISPLAY).execute();
- final ActivityDisplay newDisplay = createManagedVirtualDisplaySession()
+ final DisplayContent newDisplay = createManagedVirtualDisplaySession()
.setSimulateDisplay(true)
.createDisplay();
final int newDisplayId = newDisplay.mId;
@@ -211,7 +211,7 @@
assertEquals("Unexpected resumed activity",
0, mAmWmState.getAmState().getResumedActivitiesCount());
- final ActivityDisplay newDisplay = externalDisplaySession
+ final DisplayContent newDisplay = externalDisplaySession
.setCanShowWithInsecureKeyguard(true).createVirtualDisplay();
launchActivityOnDisplay(TEST_ACTIVITY, newDisplay.mId);
@@ -230,7 +230,7 @@
@Test
public void testLaunchNonResizeableActivityOnSecondaryDisplay() {
// Create new virtual display.
- final ActivityDisplay newDisplay = createManagedVirtualDisplaySession()
+ final DisplayContent newDisplay = createManagedVirtualDisplaySession()
.setSimulateDisplay(true).createDisplay();
// Launch activity on new secondary display.
@@ -261,7 +261,7 @@
final VirtualDisplayLauncher virtualLauncher =
mObjectTracker.manage(new VirtualDisplayLauncher());
// Create new virtual display.
- final ActivityDisplay newDisplay = virtualLauncher
+ final DisplayContent newDisplay = virtualLauncher
.setSimulateDisplay(true).createDisplay();
// Launch a non-resizeable activity on a primary display.
final ActivitySession nonResizeableSession = virtualLauncher.launchActivity(
@@ -297,7 +297,7 @@
@Test
public void testLaunchNonResizeableActivityFromSecondaryDisplaySameTask() {
// Create new simulated display.
- final ActivityDisplay newDisplay = createManagedVirtualDisplaySession()
+ final DisplayContent newDisplay = createManagedVirtualDisplaySession()
.setSimulateDisplay(true)
.createDisplay();
@@ -319,7 +319,7 @@
@Test
public void testLaunchNonResizeableActivityFromSecondaryDisplayNewTask() {
// Create new virtual display.
- final ActivityDisplay newDisplay = createManagedVirtualDisplaySession()
+ final DisplayContent newDisplay = createManagedVirtualDisplaySession()
.setSimulateDisplay(true).createDisplay();
// Launch activity on new secondary display.
@@ -356,7 +356,7 @@
@Test
public void testConsequentLaunchActivity() {
// Create new virtual display.
- final ActivityDisplay newDisplay = createManagedVirtualDisplaySession()
+ final DisplayContent newDisplay = createManagedVirtualDisplaySession()
.setSimulateDisplay(true).createDisplay();
// Launch activity on new secondary display.
@@ -382,7 +382,7 @@
@Test
public void testConsequentLaunchActivityFromSecondaryDisplay() {
// Create new simulated display.
- final ActivityDisplay newDisplay = createManagedVirtualDisplaySession()
+ final DisplayContent newDisplay = createManagedVirtualDisplaySession()
.setSimulateDisplay(true)
.createDisplay();
@@ -407,7 +407,7 @@
@Test
public void testConsequentLaunchActivityFromVirtualDisplay() {
// Create new virtual display.
- final ActivityDisplay newDisplay = createManagedVirtualDisplaySession()
+ final DisplayContent newDisplay = createManagedVirtualDisplaySession()
.setSimulateDisplay(true).createDisplay();
// Launch activity on new secondary display.
@@ -432,7 +432,7 @@
@Test
public void testConsequentLaunchActivityFromVirtualDisplayToTargetDisplay() {
// Create new virtual display.
- final ActivityDisplay newDisplay = createManagedVirtualDisplaySession()
+ final DisplayContent newDisplay = createManagedVirtualDisplaySession()
.setSimulateDisplay(true).createDisplay();
// Launch activity on new secondary display.
@@ -473,7 +473,7 @@
launchActivity(LAUNCHING_ACTIVITY);
// Create new simulated display.
- final ActivityDisplay newDisplay = createManagedVirtualDisplaySession()
+ final DisplayContent newDisplay = createManagedVirtualDisplaySession()
.setSimulateDisplay(true)
.createDisplay();
@@ -493,7 +493,7 @@
public void testLaunchPendingActivityOnSecondaryDisplay() {
pressHomeButton();
// Create new simulated display.
- final ActivityDisplay newDisplay = createManagedVirtualDisplaySession()
+ final DisplayContent newDisplay = createManagedVirtualDisplaySession()
.setSimulateDisplay(true)
.createDisplay();
final Bundle bundle = ActivityOptions.makeBasic().
@@ -537,7 +537,7 @@
launchActivity(LAUNCHING_ACTIVITY);
// Create new virtual display.
- final ActivityDisplay newDisplay = createManagedVirtualDisplaySession().createDisplay();
+ final DisplayContent newDisplay = createManagedVirtualDisplaySession().createDisplay();
mAmWmState.assertVisibility(VIRTUAL_DISPLAY_ACTIVITY, true /* visible */);
// Launch something to that display so that a new stack is created. We need this to be
// able to compare task numbers in stacks later.
@@ -586,7 +586,7 @@
launchActivity(RESIZEABLE_ACTIVITY);
// Create new virtual display.
- final ActivityDisplay newDisplay = createManagedVirtualDisplaySession().createDisplay();
+ final DisplayContent newDisplay = createManagedVirtualDisplaySession().createDisplay();
mAmWmState.assertVisibility(VIRTUAL_DISPLAY_ACTIVITY, true /* visible */);
final int stackNum = mAmWmState.getAmState().getDisplay(DEFAULT_DISPLAY).mStacks.size();
@@ -617,7 +617,7 @@
*/
@Test
public void testTaskMatchAcrossDisplays() {
- final ActivityDisplay newDisplay = createManagedVirtualDisplaySession()
+ final DisplayContent newDisplay = createManagedVirtualDisplaySession()
.setSimulateDisplay(true).createDisplay();
launchActivityOnDisplay(LAUNCHING_ACTIVITY, newDisplay.mId);
@@ -676,7 +676,7 @@
.setTargetActivity(BROADCAST_RECEIVER_ACTIVITY).setNewTask(true)
.setDisplayId(DEFAULT_DISPLAY).execute();
- final ActivityDisplay newDisplay = createManagedVirtualDisplaySession().createDisplay();
+ final DisplayContent newDisplay = createManagedVirtualDisplaySession().createDisplay();
getLaunchActivityBuilder().setUseInstrumentation().setWithShellPermission(true)
.setTargetActivity(TEST_ACTIVITY).setNewTask(true)
.setDisplayId(newDisplay.mId).execute();
@@ -694,7 +694,7 @@
*/
@Test
public void testLaunchDisplayAffinityMatch() {
- final ActivityDisplay newDisplay = createManagedVirtualDisplaySession()
+ final DisplayContent newDisplay = createManagedVirtualDisplaySession()
.setSimulateDisplay(true).createDisplay();
launchActivityOnDisplay(LAUNCHING_ACTIVITY, newDisplay.mId);
@@ -733,7 +733,7 @@
*/
@Test
public void testNewTaskSameDisplay() {
- final ActivityDisplay newDisplay = createManagedVirtualDisplaySession()
+ final DisplayContent newDisplay = createManagedVirtualDisplaySession()
.setSimulateDisplay(true)
.createDisplay();
@@ -769,7 +769,7 @@
@Test
public void testImmediateLaunchOnNewDisplay() {
// Create new virtual display and immediately launch an activity on it.
- final ActivityDisplay newDisplay = createManagedVirtualDisplaySession()
+ final DisplayContent newDisplay = createManagedVirtualDisplaySession()
.setLaunchActivity(TEST_ACTIVITY)
.createDisplay();
@@ -785,7 +785,7 @@
/** Tests launching of activities on a single task instance display. */
@Test
public void testSingleTaskInstanceDisplay() {
- ActivityDisplay display = createManagedVirtualDisplaySession()
+ DisplayContent display = createManagedVirtualDisplaySession()
.setSimulateDisplay(true)
.createDisplay();
final int displayId = display.mId;
@@ -822,7 +822,7 @@
public void testLaunchPendingIntentActivity() throws Exception {
final DisplayManager displayManager = mContext.getSystemService(DisplayManager.class);
- final ActivityDisplay activityDisplay = createManagedVirtualDisplaySession()
+ final DisplayContent displayContent = createManagedVirtualDisplaySession()
.setSimulateDisplay(true)
.createDisplay();
@@ -834,9 +834,9 @@
final int resultCode = 1;
// Activity should be launched on target display according to the caller context.
final Context displayContext =
- mContext.createDisplayContext(displayManager.getDisplay(activityDisplay.mId));
+ mContext.createDisplayContext(displayManager.getDisplay(displayContent.mId));
getPendingIntentActivity(TOP_ACTIVITY).send(displayContext, resultCode, null /* intent */);
- waitAndAssertTopResumedActivity(TOP_ACTIVITY, activityDisplay.mId,
+ waitAndAssertTopResumedActivity(TOP_ACTIVITY, displayContent.mId,
"Activity launched on secondary display and on top");
// Activity should be brought to front on the same display if it already existed.
@@ -846,11 +846,11 @@
// Activity should be moved to target display.
final ActivityOptions options = ActivityOptions.makeBasic();
- options.setLaunchDisplayId(activityDisplay.mId);
+ options.setLaunchDisplayId(displayContent.mId);
getPendingIntentActivity(TEST_ACTIVITY).send(mContext, resultCode, null /* intent */,
null /* onFinished */, null /* handler */, null /* requiredPermission */,
options.toBundle());
- waitAndAssertTopResumedActivity(TEST_ACTIVITY, activityDisplay.mId,
+ waitAndAssertTopResumedActivity(TEST_ACTIVITY, displayContent.mId,
"Activity launched on secondary display and on top");
}
@@ -873,7 +873,7 @@
// Start TEST_ACTIVITY on top of LAUNCHING_ACTIVITY within the same task
getLaunchActivityBuilder().setTargetActivity(TEST_ACTIVITY).execute();
- final ActivityDisplay newDisplay = createManagedVirtualDisplaySession()
+ final DisplayContent newDisplay = createManagedVirtualDisplaySession()
.setSimulateDisplay(true)
.createDisplay();
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayClientTests.java b/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayClientTests.java
index 4ab381c..7cbdcd4 100755
--- a/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayClientTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayClientTests.java
@@ -40,7 +40,7 @@
import android.hardware.display.DisplayManager;
import android.os.Bundle;
import android.platform.test.annotations.Presubmit;
-import android.server.wm.ActivityManagerState.ActivityDisplay;
+import android.server.wm.ActivityManagerState.DisplayContent;
import android.view.Display;
import android.view.View;
import android.view.WindowManager;
@@ -100,7 +100,7 @@
waitAndAssertResume(activityName);
// Create new simulated display
- final ActivityDisplay newDisplay = createManagedVirtualDisplaySession()
+ final DisplayContent newDisplay = createManagedVirtualDisplaySession()
.setSimulateDisplay(true)
.createDisplay();
@@ -157,7 +157,7 @@
assertImeShownAndMatchesDisplayId(
activityClass, mockImeSession, DEFAULT_DISPLAY);
- final ActivityDisplay newDisplay = virtualDisplaySession
+ final DisplayContent newDisplay = virtualDisplaySession
.setSimulateDisplay(true).setShowSystemDecorations(true).createDisplay();
// Launch activity on the secondary display and make IME show.
@@ -190,7 +190,7 @@
@Test
public void testInputMethodManagerDisplayId() {
// Create a simulated display.
- final ActivityDisplay newDisplay = createManagedVirtualDisplaySession()
+ final DisplayContent newDisplay = createManagedVirtualDisplaySession()
.setSimulateDisplay(true)
.createDisplay();
@@ -215,7 +215,7 @@
private void testViewGetDisplay(boolean isPrimary) {
final TestActivitySession<ClientTestActivity> activitySession =
createManagedTestActivitySession();
- final ActivityDisplay newDisplay = createManagedVirtualDisplaySession()
+ final DisplayContent newDisplay = createManagedVirtualDisplaySession()
.setSimulateDisplay(true)
.createDisplay();
final int displayId = isPrimary ? DEFAULT_DISPLAY : newDisplay.mId;
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayKeyguardTests.java b/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayKeyguardTests.java
index 780712a..56949d8 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayKeyguardTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayKeyguardTests.java
@@ -25,7 +25,7 @@
import static org.junit.Assume.assumeTrue;
import android.platform.test.annotations.Presubmit;
-import android.server.wm.ActivityManagerState.ActivityDisplay;
+import android.server.wm.ActivityManagerState.DisplayContent;
import org.junit.Before;
import org.junit.Test;
@@ -58,7 +58,7 @@
@Test
public void testDismissKeyguardActivity_secondaryDisplay() {
final LockScreenSession lockScreenSession = createManagedLockScreenSession();
- final ActivityDisplay newDisplay = createManagedVirtualDisplaySession().createDisplay();
+ final DisplayContent newDisplay = createManagedVirtualDisplaySession().createDisplay();
lockScreenSession.gotoKeyguard();
mAmWmState.assertKeyguardShowingAndNotOccluded();
@@ -75,7 +75,7 @@
@Test
public void testShowKeyguardDialogOnSecondaryDisplay() {
final LockScreenSession lockScreenSession = createManagedLockScreenSession();
- final ActivityDisplay publicDisplay = createManagedVirtualDisplaySession()
+ final DisplayContent publicDisplay = createManagedVirtualDisplaySession()
.setPublicDisplay(true)
.createDisplay();
@@ -101,9 +101,9 @@
final LockScreenSession lockScreenSession = createManagedLockScreenSession();
final VirtualDisplaySession virtualDisplaySession = createManagedVirtualDisplaySession();
- final ActivityDisplay privateDisplay =
+ final DisplayContent privateDisplay =
virtualDisplaySession.setPublicDisplay(false).createDisplay();
- final ActivityDisplay publicDisplay =
+ final DisplayContent publicDisplay =
virtualDisplaySession.setPublicDisplay(true).createDisplay();
lockScreenSession.gotoKeyguard();
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayLockedKeyguardTests.java b/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayLockedKeyguardTests.java
index 590ff27..2e034c0 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayLockedKeyguardTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayLockedKeyguardTests.java
@@ -27,7 +27,7 @@
import static org.junit.Assume.assumeTrue;
import android.platform.test.annotations.Presubmit;
-import android.server.wm.ActivityManagerState.ActivityDisplay;
+import android.server.wm.ActivityManagerState.DisplayContent;
import androidx.test.filters.FlakyTest;
@@ -62,7 +62,7 @@
lockScreenSession.setLockCredential();
// Create new usual virtual display.
- final ActivityDisplay newDisplay = createManagedVirtualDisplaySession()
+ final DisplayContent newDisplay = createManagedVirtualDisplaySession()
.setPublicDisplay(true)
.createDisplay();
mAmWmState.assertVisibility(VIRTUAL_DISPLAY_ACTIVITY, true /* visible */);
@@ -96,7 +96,7 @@
final LockScreenSession lockScreenSession = createManagedLockScreenSession();
lockScreenSession.setLockCredential();
- final ActivityDisplay newDisplay = createManagedVirtualDisplaySession()
+ final DisplayContent newDisplay = createManagedVirtualDisplaySession()
.setPublicDisplay(false)
.createDisplay();
launchActivityOnDisplay(TEST_ACTIVITY, newDisplay.mId);
@@ -117,7 +117,7 @@
mObjectTracker.manage(new LockScreenSession(FLAG_REMOVE_ACTIVITIES_ON_CLOSE));
lockScreenSession.setLockCredential();
- final ActivityDisplay newDisplay = createManagedVirtualDisplaySession()
+ final DisplayContent newDisplay = createManagedVirtualDisplaySession()
.setPublicDisplay(true)
.createDisplay();
@@ -142,7 +142,7 @@
mObjectTracker.manage(new LockScreenSession(FLAG_REMOVE_ACTIVITIES_ON_CLOSE));
lockScreenSession.setLockCredential();
- final ActivityDisplay newDisplay = createManagedVirtualDisplaySession()
+ final DisplayContent newDisplay = createManagedVirtualDisplaySession()
.setPublicDisplay(true)
.createDisplay();
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayPolicyTests.java b/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayPolicyTests.java
index 0d61322..69d599e 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayPolicyTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayPolicyTests.java
@@ -48,7 +48,7 @@
import static org.junit.Assume.assumeTrue;
import android.platform.test.annotations.Presubmit;
-import android.server.wm.ActivityManagerState.ActivityDisplay;
+import android.server.wm.ActivityManagerState.DisplayContent;
import android.server.wm.ActivityManagerState.ActivityStack;
import android.server.wm.CommandSession.ActivityCallback;
import android.server.wm.CommandSession.ActivitySession;
@@ -80,7 +80,7 @@
public void testContentDestroyOnDisplayRemoved() {
try (final VirtualDisplaySession virtualDisplaySession = new VirtualDisplaySession()) {
// Create new private virtual display.
- final ActivityDisplay newDisplay = virtualDisplaySession.createDisplay();
+ final DisplayContent newDisplay = virtualDisplaySession.createDisplay();
mAmWmState.assertVisibility(VIRTUAL_DISPLAY_ACTIVITY, true /* visible */);
// Launch activities on new secondary display.
@@ -121,7 +121,7 @@
public void testActivityLaunchOnContentDestroyDisplayRemoved() {
try (final VirtualDisplaySession virtualDisplaySession = new VirtualDisplaySession()) {
// Create new private virtual display.
- final ActivityDisplay newDisplay = virtualDisplaySession.createDisplay();
+ final DisplayContent newDisplay = virtualDisplaySession.createDisplay();
mAmWmState.assertVisibility(VIRTUAL_DISPLAY_ACTIVITY, true /* visible */);
// Launch activities on new secondary display.
@@ -144,7 +144,7 @@
public void testDisplayResize() {
final VirtualDisplaySession virtualDisplaySession = createManagedVirtualDisplaySession();
// Create new virtual display.
- final ActivityDisplay newDisplay = virtualDisplaySession.createDisplay();
+ final DisplayContent newDisplay = virtualDisplaySession.createDisplay();
mAmWmState.assertVisibility(VIRTUAL_DISPLAY_ACTIVITY, true /* visible */);
// Launch a resizeable activity on new secondary display.
@@ -196,7 +196,7 @@
final VirtualDisplayLauncher virtualLauncher =
mObjectTracker.manage(new VirtualDisplayLauncher());
// Create new virtual display.
- final ActivityDisplay newDisplay = virtualLauncher.setResizeDisplay(false).createDisplay();
+ final DisplayContent newDisplay = virtualLauncher.setResizeDisplay(false).createDisplay();
mAmWmState.assertVisibility(VIRTUAL_DISPLAY_ACTIVITY, true /* visible */);
// Launch activity on new secondary display.
@@ -247,7 +247,7 @@
waitAndAssertTopResumedActivity(RESIZEABLE_ACTIVITY, DEFAULT_DISPLAY,
"Activity launched on primary display must be resumed");
- final ActivityDisplay newDisplay = createManagedExternalDisplaySession()
+ final DisplayContent newDisplay = createManagedExternalDisplaySession()
.setCanShowWithInsecureKeyguard(true).createVirtualDisplay();
launchActivityOnDisplay(TEST_ACTIVITY, newDisplay.mId);
@@ -283,7 +283,7 @@
@Test
public void testExternalDisplayToggleState() {
final ExternalDisplaySession externalDisplaySession = createManagedExternalDisplaySession();
- final ActivityDisplay newDisplay = externalDisplaySession.createVirtualDisplay();
+ final DisplayContent newDisplay = externalDisplaySession.createVirtualDisplay();
launchActivityOnDisplay(TEST_ACTIVITY, newDisplay.mId);
@@ -321,7 +321,7 @@
mAmWmState.getAmState().computeState();
final int displayCount = mAmWmState.getAmState().getDisplayCount();
try (final VirtualDisplaySession externalDisplaySession = new VirtualDisplaySession()) {
- final ActivityDisplay newDisplay = externalDisplaySession
+ final DisplayContent newDisplay = externalDisplaySession
.setSimulateDisplay(true).createDisplay();
launchActivityOnDisplay(VIRTUAL_DISPLAY_ACTIVITY, newDisplay.mId);
waitAndAssertTopResumedActivity(VIRTUAL_DISPLAY_ACTIVITY, newDisplay.mId,
@@ -346,7 +346,7 @@
launchActivity(LAUNCHING_ACTIVITY);
// Create new virtual display.
- final ActivityDisplay newDisplay = createManagedVirtualDisplaySession().createDisplay();
+ final DisplayContent newDisplay = createManagedVirtualDisplaySession().createDisplay();
mAmWmState.assertVisibility(VIRTUAL_DISPLAY_ACTIVITY, true /* visible */);
// Launch activity on new secondary display.
@@ -370,7 +370,7 @@
@Test
public void testMoveTaskBetweenDisplays() {
// Create new virtual display.
- final ActivityDisplay newDisplay = createManagedVirtualDisplaySession().createDisplay();
+ final DisplayContent newDisplay = createManagedVirtualDisplaySession().createDisplay();
mAmWmState.assertVisibility(VIRTUAL_DISPLAY_ACTIVITY, true /* visible */);
mAmWmState.assertFocusedActivity("Virtual display activity must be on top",
VIRTUAL_DISPLAY_ACTIVITY);
@@ -457,7 +457,7 @@
private void tryCreatingAndRemovingDisplayWithActivity(boolean splitScreen, int windowingMode) {
try (final VirtualDisplaySession virtualDisplaySession = new VirtualDisplaySession()) {
// Create new virtual display.
- final ActivityDisplay newDisplay = virtualDisplaySession
+ final DisplayContent newDisplay = virtualDisplaySession
.setPublicDisplay(true)
.setLaunchInSplitScreen(splitScreen)
.createDisplay();
@@ -516,7 +516,7 @@
private void validateStackFocusSwitchOnStackEmptied(VirtualDisplaySession virtualDisplaySession,
LockScreenSession lockScreenSession) {
// Create new virtual display.
- final ActivityDisplay newDisplay = virtualDisplaySession.createDisplay();
+ final DisplayContent newDisplay = virtualDisplaySession.createDisplay();
mAmWmState.assertVisibility(VIRTUAL_DISPLAY_ACTIVITY, true /* visible */);
// Launch activity on new secondary display.
@@ -551,7 +551,7 @@
assumeFalse(perDisplayFocusEnabled());
// Create new virtual display.
- final ActivityDisplay newDisplay = createManagedVirtualDisplaySession().createDisplay();
+ final DisplayContent newDisplay = createManagedVirtualDisplaySession().createDisplay();
mAmWmState.computeState(VIRTUAL_DISPLAY_ACTIVITY);
mAmWmState.assertFocusedActivity("Top activity must be the latest launched one",
@@ -598,7 +598,7 @@
assertEquals("Unexpected resumed activity",
0, mAmWmState.getAmState().getResumedActivitiesCount());
- final ActivityDisplay newDisplay = createManagedExternalDisplaySession()
+ final DisplayContent newDisplay = createManagedExternalDisplaySession()
.setCanShowWithInsecureKeyguard(true).createVirtualDisplay();
launchActivityOnDisplay(TEST_ACTIVITY, newDisplay.mId);
@@ -636,7 +636,7 @@
launchActivity(TEST_ACTIVITY);
- final ActivityDisplay newDisplay = createManagedExternalDisplaySession()
+ final DisplayContent newDisplay = createManagedExternalDisplaySession()
.createVirtualDisplay();
launchActivityOnDisplay(SHOW_WHEN_LOCKED_ATTR_ACTIVITY, newDisplay.mId);
@@ -658,7 +658,7 @@
launchActivity(TEST_ACTIVITY);
mAmWmState.waitForActivityState(TEST_ACTIVITY, STATE_RESUMED);
- final ActivityDisplay newDisplay = createManagedVirtualDisplaySession()
+ final DisplayContent newDisplay = createManagedVirtualDisplaySession()
.setSimulateDisplay(true).createDisplay();
launchActivityOnDisplay(VIRTUAL_DISPLAY_ACTIVITY, newDisplay.mId);
waitAndAssertTopResumedActivity(VIRTUAL_DISPLAY_ACTIVITY, newDisplay.mId,
@@ -689,7 +689,7 @@
*/
@Test
public void testSecondaryDisplayShowToast() {
- final ActivityDisplay newDisplay = createManagedVirtualDisplaySession()
+ final DisplayContent newDisplay = createManagedVirtualDisplaySession()
.setPublicDisplay(true)
.createDisplay();
final String TOAST_NAME = "Toast";
@@ -711,7 +711,7 @@
public void testTaskSurfaceSizeAfterReparentDisplay() {
try (final VirtualDisplaySession virtualDisplaySession = new VirtualDisplaySession()) {
// Create new simulated display and launch an activity on it.
- final ActivityDisplay newDisplay = virtualDisplaySession.setSimulateDisplay(true)
+ final DisplayContent newDisplay = virtualDisplaySession.setSimulateDisplay(true)
.createDisplay();
launchActivityOnDisplay(TEST_ACTIVITY, newDisplay.mId);
@@ -749,7 +749,7 @@
final TestActivitySession<StandardActivity> transitionActivitySession =
createManagedTestActivitySession();
// Create new simulated display.
- final ActivityDisplay newDisplay = createManagedVirtualDisplaySession()
+ final DisplayContent newDisplay = createManagedVirtualDisplaySession()
.setSimulateDisplay(true).createDisplay();
// Launch BottomActivity on top of launcher activity to prevent transition state
@@ -783,7 +783,7 @@
@Test
public void testNoTransitionWhenMovingActivityToDisplay() throws Exception {
// Create new simulated display & capture new display's transition state.
- final ActivityDisplay newDisplay = createManagedVirtualDisplaySession()
+ final DisplayContent newDisplay = createManagedVirtualDisplaySession()
.setSimulateDisplay(true).createDisplay();
// Launch TestActivity in virtual display & capture its transition state.
@@ -809,7 +809,7 @@
@Test
public void testPreQTopProcessResumedActivity() {
- final ActivityDisplay newDisplay = createManagedVirtualDisplaySession()
+ final DisplayContent newDisplay = createManagedVirtualDisplaySession()
.setSimulateDisplay(true).createDisplay();
getLaunchActivityBuilder().setUseInstrumentation()
@@ -839,4 +839,28 @@
mAmWmState.getAmState().getResumedActivitiesCountInPackage(
SDK_27_TEST_ACTIVITY.getPackageName()));
}
+
+ @Test
+ public void testPreQTopProcessResumedDisplayMoved() throws Exception {
+ final DisplayContent newDisplay = createManagedVirtualDisplaySession()
+ .setSimulateDisplay(true).createDisplay();
+ getLaunchActivityBuilder().setUseInstrumentation()
+ .setTargetActivity(SDK_27_LAUNCHING_ACTIVITY).setNewTask(true)
+ .setDisplayId(DEFAULT_DISPLAY).execute();
+ waitAndAssertTopResumedActivity(SDK_27_LAUNCHING_ACTIVITY, DEFAULT_DISPLAY,
+ "Activity launched on default display must be resumed and focused");
+
+ getLaunchActivityBuilder().setUseInstrumentation()
+ .setTargetActivity(SDK_27_TEST_ACTIVITY).setNewTask(true)
+ .setDisplayId(newDisplay.mId).execute();
+ waitAndAssertTopResumedActivity(SDK_27_TEST_ACTIVITY, newDisplay.mId,
+ "Activity launched on secondary display must be resumed and focused");
+
+ tapOnDisplayCenter(DEFAULT_DISPLAY);
+ waitAndAssertTopResumedActivity(SDK_27_LAUNCHING_ACTIVITY, DEFAULT_DISPLAY,
+ "Activity launched on default display must be resumed and focused");
+ assertEquals("There must be only one resumed activity in the package.", 1,
+ mAmWmState.getAmState().getResumedActivitiesCountInPackage(
+ SDK_27_LAUNCHING_ACTIVITY.getPackageName()));
+ }
}
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayPrivateDisplayTests.java b/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayPrivateDisplayTests.java
index 0ba5526..93b1efa 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayPrivateDisplayTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayPrivateDisplayTests.java
@@ -28,7 +28,7 @@
import android.content.Context;
import android.content.Intent;
import android.platform.test.annotations.Presubmit;
-import android.server.wm.ActivityManagerState.ActivityDisplay;
+import android.server.wm.ActivityManagerState.DisplayContent;
import android.server.wm.WindowManagerState.Display;
import android.util.Log;
@@ -70,8 +70,8 @@
mPrivateDisplayIds.clear();
mAmWmState.computeState(true);
- for (ActivityDisplay activityDisplay: getDisplaysStates()) {
- int displayId = activityDisplay.mId;
+ for (DisplayContent displayContent: getDisplaysStates()) {
+ int displayId = displayContent.mId;
Display display = mAmWmState.getWmState().getDisplay(displayId);
if ((display.getFlags() & FLAG_PRIVATE) != 0) {
mPrivateDisplayIds.add(displayId);
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplaySecurityTests.java b/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplaySecurityTests.java
index 646d1ed..f45ec03 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplaySecurityTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplaySecurityTests.java
@@ -63,7 +63,7 @@
import android.hardware.display.DisplayManager;
import android.os.Bundle;
import android.platform.test.annotations.Presubmit;
-import android.server.wm.ActivityManagerState.ActivityDisplay;
+import android.server.wm.ActivityManagerState.DisplayContent;
import android.server.wm.ActivityManagerState.ActivityStack;
import android.server.wm.CommandSession.ActivitySession;
import android.server.wm.TestJournalProvider.TestJournalContainer;
@@ -107,7 +107,7 @@
@Test
public void testLaunchWithoutPermissionOnVirtualDisplayByOwner() {
// Create new virtual display.
- final ActivityDisplay newDisplay = createManagedVirtualDisplaySession().createDisplay();
+ final DisplayContent newDisplay = createManagedVirtualDisplaySession().createDisplay();
// Try to launch an activity and check it security exception was triggered.
getLaunchActivityBuilder()
@@ -135,7 +135,7 @@
@Test
public void testLaunchWithoutPermissionOnVirtualDisplay() {
// Create new virtual display.
- final ActivityDisplay newDisplay = createManagedVirtualDisplaySession().createDisplay();
+ final DisplayContent newDisplay = createManagedVirtualDisplaySession().createDisplay();
separateTestJournal();
@@ -161,7 +161,7 @@
@Test
public void testConsequentLaunchActivityFromVirtualDisplayNoEmbedding() {
// Create new virtual display.
- final ActivityDisplay newDisplay = createManagedVirtualDisplaySession().createDisplay();
+ final DisplayContent newDisplay = createManagedVirtualDisplaySession().createDisplay();
// Launch activity on new secondary display.
launchActivityOnDisplay(LAUNCHING_ACTIVITY, newDisplay.mId);
@@ -193,7 +193,7 @@
*/
@Test
public void testCanAccessSystemOwnedDisplay() {
- final ActivityDisplay newDisplay = createManagedVirtualDisplaySession()
+ final DisplayContent newDisplay = createManagedVirtualDisplaySession()
.setSimulateDisplay(true)
.createDisplay();
@@ -207,7 +207,7 @@
*/
@Test
public void testCanAccessPublicVirtualDisplayWithInternalPermission() {
- final ActivityDisplay newDisplay = createManagedVirtualDisplaySession()
+ final DisplayContent newDisplay = createManagedVirtualDisplaySession()
.setPublicDisplay(true)
.createDisplay();
@@ -224,7 +224,7 @@
*/
@Test
public void testCanAccessPrivateVirtualDisplayWithInternalPermission() {
- final ActivityDisplay newDisplay = createManagedVirtualDisplaySession()
+ final DisplayContent newDisplay = createManagedVirtualDisplaySession()
.setPublicDisplay(false)
.createDisplay();
@@ -242,7 +242,7 @@
*/
@Test
public void testCantAccessPublicVirtualDisplayNoEmbeddingPermission() {
- final ActivityDisplay newDisplay = createManagedVirtualDisplaySession()
+ final DisplayContent newDisplay = createManagedVirtualDisplaySession()
.setPublicDisplay(true)
.createDisplay();
@@ -256,7 +256,7 @@
*/
@Test
public void testCantAccessPublicVirtualDisplayActivityEmbeddingNotAllowed() {
- final ActivityDisplay newDisplay = createManagedVirtualDisplaySession()
+ final DisplayContent newDisplay = createManagedVirtualDisplaySession()
.setPublicDisplay(true)
.createDisplay();
@@ -273,7 +273,7 @@
*/
@Test
public void testCanAccessPublicVirtualDisplayActivityEmbeddingAllowed() {
- final ActivityDisplay newDisplay = createManagedVirtualDisplaySession()
+ final DisplayContent newDisplay = createManagedVirtualDisplaySession()
.setPublicDisplay(true)
.createDisplay();
@@ -290,7 +290,7 @@
*/
@Test
public void testCantAccessPrivateVirtualDisplay() {
- final ActivityDisplay newDisplay = createManagedVirtualDisplaySession()
+ final DisplayContent newDisplay = createManagedVirtualDisplaySession()
.setPublicDisplay(false)
.createDisplay();
@@ -304,7 +304,7 @@
*/
@Test
public void testCanAccessPrivateVirtualDisplayByOwner() {
- final ActivityDisplay newDisplay = createManagedVirtualDisplaySession()
+ final DisplayContent newDisplay = createManagedVirtualDisplaySession()
.setPublicDisplay(false)
.createDisplay();
@@ -327,7 +327,7 @@
*/
@Test
public void testCanAccessPrivateVirtualDisplayByUidPresentOnDisplayActivityEmbeddingAllowed() {
- final ActivityDisplay newDisplay = createManagedVirtualDisplaySession()
+ final DisplayContent newDisplay = createManagedVirtualDisplaySession()
.setPublicDisplay(false)
.createDisplay();
// Launch a test activity into the target display.
@@ -352,7 +352,7 @@
@Test
public void testCanAccessPrivateVirtualDisplayByUidPresentOnDisplayActivityEmbeddingNotAllowed()
throws Exception {
- final ActivityDisplay newDisplay = createManagedVirtualDisplaySession()
+ final DisplayContent newDisplay = createManagedVirtualDisplaySession()
.setPublicDisplay(false)
.createDisplay();
// Launch a test activity into the target display.
@@ -389,7 +389,7 @@
final VirtualDisplayLauncher virtualDisplayLauncher =
mObjectTracker.manage(new VirtualDisplayLauncher());
// Create a virtual private display.
- final ActivityDisplay newDisplay = virtualDisplayLauncher
+ final DisplayContent newDisplay = virtualDisplayLauncher
.setPublicDisplay(false)
.createDisplay();
// Launch an embeddable activity into the private display.
@@ -418,7 +418,7 @@
final VirtualDisplayLauncher virtualDisplayLauncher =
mObjectTracker.manage(new VirtualDisplayLauncher());
// Create a virtual private display.
- final ActivityDisplay newDisplay = virtualDisplayLauncher
+ final DisplayContent newDisplay = virtualDisplayLauncher
.setPublicDisplay(false)
.createDisplay();
// Launch an embeddable activity into the private display.
@@ -443,7 +443,7 @@
@Test
public void testDisplayHasAccess_ExceptionWhenAddViewWithoutPresentOnPrivateDisplay() {
// Create a virtual private display.
- final ActivityDisplay newDisplay = createManagedVirtualDisplaySession()
+ final DisplayContent newDisplay = createManagedVirtualDisplaySession()
.setPublicDisplay(false)
.createDisplay();
try {
@@ -473,7 +473,7 @@
@Test
public void testPermissionLaunchFromShell(){
// Create new virtual display.
- final ActivityDisplay newDisplay = createManagedVirtualDisplaySession().createDisplay();
+ final DisplayContent newDisplay = createManagedVirtualDisplaySession().createDisplay();
mAmWmState.assertVisibility(VIRTUAL_DISPLAY_ACTIVITY, true /* visible */);
mAmWmState.assertFocusedActivity("Virtual display activity must be on top",
VIRTUAL_DISPLAY_ACTIVITY);
@@ -507,7 +507,7 @@
@Test
public void testPermissionLaunchFromAppOnSecondary() {
// Create new simulated display.
- final ActivityDisplay newDisplay = createManagedVirtualDisplaySession()
+ final DisplayContent newDisplay = createManagedVirtualDisplaySession()
.setSimulateDisplay(true)
.createDisplay();
@@ -535,7 +535,7 @@
/** Tests that an activity can launch an activity from a different UID into its own task. */
@Test
public void testPermissionLaunchMultiUidTask() {
- final ActivityDisplay newDisplay = createManagedVirtualDisplaySession()
+ final DisplayContent newDisplay = createManagedVirtualDisplaySession()
.setSimulateDisplay(true)
.createDisplay();
@@ -565,7 +565,7 @@
@Test
public void testPermissionLaunchFromOwner() {
// Create new virtual display.
- final ActivityDisplay newDisplay = createManagedVirtualDisplaySession().createDisplay();
+ final DisplayContent newDisplay = createManagedVirtualDisplaySession().createDisplay();
mAmWmState.assertVisibility(VIRTUAL_DISPLAY_ACTIVITY, true /* visible */);
mAmWmState.assertFocusedActivity("Virtual display activity must be focused",
VIRTUAL_DISPLAY_ACTIVITY);
@@ -602,7 +602,7 @@
@Test
public void testPermissionLaunchFromDifferentApp() {
// Create new virtual display.
- final ActivityDisplay newDisplay = createManagedVirtualDisplaySession().createDisplay();
+ final DisplayContent newDisplay = createManagedVirtualDisplaySession().createDisplay();
mAmWmState.assertVisibility(VIRTUAL_DISPLAY_ACTIVITY, true /* visible */);
mAmWmState.assertFocusedActivity("Virtual display activity must be focused",
VIRTUAL_DISPLAY_ACTIVITY);
@@ -636,7 +636,7 @@
@Test
public void testFlagShowWithInsecureKeyguardOnPublicVirtualDisplay() {
// Try to create new show-with-insecure-keyguard public virtual display.
- final ActivityDisplay newDisplay = createManagedVirtualDisplaySession()
+ final DisplayContent newDisplay = createManagedVirtualDisplaySession()
.setPublicDisplay(true)
.setCanShowWithInsecureKeyguard(true)
.setMustBeCreated(false)
@@ -653,7 +653,7 @@
public void testSettingFlagWithoutInternalSystemPermission() throws Exception {
// The reason to use a trusted display is that we can guarantee the security exception
// is coming from lacking internal system permission.
- final ActivityDisplay trustedDisplay = createManagedVirtualDisplaySession()
+ final DisplayContent trustedDisplay = createManagedVirtualDisplaySession()
.setSimulateDisplay(true)
.createDisplay();
final WindowManager wm = mTargetContext.getSystemService(WindowManager.class);
@@ -695,7 +695,7 @@
public void testGettingFlagWithoutInternalSystemPermission() {
// The reason to use a trusted display is that we can guarantee the security exception
// is coming from lacking internal system permission.
- final ActivityDisplay trustedDisplay = createManagedVirtualDisplaySession()
+ final DisplayContent trustedDisplay = createManagedVirtualDisplaySession()
.setSimulateDisplay(true)
.createDisplay();
final WindowManager wm = mTargetContext.getSystemService(WindowManager.class);
@@ -722,7 +722,7 @@
*/
@Test
public void testSettingFlagToUntrustedDisplay() throws Exception {
- final ActivityDisplay untrustedDisplay = createManagedVirtualDisplaySession()
+ final DisplayContent untrustedDisplay = createManagedVirtualDisplaySession()
.createDisplay();
final WindowManager wm = mTargetContext.getSystemService(WindowManager.class);
@@ -767,7 +767,7 @@
*/
@Test
public void testGettingFlagFromUntrustedDisplay() {
- final ActivityDisplay untrustedDisplay = createManagedVirtualDisplaySession()
+ final DisplayContent untrustedDisplay = createManagedVirtualDisplaySession()
.createDisplay();
final WindowManager wm = mTargetContext.getSystemService(WindowManager.class);
@@ -787,7 +787,7 @@
*/
@Test
public void testSettingFlagToTrustedDisplay() throws Exception {
- final ActivityDisplay trustedDisplay = createManagedVirtualDisplaySession()
+ final DisplayContent trustedDisplay = createManagedVirtualDisplaySession()
.setSimulateDisplay(true)
.createDisplay();
final WindowManager wm = mTargetContext.getSystemService(WindowManager.class);
@@ -843,7 +843,7 @@
final TestActivitySession<ImeTestActivity> imeTestActivitySession =
createManagedTestActivitySession();
// Create a untrusted virtual display and assume the display should not show IME window.
- final ActivityDisplay newDisplay = createManagedVirtualDisplaySession()
+ final DisplayContent newDisplay = createManagedVirtualDisplaySession()
.setPublicDisplay(true).createDisplay();
// Launch Ime test activity in virtual display.
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplaySystemDecorationTests.java b/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplaySystemDecorationTests.java
index 1eb60c2..58fb32a 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplaySystemDecorationTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplaySystemDecorationTests.java
@@ -53,7 +53,7 @@
import android.os.Bundle;
import android.os.SystemClock;
import android.platform.test.annotations.Presubmit;
-import android.server.wm.ActivityManagerState.ActivityDisplay;
+import android.server.wm.ActivityManagerState.DisplayContent;
import android.server.wm.TestJournalProvider.TestJournalContainer;
import android.server.wm.WindowManagerState.Display;
import android.server.wm.WindowManagerState.WindowState;
@@ -78,7 +78,6 @@
import java.util.List;
import java.util.concurrent.TimeUnit;
-import java.util.function.Predicate;
/**
* Build/Install/Run:
@@ -114,7 +113,7 @@
TestJournalContainer.start();
- final ActivityDisplay newDisplay = virtualDisplaySession
+ final DisplayContent newDisplay = virtualDisplaySession
.setSimulateDisplay(true).setShowSystemDecorations(true).createDisplay();
wallpaperSession.setWallpaperComponent(TEST_LIVE_WALLPAPER_SERVICE);
@@ -131,10 +130,10 @@
public void testWallpaperShowOnSecondaryDisplays() {
final ChangeWallpaperSession wallpaperSession = createManagedChangeWallpaperSession();
- final ActivityDisplay untrustedDisplay = createManagedExternalDisplaySession()
+ final DisplayContent untrustedDisplay = createManagedExternalDisplaySession()
.setPublicDisplay(true).setShowSystemDecorations(true).createVirtualDisplay();
- final ActivityDisplay decoredSystemDisplay = createManagedVirtualDisplaySession()
+ final DisplayContent decoredSystemDisplay = createManagedVirtualDisplaySession()
.setSimulateDisplay(true).setShowSystemDecorations(true).createDisplay();
final Bitmap tmpWallpaper = wallpaperSession.getTestBitmap();
@@ -202,7 +201,7 @@
@Test
public void testNavBarShowingOnDisplayWithDecor() {
assumeHasBars();
- final ActivityDisplay newDisplay = createManagedExternalDisplaySession()
+ final DisplayContent newDisplay = createManagedExternalDisplaySession()
.setPublicDisplay(true).setShowSystemDecorations(true).createVirtualDisplay();
mAmWmState.waitAndAssertNavBarShownOnDisplay(newDisplay.mId);
@@ -251,7 +250,7 @@
// bars were added to a display that was added before executing this method that shouldn't
// have nav bars (i.e. private or without system ui decor).
try (final ExternalDisplaySession secondDisplaySession = new ExternalDisplaySession()) {
- final ActivityDisplay supportsSysDecorDisplay = secondDisplaySession
+ final DisplayContent supportsSysDecorDisplay = secondDisplaySession
.setPublicDisplay(true).setShowSystemDecorations(true).createVirtualDisplay();
mAmWmState.waitAndAssertNavBarShownOnDisplay(supportsSysDecorDisplay.mId);
// This display has finished his task. Just close it.
@@ -278,7 +277,7 @@
createManagedHomeActivitySession(SECONDARY_HOME_ACTIVITY);
// Create new virtual display without system decoration support.
- final ActivityDisplay newDisplay = createManagedExternalDisplaySession()
+ final DisplayContent newDisplay = createManagedExternalDisplaySession()
.createVirtualDisplay();
// Secondary home activity can't be launched on the display without system decoration
@@ -295,7 +294,7 @@
createManagedHomeActivitySession(SINGLE_HOME_ACTIVITY);
// Create new virtual display with system decoration support.
- final ActivityDisplay newDisplay = createManagedExternalDisplaySession()
+ final DisplayContent newDisplay = createManagedExternalDisplaySession()
.setShowSystemDecorations(true)
.createVirtualDisplay();
@@ -318,7 +317,7 @@
createManagedHomeActivitySession(SINGLE_SECONDARY_HOME_ACTIVITY);
// Create new virtual display with system decoration support.
- final ActivityDisplay newDisplay = createManagedExternalDisplaySession()
+ final DisplayContent newDisplay = createManagedExternalDisplaySession()
.setShowSystemDecorations(true)
.createVirtualDisplay();
@@ -342,7 +341,7 @@
final VirtualDisplaySession virtualDisplaySession = createManagedVirtualDisplaySession();
// Create new virtual display with system decoration support.
- final ActivityDisplay newDisplay = createManagedExternalDisplaySession()
+ final DisplayContent newDisplay = createManagedExternalDisplaySession()
.setShowSystemDecorations(true)
.createVirtualDisplay();
@@ -366,7 +365,7 @@
final VirtualDisplaySession virtualDisplaySession = createManagedVirtualDisplaySession();
// Create new virtual display with system decoration support.
- final ActivityDisplay newDisplay = createManagedExternalDisplaySession()
+ final DisplayContent newDisplay = createManagedExternalDisplaySession()
.setShowSystemDecorations(true)
.createVirtualDisplay();
@@ -389,7 +388,7 @@
createManagedTestActivitySession();
// Create a virtual display and launch an activity on it.
- final ActivityDisplay newDisplay = createManagedVirtualDisplaySession()
+ final DisplayContent newDisplay = createManagedVirtualDisplaySession()
.setShowSystemDecorations(true)
.setSimulateDisplay(true)
.createDisplay();
@@ -435,7 +434,7 @@
final TestActivitySession<ImeTestActivityWithBrokenContextWrapper> imeTestActivitySession =
createManagedTestActivitySession();
// Create a virtual display and launch an activity on it.
- final ActivityDisplay newDisplay = createManagedVirtualDisplaySession()
+ final DisplayContent newDisplay = createManagedVirtualDisplaySession()
.setShowSystemDecorations(true)
.setSimulateDisplay(true)
.createDisplay();
@@ -475,7 +474,7 @@
createManagedTestActivitySession();
// Create a virtual display and launch an activity on virtual & default display.
- final ActivityDisplay newDisplay = createManagedVirtualDisplaySession()
+ final DisplayContent newDisplay = createManagedVirtualDisplaySession()
.setShowSystemDecorations(true)
.setSimulateDisplay(true)
.createDisplay();
@@ -531,7 +530,7 @@
createManagedTestActivitySession();
// Create a virtual display by app and assume the display should not show IME window.
- final ActivityDisplay newDisplay = createManagedVirtualDisplaySession()
+ final DisplayContent newDisplay = createManagedVirtualDisplaySession()
.setPublicDisplay(true)
.createDisplay();
SystemUtil.runWithShellPermissionIdentity(
@@ -653,7 +652,7 @@
}
void assertImeWindowAndDisplayConfiguration(
- WindowManagerState.WindowState imeWinState, ActivityDisplay display) {
+ WindowManagerState.WindowState imeWinState, DisplayContent display) {
final Configuration configurationForIme = imeWinState.mMergedOverrideConfiguration;
final Configuration configurationForDisplay = display.mMergedOverrideConfiguration;
final int displayDensityDpiForIme = configurationForIme.densityDpi;
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayTestBase.java b/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayTestBase.java
index 4886252..417115e 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayTestBase.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayTestBase.java
@@ -53,7 +53,7 @@
import android.graphics.Rect;
import android.os.Bundle;
import android.provider.Settings;
-import android.server.wm.ActivityManagerState.ActivityDisplay;
+import android.server.wm.ActivityManagerState.DisplayContent;
import android.server.wm.CommandSession.ActivitySession;
import android.server.wm.CommandSession.ActivitySessionClient;
import android.server.wm.settings.SettingsSession;
@@ -99,12 +99,12 @@
mTargetContext = getInstrumentation().getTargetContext();
}
- ActivityDisplay getDisplayState(int displayId) {
+ DisplayContent getDisplayState(int displayId) {
return getDisplayState(getDisplaysStates(), displayId);
}
- ActivityDisplay getDisplayState(List<ActivityDisplay> displays, int displayId) {
- for (ActivityDisplay display : displays) {
+ DisplayContent getDisplayState(List<DisplayContent> displays, int displayId) {
+ for (DisplayContent display : displays) {
if (display.mId == displayId) {
return display;
}
@@ -113,9 +113,9 @@
}
/** Return the display state with width, height, dpi. Always not default display. */
- ActivityDisplay getDisplayState(List<ActivityDisplay> displays, int width, int height,
+ DisplayContent getDisplayState(List<DisplayContent> displays, int width, int height,
int dpi) {
- for (ActivityDisplay display : displays) {
+ for (DisplayContent display : displays) {
if (display.mId == DEFAULT_DISPLAY) {
continue;
}
@@ -128,17 +128,17 @@
return null;
}
- List<ActivityDisplay> getDisplaysStates() {
+ List<DisplayContent> getDisplaysStates() {
mAmWmState.getAmState().computeState();
return mAmWmState.getAmState().getDisplays();
}
/** Find the display that was not originally reported in oldDisplays and added in newDisplays */
- List<ActivityDisplay> findNewDisplayStates(List<ActivityDisplay> oldDisplays,
- List<ActivityDisplay> newDisplays) {
- final ArrayList<ActivityDisplay> result = new ArrayList<>();
+ List<DisplayContent> findNewDisplayStates(List<DisplayContent> oldDisplays,
+ List<DisplayContent> newDisplays) {
+ final ArrayList<DisplayContent> result = new ArrayList<>();
- for (ActivityDisplay newDisplay : newDisplays) {
+ for (DisplayContent newDisplay : newDisplays) {
if (oldDisplays.stream().noneMatch(d -> d.mId == newDisplay.mId)) {
result.add(newDisplay);
}
@@ -339,12 +339,12 @@
}
@Nullable
- public ActivityDisplay createDisplay() {
+ public DisplayContent createDisplay() {
return createDisplays(1).stream().findFirst().orElse(null);
}
@NonNull
- List<ActivityDisplay> createDisplays(int count) {
+ List<DisplayContent> createDisplays(int count) {
if (mSimulateDisplay) {
return simulateDisplay();
} else {
@@ -371,9 +371,9 @@
* <pre>
* <code>mDensityDpi</code> provide custom density for the display.
* </pre>
- * @return {@link ActivityDisplay} of newly created display.
+ * @return {@link DisplayContent} of newly created display.
*/
- private List<ActivityDisplay> simulateDisplay() {
+ private List<DisplayContent> simulateDisplay() {
// Create virtual display with custom density dpi and specified size.
mOverlayDisplayDeviceSession.set(mSimulationDisplaySize + "/" + mDensityDpi);
if (mShowSystemDecorations) {
@@ -399,10 +399,10 @@
* creation.
* </pre>
* @param displayCount number of displays to be created.
- * @return A list of {@link ActivityDisplay} that represent newly created displays.
+ * @return A list of {@link DisplayContent} that represent newly created displays.
* @throws Exception
*/
- private List<ActivityDisplay> createVirtualDisplays(int displayCount) {
+ private List<DisplayContent> createVirtualDisplays(int displayCount) {
// Start an activity that is able to create virtual displays.
if (mLaunchInSplitScreen) {
getLaunchActivityBuilder()
@@ -417,7 +417,7 @@
mAmWmState.assertVisibility(VIRTUAL_DISPLAY_ACTIVITY, true /* visible */);
mAmWmState.assertFocusedActivity("Focus must be on virtual display host activity",
VIRTUAL_DISPLAY_ACTIVITY);
- final List<ActivityDisplay> originalDS = getDisplaysStates();
+ final List<DisplayContent> originalDS = getDisplaysStates();
// Create virtual display with custom density dpi.
final StringBuilder createVirtualDisplayCommand = new StringBuilder(
@@ -466,13 +466,13 @@
private final ActivitySessionClient mActivitySessionClient = createActivitySessionClient();
ActivitySession launchActivityOnDisplay(ComponentName activityName,
- ActivityDisplay display) {
+ DisplayContent display) {
return launchActivityOnDisplay(activityName, display, null /* extrasConsumer */,
true /* withShellPermission */, true /* waitForLaunch */);
}
ActivitySession launchActivityOnDisplay(ComponentName activityName,
- ActivityDisplay display, Consumer<Bundle> extrasConsumer,
+ DisplayContent display, Consumer<Bundle> extrasConsumer,
boolean withShellPermission, boolean waitForLaunch) {
return launchActivity(builder -> builder
// VirtualDisplayActivity is in different package. If the display is not public,
@@ -502,7 +502,7 @@
/** Helper class to save, set, and restore overlay_display_devices preference. */
private class OverlayDisplayDevicesSession extends SettingsSession<String> {
/** The displays which are created by this session. */
- private final List<ActivityDisplay> mDisplays = new ArrayList<>();
+ private final List<DisplayContent> mDisplays = new ArrayList<>();
/** The configured displays that need to be restored when this session is closed. */
private final List<OverlayDisplayState> mDisplayStates = new ArrayList<>();
private final WindowManager mWm;
@@ -516,13 +516,13 @@
mWm = context.getSystemService(WindowManager.class);
}
- List<ActivityDisplay> getCreatedDisplays() {
+ List<DisplayContent> getCreatedDisplays() {
return new ArrayList<>(mDisplays);
}
@Override
public void set(String value) {
- final List<ActivityDisplay> originalDisplays = getDisplaysStates();
+ final List<DisplayContent> originalDisplays = getDisplaysStates();
super.set(value);
final int newDisplayCount = 1 + (int) value.chars().filter(ch -> ch == ';').count();
mDisplays.addAll(assertAndGetNewDisplays(newDisplayCount, originalDisplays));
@@ -530,7 +530,7 @@
void configureDisplays(boolean requestShowSysDecors, boolean requestShowIme) {
SystemUtil.runWithShellPermissionIdentity(() -> {
- for (ActivityDisplay display : mDisplays) {
+ for (DisplayContent display : mDisplays) {
final boolean showSystemDecors = mWm.shouldShowSystemDecors(display.mId);
final boolean showIme = mWm.shouldShowIme(display.mId);
mDisplayStates.add(new OverlayDisplayState(
@@ -590,7 +590,7 @@
}
/** Wait for provided number of displays and report their configurations. */
- List<ActivityDisplay> getDisplayStateAfterChange(int expectedDisplayCount) {
+ List<DisplayContent> getDisplayStateAfterChange(int expectedDisplayCount) {
return Condition.waitForResult("the correct number of displays=" + expectedDisplayCount,
condition -> condition
.setReturnLastResult(true)
@@ -599,11 +599,11 @@
displays -> areDisplaysValid(displays, expectedDisplayCount)));
}
- private boolean areDisplaysValid(List<ActivityDisplay> displays, int expectedDisplayCount) {
+ private boolean areDisplaysValid(List<DisplayContent> displays, int expectedDisplayCount) {
if (displays.size() != expectedDisplayCount) {
return false;
}
- for (ActivityDisplay display : displays) {
+ for (DisplayContent display : displays) {
if (display.mOverrideConfiguration.densityDpi == 0) {
return false;
}
@@ -618,12 +618,12 @@
* @param originalDisplays display states before creation of new display(s).
* @return list of new displays, empty list if no new display is created.
*/
- private List<ActivityDisplay> assertAndGetNewDisplays(int newDisplayCount,
- List<ActivityDisplay> originalDisplays) {
+ private List<DisplayContent> assertAndGetNewDisplays(int newDisplayCount,
+ List<DisplayContent> originalDisplays) {
final int originalDisplayCount = originalDisplays.size();
// Wait for the display(s) to be created and get configurations.
- final List<ActivityDisplay> ds = getDisplayStateAfterChange(
+ final List<DisplayContent> ds = getDisplayStateAfterChange(
originalDisplayCount + newDisplayCount);
if (newDisplayCount != -1) {
assertEquals("New virtual display(s) must be created",
@@ -635,7 +635,7 @@
}
// Find the newly added display(s).
- final List<ActivityDisplay> newDisplays = findNewDisplayStates(originalDisplays, ds);
+ final List<DisplayContent> newDisplays = findNewDisplayStates(originalDisplays, ds);
assertThat("New virtual display must be created", newDisplays, hasSize(newDisplayCount));
return newDisplays;
@@ -710,8 +710,8 @@
/**
* Creates a private virtual display with insecure keyguard flags set.
*/
- ActivityDisplay createVirtualDisplay() {
- final List<ActivityDisplay> originalDS = getDisplaysStates();
+ DisplayContent createVirtualDisplay() {
+ final List<DisplayContent> originalDS = getDisplaysStates();
final int originalDisplayCount = originalDS.size();
mExternalDisplayHelper = new VirtualDisplayHelper();
@@ -722,12 +722,12 @@
.createAndWaitForDisplay();
// Wait for the virtual display to be created and get configurations.
- final List<ActivityDisplay> ds = getDisplayStateAfterChange(originalDisplayCount + 1);
+ final List<DisplayContent> ds = getDisplayStateAfterChange(originalDisplayCount + 1);
assertEquals("New virtual display must be created", originalDisplayCount + 1,
ds.size());
// Find the newly added display.
- final ActivityDisplay newDisplay = findNewDisplayStates(originalDS, ds).get(0);
+ final DisplayContent newDisplay = findNewDisplayStates(originalDS, ds).get(0);
mDisplayId = newDisplay.mId;
return newDisplay;
}
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/SplitScreenTests.java b/tests/framework/base/windowmanager/src/android/server/wm/SplitScreenTests.java
index a410ee1..56f7e0b 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/SplitScreenTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/SplitScreenTests.java
@@ -269,7 +269,7 @@
// Move to split-screen primary
final int taskId = mAmWmState.getAmState().getTaskByActivity(LAUNCHING_ACTIVITY).mTaskId;
- moveTaskToPrimarySplitScreen(taskId, true /* showRecents */);
+ moveTaskToPrimarySplitScreen(taskId, true /* showSideActivity */);
// Launch target to side
final LaunchActivityBuilder targetActivityLauncher = getLaunchActivityBuilder()
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/VrDisplayTests.java b/tests/framework/base/windowmanager/src/android/server/wm/VrDisplayTests.java
index 9573cfa..26026e2 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/VrDisplayTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/VrDisplayTests.java
@@ -31,7 +31,7 @@
import android.content.ComponentName;
import android.platform.test.annotations.Presubmit;
import android.provider.Settings;
-import android.server.wm.ActivityManagerState.ActivityDisplay;
+import android.server.wm.ActivityManagerState.DisplayContent;
import android.server.wm.settings.SettingsSession;
import com.android.cts.verifier.vr.MockVrListenerService;
@@ -140,8 +140,8 @@
getActivityName(LAUNCHING_ACTIVITY), focusedStack.mResumedActivity);
// Check if the launch activity is in Vr virtual display id.
- final List<ActivityDisplay> reportedDisplays = getDisplaysStates();
- final ActivityDisplay vrDisplay = getDisplayState(reportedDisplays,
+ final List<DisplayContent> reportedDisplays = getDisplaysStates();
+ final DisplayContent vrDisplay = getDisplayState(reportedDisplays,
VR_VIRTUAL_DISPLAY_WIDTH, VR_VIRTUAL_DISPLAY_HEIGHT, VR_VIRTUAL_DISPLAY_DPI);
assertNotNull("Vr mode should have a virtual display", vrDisplay);
@@ -190,8 +190,8 @@
getActivityName(LAUNCHING_ACTIVITY), focusedStack.mResumedActivity);
// Check if the launch activity is in Vr virtual display id.
- final List<ActivityDisplay> reportedDisplays = getDisplaysStates();
- final ActivityDisplay vrDisplay = getDisplayState(reportedDisplays,
+ final List<DisplayContent> reportedDisplays = getDisplaysStates();
+ final DisplayContent vrDisplay = getDisplayState(reportedDisplays,
VR_VIRTUAL_DISPLAY_WIDTH, VR_VIRTUAL_DISPLAY_HEIGHT, VR_VIRTUAL_DISPLAY_DPI);
assertNotNull("Vr mode should have a virtual display", vrDisplay);
@@ -240,8 +240,8 @@
focusedStack.mResumedActivity);
// Check if the launch activity is in Vr virtual display id.
- final List<ActivityDisplay> reportedDisplays = getDisplaysStates();
- final ActivityDisplay vrDisplay = getDisplayState(reportedDisplays,
+ final List<DisplayContent> reportedDisplays = getDisplaysStates();
+ final DisplayContent vrDisplay = getDisplayState(reportedDisplays,
VR_VIRTUAL_DISPLAY_WIDTH, VR_VIRTUAL_DISPLAY_HEIGHT,
VR_VIRTUAL_DISPLAY_DPI);
assertNotNull("Vr mode should have a virtual display", vrDisplay);
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/WindowFocusTests.java b/tests/framework/base/windowmanager/src/android/server/wm/WindowFocusTests.java
index 55e3b63..2cf5469 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/WindowFocusTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/WindowFocusTests.java
@@ -128,7 +128,7 @@
assumeTrue(supportsMultiDisplay());
try (VirtualDisplaySession displaySession = new VirtualDisplaySession()) {
- final ActivityManagerState.ActivityDisplay display = displaySession
+ final ActivityManagerState.DisplayContent display = displaySession
.setPublicDisplay(true).setSimulateDisplay(true).createDisplay();
final int secondaryDisplayId = display.mId;
final SecondaryActivity secondaryActivity =
@@ -182,7 +182,7 @@
DEFAULT_DISPLAY);
try (VirtualDisplaySession displaySession = new VirtualDisplaySession()) {
- final ActivityManagerState.ActivityDisplay display = displaySession
+ final ActivityManagerState.DisplayContent display = displaySession
.setPublicDisplay(true).setSimulateDisplay(true).createDisplay();
final int secondaryDisplayId = display.mId;
final SecondaryActivity secondaryActivity =
@@ -228,7 +228,7 @@
assumeTrue(supportsMultiDisplay());
try (VirtualDisplaySession displaySession = new VirtualDisplaySession()) {
- final ActivityManagerState.ActivityDisplay display = displaySession
+ final ActivityManagerState.DisplayContent display = displaySession
.setPublicDisplay(true).setSimulateDisplay(true).createDisplay();
final int secondaryDisplayId = display.mId;
final SecondaryActivity secondaryActivity =
@@ -260,7 +260,7 @@
final SecondaryActivity secondaryActivity;
try (VirtualDisplaySession displaySession = new VirtualDisplaySession()) {
- final ActivityManagerState.ActivityDisplay display = displaySession
+ final ActivityManagerState.DisplayContent display = displaySession
.setPublicDisplay(true).createDisplay();
final int secondaryDisplayId = display.mId;
// For launching activity on untrusted display, by default the activity will not get
@@ -289,7 +289,7 @@
PrimaryActivity primaryActivity = startActivity(PrimaryActivity.class, DEFAULT_DISPLAY);
try (VirtualDisplaySession displaySession = new VirtualDisplaySession()) {
- final ActivityManagerState.ActivityDisplay display = displaySession
+ final ActivityManagerState.DisplayContent display = displaySession
.setPublicDisplay(true).setSimulateDisplay(true).createDisplay();
final int secondaryDisplayId = display.mId;
SecondaryActivity secondaryActivity = startActivity(SecondaryActivity.class,
@@ -314,7 +314,7 @@
PrimaryActivity primaryActivity = startActivity(PrimaryActivity.class, DEFAULT_DISPLAY);
try (VirtualDisplaySession displaySession = new VirtualDisplaySession()) {
- final ActivityManagerState.ActivityDisplay display = displaySession
+ final ActivityManagerState.DisplayContent display = displaySession
.setPublicDisplay(true).setSimulateDisplay(true).createDisplay();
final int secondaryDisplayId = display.mId;
SecondaryActivity secondaryActivity = startActivity(SecondaryActivity.class,
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecycleTopResumedStateTests.java b/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecycleTopResumedStateTests.java
index 2c3985e..04b8966 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecycleTopResumedStateTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecycleTopResumedStateTests.java
@@ -746,7 +746,7 @@
try (final VirtualDisplaySession virtualDisplaySession = new VirtualDisplaySession()) {
// Create new simulated display
- final ActivityManagerState.ActivityDisplay newDisplay
+ final ActivityManagerState.DisplayContent newDisplay
= virtualDisplaySession.setSimulateDisplay(true).createDisplay();
// Launch another activity on new secondary display.
@@ -795,7 +795,7 @@
DEFAULT_DISPLAY, "Activity launched on default display must be focused");
// Create new simulated display
- final ActivityManagerState.ActivityDisplay newDisplay = createManagedVirtualDisplaySession()
+ final ActivityManagerState.DisplayContent newDisplay = createManagedVirtualDisplaySession()
.setSimulateDisplay(true)
.createDisplay();
@@ -845,7 +845,7 @@
assumeTrue(supportsMultiDisplay());
// Create new simulated display.
- final ActivityManagerState.ActivityDisplay newDisplay = createManagedVirtualDisplaySession()
+ final ActivityManagerState.DisplayContent newDisplay = createManagedVirtualDisplaySession()
.setSimulateDisplay(true)
.createDisplay();
@@ -914,7 +914,7 @@
assumeTrue(supportsMultiDisplay());
// Create new simulated display.
- final ActivityManagerState.ActivityDisplay newDisplay = createManagedVirtualDisplaySession()
+ final ActivityManagerState.DisplayContent newDisplay = createManagedVirtualDisplaySession()
.setSimulateDisplay(true)
.createDisplay();
@@ -989,7 +989,7 @@
DEFAULT_DISPLAY, "Activity launched on default display must be focused");
// Create new simulated display.
- final ActivityManagerState.ActivityDisplay newDisplay = createManagedVirtualDisplaySession()
+ final ActivityManagerState.DisplayContent newDisplay = createManagedVirtualDisplaySession()
.setSimulateDisplay(true)
.createDisplay();
@@ -1034,7 +1034,7 @@
DEFAULT_DISPLAY, "Activity launched on default display must be focused");
// Create new simulated display.
- final ActivityManagerState.ActivityDisplay newDisplay = createManagedVirtualDisplaySession()
+ final ActivityManagerState.DisplayContent newDisplay = createManagedVirtualDisplaySession()
.setSimulateDisplay(true)
.createDisplay();
diff --git a/tests/framework/base/windowmanager/util/src/android/server/wm/ActivityManagerState.java b/tests/framework/base/windowmanager/util/src/android/server/wm/ActivityManagerState.java
index 9449d71..dbdcc74 100644
--- a/tests/framework/base/windowmanager/util/src/android/server/wm/ActivityManagerState.java
+++ b/tests/framework/base/windowmanager/util/src/android/server/wm/ActivityManagerState.java
@@ -68,7 +68,7 @@
private static final String DUMPSYS_ACTIVITY_ACTIVITIES = "dumpsys activity --proto activities";
// Displays in z-order with the top most at the front of the list, starting with primary.
- private final List<ActivityDisplay> mDisplays = new ArrayList<>();
+ private final List<DisplayContent> mDisplays = new ArrayList<>();
// Stacks in z-order with the top most at the front of the list, starting with primary display.
private final List<ActivityStack> mStacks = new ArrayList<>();
private KeyguardControllerState mKeyguardControllerState;
@@ -160,7 +160,7 @@
.activityStackSupervisor;
for (int i = 0; i < state.displays.length; i++) {
ActivityDisplayProto activityDisplay = state.displays[i];
- mDisplays.add(new ActivityDisplay(activityDisplay, this));
+ mDisplays.add(new DisplayContent(activityDisplay, this));
}
mKeyguardControllerState = new KeyguardControllerState(state.keyguardController);
mTopFocusedStackId = state.focusedStackId;
@@ -196,8 +196,8 @@
return mIsHomeRecentsComponent;
}
- ActivityDisplay getDisplay(int displayId) {
- for (ActivityDisplay display : mDisplays) {
+ DisplayContent getDisplay(int displayId) {
+ for (DisplayContent display : mDisplays) {
if (display.mId == displayId) {
return display;
}
@@ -339,7 +339,7 @@
/** Get the stack position on its display. */
int getStackIndexByActivityType(int activityType) {
- for (ActivityDisplay display : mDisplays) {
+ for (DisplayContent display : mDisplays) {
for (int i = 0; i < display.mStacks.size(); i++) {
if (activityType == display.mStacks.get(i).getActivityType()) {
return i;
@@ -353,7 +353,7 @@
int getStackIndexByActivity(ComponentName activityName) {
final String fullName = getActivityName(activityName);
- for (ActivityDisplay display : mDisplays) {
+ for (DisplayContent display : mDisplays) {
for (int i = display.mStacks.size() - 1; i >= 0; --i) {
final ActivityStack stack = display.mStacks.get(i);
for (ActivityTask task : stack.mTasks) {
@@ -377,7 +377,7 @@
return getStackById(task.mStackId).mDisplayId;
}
- List<ActivityDisplay> getDisplays() {
+ List<DisplayContent> getDisplays() {
return new ArrayList<>(mDisplays);
}
@@ -641,7 +641,7 @@
return mPendingActivities.contains(getActivityName(activityName));
}
- public static class ActivityDisplay extends ActivityContainer {
+ public static class DisplayContent extends ActivityContainer {
public int mId;
ArrayList<ActivityStack> mStacks = new ArrayList<>();
@@ -649,7 +649,7 @@
String mResumedActivity;
boolean mSingleTaskInstance;
- ActivityDisplay(ActivityDisplayProto proto, ActivityManagerState amState) {
+ DisplayContent(ActivityDisplayProto proto, ActivityManagerState amState) {
super(proto.display.windowContainer.configurationContainer);
mId = proto.id;
mFocusedStackId = proto.focusedStackId;
diff --git a/tests/framework/base/windowmanager/util/src/android/server/wm/ActivityManagerTestBase.java b/tests/framework/base/windowmanager/util/src/android/server/wm/ActivityManagerTestBase.java
index 1318de2..d8eab7e 100644
--- a/tests/framework/base/windowmanager/util/src/android/server/wm/ActivityManagerTestBase.java
+++ b/tests/framework/base/windowmanager/util/src/android/server/wm/ActivityManagerTestBase.java
@@ -738,7 +738,7 @@
}
public void moveTaskToPrimarySplitScreen(int taskId) {
- moveTaskToPrimarySplitScreen(taskId, false /* showRecents */);
+ moveTaskToPrimarySplitScreen(taskId, false /* showSideActivity */);
}
/**
@@ -763,7 +763,8 @@
// Launch Placeholder Side Activity
final ComponentName sideActivityName =
new ComponentName(mContext, SideActivity.class);
- launchActivityNoWait(sideActivityName);
+ mContext.startActivity(new Intent().setComponent(sideActivityName)
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
mAmWmState.waitForActivityState(sideActivityName, STATE_RESUMED);
}
@@ -2189,7 +2190,10 @@
}
}
- // Activity used in place of recents when home is the recents component.
+ /**
+ * Activity used in place of recents when home is the recents component. It should only be used
+ * by {@link #moveTaskToPrimarySplitScreen}.
+ */
public static class SideActivity extends Activity {
}
}
diff --git a/tests/location/common/src/android/location/cts/common/BroadcastCapture.java b/tests/location/common/src/android/location/cts/common/BroadcastCapture.java
new file mode 100644
index 0000000..f2ea3ae
--- /dev/null
+++ b/tests/location/common/src/android/location/cts/common/BroadcastCapture.java
@@ -0,0 +1,64 @@
+/*
+ * 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 android.location.cts.common;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Looper;
+
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+
+public class BroadcastCapture extends BroadcastReceiver implements AutoCloseable {
+
+ protected final Context mContext;
+ private final LinkedBlockingQueue<Intent> mIntents;
+
+ public BroadcastCapture(Context context, String action) {
+ this(context);
+ register(action);
+ }
+
+ protected BroadcastCapture(Context context) {
+ mContext = context;
+ mIntents = new LinkedBlockingQueue<>();
+ }
+
+ protected void register(String action) {
+ mContext.registerReceiver(this, new IntentFilter(action));
+ }
+
+ public Intent getNextIntent(long timeoutMs) throws InterruptedException {
+ if (Looper.myLooper() == Looper.getMainLooper()) {
+ throw new AssertionError("getNextLocation() called from main thread");
+ }
+
+ return mIntents.poll(timeoutMs, TimeUnit.MILLISECONDS);
+ }
+
+ @Override
+ public void close() {
+ mContext.unregisterReceiver(this);
+ }
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ mIntents.add(intent);
+ }
+}
\ No newline at end of file
diff --git a/tests/location/common/src/android/location/cts/common/LocationPendingIntentCapture.java b/tests/location/common/src/android/location/cts/common/LocationPendingIntentCapture.java
index 22432dc..5afb7b3 100644
--- a/tests/location/common/src/android/location/cts/common/LocationPendingIntentCapture.java
+++ b/tests/location/common/src/android/location/cts/common/LocationPendingIntentCapture.java
@@ -32,19 +32,19 @@
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
-public class LocationPendingIntentCapture extends BroadcastReceiver implements AutoCloseable {
+public class LocationPendingIntentCapture extends BroadcastCapture {
private static final String ACTION = "android.location.cts.LOCATION_BROADCAST";
private static final AtomicInteger sRequestCode = new AtomicInteger(0);
- private final Context mContext;
private final LocationManager mLocationManager;
private final PendingIntent mPendingIntent;
private final LinkedBlockingQueue<Location> mLocations;
private final LinkedBlockingQueue<Boolean> mProviderChanges;
public LocationPendingIntentCapture(Context context) {
- mContext = context;
+ super(context);
+
mLocationManager = context.getSystemService(LocationManager.class);
mPendingIntent = PendingIntent.getBroadcast(context, sRequestCode.getAndIncrement(),
new Intent(ACTION).setPackage(context.getPackageName()),
@@ -52,7 +52,7 @@
mLocations = new LinkedBlockingQueue<>();
mProviderChanges = new LinkedBlockingQueue<>();
- context.registerReceiver(this, new IntentFilter(ACTION));
+ register(ACTION);
}
public PendingIntent getPendingIntent() {
@@ -77,13 +77,14 @@
@Override
public void close() {
+ super.close();
mLocationManager.removeUpdates(mPendingIntent);
- mContext.unregisterReceiver(this);
mPendingIntent.cancel();
}
@Override
public void onReceive(Context context, Intent intent) {
+ super.onReceive(context, intent);
if (intent.hasExtra(KEY_PROVIDER_ENABLED)) {
mProviderChanges.add(intent.getBooleanExtra(KEY_PROVIDER_ENABLED, false));
} else if (intent.hasExtra(KEY_LOCATION_CHANGED)) {
diff --git a/tests/location/common/src/android/location/cts/common/ProximityPendingIntentCapture.java b/tests/location/common/src/android/location/cts/common/ProximityPendingIntentCapture.java
index c8f1c06..75e4e39 100644
--- a/tests/location/common/src/android/location/cts/common/ProximityPendingIntentCapture.java
+++ b/tests/location/common/src/android/location/cts/common/ProximityPendingIntentCapture.java
@@ -14,25 +14,25 @@
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
-public class ProximityPendingIntentCapture extends BroadcastReceiver implements AutoCloseable {
+public class ProximityPendingIntentCapture extends BroadcastCapture {
private static final String ACTION = "android.location.cts.LOCATION_BROADCAST";
private static final AtomicInteger sRequestCode = new AtomicInteger(0);
- private final Context mContext;
private final LocationManager mLocationManager;
private final PendingIntent mPendingIntent;
private final LinkedBlockingQueue<Boolean> mProximityChanges;
public ProximityPendingIntentCapture(Context context) {
- mContext = context;
+ super(context);
+
mLocationManager = context.getSystemService(LocationManager.class);
mPendingIntent = PendingIntent.getBroadcast(context, sRequestCode.getAndIncrement(),
new Intent(ACTION).setPackage(context.getPackageName()),
PendingIntent.FLAG_CANCEL_CURRENT);
mProximityChanges = new LinkedBlockingQueue<>();
- context.registerReceiver(this, new IntentFilter(ACTION));
+ register(ACTION);
}
public PendingIntent getPendingIntent() {
@@ -49,13 +49,14 @@
@Override
public void close() {
+ super.close();
mLocationManager.removeProximityAlert(mPendingIntent);
- mContext.unregisterReceiver(this);
mPendingIntent.cancel();
}
@Override
public void onReceive(Context context, Intent intent) {
+ super.onReceive(context, intent);
if (intent.hasExtra(KEY_PROXIMITY_ENTERING)) {
mProximityChanges.add(intent.getBooleanExtra(KEY_PROXIMITY_ENTERING, false));
}
diff --git a/tests/location/location_fine/src/android/location/cts/fine/LocationManagerFineTest.java b/tests/location/location_fine/src/android/location/cts/fine/LocationManagerFineTest.java
index c57107d..c147cfd 100644
--- a/tests/location/location_fine/src/android/location/cts/fine/LocationManagerFineTest.java
+++ b/tests/location/location_fine/src/android/location/cts/fine/LocationManagerFineTest.java
@@ -16,22 +16,21 @@
package android.location.cts.fine;
+import static android.location.LocationManager.EXTRA_PROVIDER_ENABLED;
+import static android.location.LocationManager.EXTRA_PROVIDER_NAME;
import static android.location.LocationManager.FUSED_PROVIDER;
import static android.location.LocationManager.GPS_PROVIDER;
import static android.location.LocationManager.NETWORK_PROVIDER;
import static android.location.LocationManager.PASSIVE_PROVIDER;
+import static android.location.LocationManager.PROVIDERS_CHANGED_ACTION;
+import static androidx.test.ext.truth.content.IntentSubject.assertThat;
import static androidx.test.ext.truth.location.LocationSubject.assertThat;
import static com.android.compatibility.common.util.LocationUtils.createLocation;
import static com.google.common.truth.Truth.assertThat;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotEquals;
-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.PendingIntent;
@@ -50,6 +49,7 @@
import android.location.LocationProvider;
import android.location.LocationRequest;
import android.location.OnNmeaMessageListener;
+import android.location.cts.common.BroadcastCapture;
import android.location.cts.common.GetCurrentLocationCapture;
import android.location.cts.common.LocationListenerCapture;
import android.location.cts.common.LocationPendingIntentCapture;
@@ -74,6 +74,7 @@
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.util.HashSet;
import java.util.List;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
@@ -106,7 +107,7 @@
mContext = ApplicationProvider.getApplicationContext();
mManager = mContext.getSystemService(LocationManager.class);
- assertNotNull(mManager);
+ assertThat(mManager).isNotNull();
for (String provider : mManager.getAllProviders()) {
mManager.removeTestProvider(provider);
@@ -137,7 +138,7 @@
@Test
public void testIsLocationEnabled() {
- assertTrue(mManager.isLocationEnabled());
+ assertThat(mManager.isLocationEnabled()).isTrue();
}
@Test
@@ -150,13 +151,13 @@
@Test
public void testIsProviderEnabled() {
- assertTrue(mManager.isProviderEnabled(TEST_PROVIDER));
+ assertThat(mManager.isProviderEnabled(TEST_PROVIDER)).isTrue();
mManager.setTestProviderEnabled(TEST_PROVIDER, false);
- assertFalse(mManager.isProviderEnabled(TEST_PROVIDER));
+ assertThat(mManager.isProviderEnabled(TEST_PROVIDER)).isFalse();
mManager.setTestProviderEnabled(TEST_PROVIDER, true);
- assertTrue(mManager.isProviderEnabled(TEST_PROVIDER));
+ assertThat(mManager.isProviderEnabled(TEST_PROVIDER)).isTrue();
try {
mManager.isProviderEnabled(null);
@@ -178,7 +179,7 @@
assertThat(mManager.getLastKnownLocation(TEST_PROVIDER)).isEqualTo(loc2);
mManager.setTestProviderEnabled(TEST_PROVIDER, false);
- assertNull(mManager.getLastKnownLocation(TEST_PROVIDER));
+ assertThat(mManager.getLastKnownLocation(TEST_PROVIDER)).isNull();
try {
mManager.getLastKnownLocation(null);
@@ -226,10 +227,10 @@
try (GetCurrentLocationCapture capture = new GetCurrentLocationCapture()) {
mManager.getCurrentLocation(TEST_PROVIDER, capture.getCancellationSignal(),
- Runnable::run, capture);
+ Executors.newSingleThreadExecutor(), capture);
capture.getCancellationSignal().cancel();
mManager.setTestProviderLocation(TEST_PROVIDER, loc);
- assertFalse(capture.hasLocation(FAILURE_TIMEOUT_MS));
+ assertThat(capture.hasLocation(FAILURE_TIMEOUT_MS)).isFalse();
}
}
@@ -238,15 +239,15 @@
try (GetCurrentLocationCapture capture = new GetCurrentLocationCapture()) {
mManager.setTestProviderEnabled(TEST_PROVIDER, false);
mManager.getCurrentLocation(TEST_PROVIDER, capture.getCancellationSignal(),
- Runnable::run, capture);
- assertNull(capture.getLocation(FAILURE_TIMEOUT_MS));
+ Executors.newSingleThreadExecutor(), capture);
+ assertThat(capture.getLocation(FAILURE_TIMEOUT_MS)).isNull();
}
try (GetCurrentLocationCapture capture = new GetCurrentLocationCapture()) {
mManager.getCurrentLocation(TEST_PROVIDER, capture.getCancellationSignal(),
- Runnable::run, capture);
+ Executors.newSingleThreadExecutor(), capture);
mManager.setTestProviderEnabled(TEST_PROVIDER, false);
- assertNull(capture.getLocation(FAILURE_TIMEOUT_MS));
+ assertThat(capture.getLocation(FAILURE_TIMEOUT_MS)).isNull();
}
}
@@ -271,11 +272,11 @@
mManager.removeUpdates(capture);
mManager.setTestProviderLocation(TEST_PROVIDER, loc1);
- assertNull(capture.getNextLocation(FAILURE_TIMEOUT_MS));
+ assertThat(capture.getNextLocation(FAILURE_TIMEOUT_MS)).isNull();
mManager.setTestProviderEnabled(TEST_PROVIDER, false);
- assertNull(capture.getNextProviderChange(FAILURE_TIMEOUT_MS));
+ assertThat(capture.getNextProviderChange(FAILURE_TIMEOUT_MS)).isNull();
mManager.setTestProviderEnabled(TEST_PROVIDER, true);
- assertNull(capture.getNextProviderChange(FAILURE_TIMEOUT_MS));
+ assertThat(capture.getNextProviderChange(FAILURE_TIMEOUT_MS)).isNull();
}
try {
@@ -327,11 +328,11 @@
mManager.removeUpdates(capture.getPendingIntent());
mManager.setTestProviderLocation(TEST_PROVIDER, loc1);
- assertNull(capture.getNextLocation(FAILURE_TIMEOUT_MS));
+ assertThat(capture.getNextLocation(FAILURE_TIMEOUT_MS)).isNull();
mManager.setTestProviderEnabled(TEST_PROVIDER, false);
- assertNull(capture.getNextProviderChange(FAILURE_TIMEOUT_MS));
+ assertThat(capture.getNextProviderChange(FAILURE_TIMEOUT_MS)).isNull();
mManager.setTestProviderEnabled(TEST_PROVIDER, true);
- assertNull(capture.getNextProviderChange(FAILURE_TIMEOUT_MS));
+ assertThat(capture.getNextProviderChange(FAILURE_TIMEOUT_MS)).isNull();
}
try {
@@ -426,7 +427,7 @@
Location loc2 = createLocation(FUSED_PROVIDER, mRandom);
try (LocationListenerCapture capture = new LocationListenerCapture(mContext)) {
- mManager.requestLocationUpdates(0, 0, criteria, Runnable::run, capture);
+ mManager.requestLocationUpdates(0, 0, criteria, Executors.newSingleThreadExecutor(), capture);
mManager.setTestProviderLocation(FUSED_PROVIDER, loc1);
assertThat(capture.getNextLocation(TIMEOUT_MS)).isEqualTo(loc1);
@@ -440,11 +441,11 @@
mManager.removeUpdates(capture);
mManager.setTestProviderLocation(FUSED_PROVIDER, loc1);
- assertNull(capture.getNextLocation(FAILURE_TIMEOUT_MS));
+ assertThat(capture.getNextLocation(FAILURE_TIMEOUT_MS)).isNull();
mManager.setTestProviderEnabled(FUSED_PROVIDER, false);
- assertNull(capture.getNextProviderChange(FAILURE_TIMEOUT_MS));
+ assertThat(capture.getNextProviderChange(FAILURE_TIMEOUT_MS)).isNull();
mManager.setTestProviderEnabled(FUSED_PROVIDER, true);
- assertNull(capture.getNextProviderChange(FAILURE_TIMEOUT_MS));
+ assertThat(capture.getNextProviderChange(FAILURE_TIMEOUT_MS)).isNull();
}
@@ -463,7 +464,7 @@
}
try (LocationListenerCapture capture = new LocationListenerCapture(mContext)) {
- mManager.requestLocationUpdates(0, 0, null, Runnable::run, capture);
+ mManager.requestLocationUpdates(0, 0, null, Executors.newSingleThreadExecutor(), capture);
fail("Should throw IllegalArgumentException if criteria is null!");
} catch (IllegalArgumentException e) {
// expected
@@ -476,8 +477,8 @@
Location loc2 = createLocation(TEST_PROVIDER, mRandom);
try (LocationListenerCapture capture = new LocationListenerCapture(mContext)) {
- mManager.requestLocationUpdates(TEST_PROVIDER, 1000, 1000, Runnable::run, capture);
- mManager.requestLocationUpdates(TEST_PROVIDER, 0, 0, Runnable::run, capture);
+ mManager.requestLocationUpdates(TEST_PROVIDER, 1000, 1000, (runnable) -> {}, capture);
+ mManager.requestLocationUpdates(TEST_PROVIDER, 0, 0, Executors.newSingleThreadExecutor(), capture);
mManager.setTestProviderLocation(TEST_PROVIDER, loc1);
assertThat(capture.getNextLocation(TIMEOUT_MS)).isEqualTo(loc1);
@@ -496,12 +497,12 @@
request.setNumUpdates(1);
try (LocationListenerCapture capture = new LocationListenerCapture(mContext)) {
- mManager.requestLocationUpdates(request, Runnable::run, capture);
+ mManager.requestLocationUpdates(request, Executors.newSingleThreadExecutor(), capture);
mManager.setTestProviderLocation(TEST_PROVIDER, loc1);
assertThat(capture.getNextLocation(TIMEOUT_MS)).isEqualTo(loc1);
mManager.setTestProviderLocation(TEST_PROVIDER, loc2);
- assertNull(capture.getNextLocation(FAILURE_TIMEOUT_MS));
+ assertThat(capture.getNextLocation(FAILURE_TIMEOUT_MS)).isNull();
}
}
@@ -514,12 +515,12 @@
0, false);
try (LocationListenerCapture capture = new LocationListenerCapture(mContext)) {
- mManager.requestLocationUpdates(request, Runnable::run, capture);
+ mManager.requestLocationUpdates(request, Executors.newSingleThreadExecutor(), capture);
mManager.setTestProviderLocation(TEST_PROVIDER, loc1);
assertThat(capture.getNextLocation(TIMEOUT_MS)).isEqualTo(loc1);
mManager.setTestProviderLocation(TEST_PROVIDER, loc2);
- assertNull(capture.getNextLocation(FAILURE_TIMEOUT_MS));
+ assertThat(capture.getNextLocation(FAILURE_TIMEOUT_MS)).isNull();
}
}
@@ -532,12 +533,12 @@
200000, false);
try (LocationListenerCapture capture = new LocationListenerCapture(mContext)) {
- mManager.requestLocationUpdates(request, Runnable::run, capture);
+ mManager.requestLocationUpdates(request, Executors.newSingleThreadExecutor(), capture);
mManager.setTestProviderLocation(TEST_PROVIDER, loc1);
assertThat(capture.getNextLocation(TIMEOUT_MS)).isEqualTo(loc1);
mManager.setTestProviderLocation(TEST_PROVIDER, loc2);
- assertNull(capture.getNextLocation(FAILURE_TIMEOUT_MS));
+ assertThat(capture.getNextLocation(FAILURE_TIMEOUT_MS)).isNull();
}
}
@@ -546,7 +547,7 @@
public void testRequestGpsUpdates_B9758659() throws Exception {
// test for b/9758659, where the gps provider may reuse network provider positions creating
// an unnatural feedback loop
- assertTrue(mManager.isProviderEnabled(GPS_PROVIDER));
+ assertThat(mManager.isProviderEnabled(GPS_PROVIDER)).isTrue();
Location networkLocation = createLocation(NETWORK_PROVIDER, mRandom);
@@ -568,7 +569,7 @@
LocationRequest request = LocationRequest.createFromDeprecatedProvider(GPS_PROVIDER, 0, 0, false);
try (LocationListenerCapture capture = new LocationListenerCapture(mContext)) {
- mManager.requestLocationUpdates(request, Runnable::run, capture);
+ mManager.requestLocationUpdates(request, Executors.newSingleThreadExecutor(), capture);
Location location = capture.getNextLocation(TIMEOUT_MS);
if (location != null) {
@@ -578,36 +579,91 @@
}
@Test
+ public void testListenProviderEnable_Listener() throws Exception {
+ try (LocationListenerCapture capture = new LocationListenerCapture(mContext)) {
+ mManager.requestLocationUpdates(TEST_PROVIDER, 0, 0,
+ Executors.newSingleThreadExecutor(), capture);
+
+ mManager.setTestProviderEnabled(TEST_PROVIDER, false);
+ assertThat(capture.getNextProviderChange(TIMEOUT_MS)).isEqualTo(false);
+ mManager.setTestProviderEnabled(TEST_PROVIDER, true);
+ assertThat(capture.getNextProviderChange(TIMEOUT_MS)).isEqualTo(true);
+
+ mManager.removeUpdates(capture);
+
+ mManager.setTestProviderEnabled(TEST_PROVIDER, false);
+ assertThat(capture.getNextLocation(FAILURE_TIMEOUT_MS)).isNull();
+ }
+ }
+
+ @Test
+ public void testListenProviderEnable_PendingIntent() throws Exception {
+ try (LocationPendingIntentCapture capture = new LocationPendingIntentCapture(mContext)) {
+ mManager.requestLocationUpdates(TEST_PROVIDER, 0, 0, capture.getPendingIntent());
+
+ mManager.setTestProviderEnabled(TEST_PROVIDER, false);
+ assertThat(capture.getNextProviderChange(TIMEOUT_MS)).isEqualTo(false);
+ mManager.setTestProviderEnabled(TEST_PROVIDER, true);
+ assertThat(capture.getNextProviderChange(TIMEOUT_MS)).isEqualTo(true);
+
+ mManager.removeUpdates(capture.getPendingIntent());
+
+ mManager.setTestProviderEnabled(TEST_PROVIDER, false);
+ assertThat(capture.getNextLocation(FAILURE_TIMEOUT_MS)).isNull();
+ }
+ }
+
+ @Test
+ public void testListenProviderEnable_Broadcast() throws Exception {
+ try (BroadcastCapture capture = new BroadcastCapture(mContext, PROVIDERS_CHANGED_ACTION)) {
+ mManager.setTestProviderEnabled(TEST_PROVIDER, false);
+ Intent broadcast = capture.getNextIntent(TIMEOUT_MS);
+ assertThat(broadcast).isNotNull();
+ assertThat(broadcast).hasAction(PROVIDERS_CHANGED_ACTION);
+ assertThat(broadcast).extras().string(EXTRA_PROVIDER_NAME).isEqualTo(TEST_PROVIDER);
+ assertThat(broadcast).extras().bool(EXTRA_PROVIDER_ENABLED).isFalse();
+
+ mManager.setTestProviderEnabled(TEST_PROVIDER, true);
+ broadcast = capture.getNextIntent(TIMEOUT_MS);
+ assertThat(broadcast).isNotNull();
+ assertThat(broadcast).hasAction(PROVIDERS_CHANGED_ACTION);
+ assertThat(broadcast).extras().string(EXTRA_PROVIDER_NAME).isEqualTo(TEST_PROVIDER);
+ assertThat(broadcast).extras().bool(EXTRA_PROVIDER_ENABLED).isTrue();
+ }
+ }
+
+ @Test
public void testGetAllProviders() {
List<String> providers = mManager.getAllProviders();
if (hasGpsFeature()) {
- assertTrue(providers.contains(LocationManager.GPS_PROVIDER));
+ assertThat(providers.contains(LocationManager.GPS_PROVIDER)).isTrue();
}
- assertTrue(providers.contains(PASSIVE_PROVIDER));
- assertTrue(providers.contains(TEST_PROVIDER));
+ assertThat(providers.contains(PASSIVE_PROVIDER)).isTrue();
+ assertThat(providers.contains(TEST_PROVIDER)).isTrue();
+ assertThat(providers.size()).isEqualTo(new HashSet<>(providers).size());
mManager.removeTestProvider(TEST_PROVIDER);
providers = mManager.getAllProviders();
- assertTrue(providers.contains(PASSIVE_PROVIDER));
- assertFalse(providers.contains(TEST_PROVIDER));
+ assertThat(providers.contains(PASSIVE_PROVIDER)).isTrue();
+ assertThat(providers.contains(TEST_PROVIDER)).isFalse();
}
@Test
public void testGetProviders() throws Exception {
List<String> providers = mManager.getProviders(false);
- assertTrue(providers.contains(TEST_PROVIDER));
+ assertThat(providers.contains(TEST_PROVIDER)).isTrue();
providers = mManager.getProviders(true);
- assertTrue(providers.contains(TEST_PROVIDER));
+ assertThat(providers.contains(TEST_PROVIDER)).isTrue();
setTestProviderEnabled(TEST_PROVIDER, false);
providers = mManager.getProviders(false);
- assertTrue(providers.contains(TEST_PROVIDER));
+ assertThat(providers.contains(TEST_PROVIDER)).isTrue();
providers = mManager.getProviders(true);
- assertFalse(providers.contains(TEST_PROVIDER));
+ assertThat(providers.contains(TEST_PROVIDER)).isFalse();
}
@Test
@@ -615,18 +671,18 @@
Criteria criteria = new Criteria();
List<String> providers = mManager.getProviders(criteria, false);
- assertTrue(providers.contains(TEST_PROVIDER));
+ assertThat(providers.contains(TEST_PROVIDER)).isTrue();
providers = mManager.getProviders(criteria, true);
- assertTrue(providers.contains(TEST_PROVIDER));
+ assertThat(providers.contains(TEST_PROVIDER)).isTrue();
criteria.setPowerRequirement(Criteria.POWER_LOW);
providers = mManager.getProviders(criteria, false);
- assertFalse(providers.contains(TEST_PROVIDER));
+ assertThat(providers.contains(TEST_PROVIDER)).isFalse();
providers = mManager.getProviders(criteria, true);
- assertFalse(providers.contains(TEST_PROVIDER));
+ assertThat(providers.contains(TEST_PROVIDER)).isFalse();
}
@Test
@@ -661,21 +717,21 @@
assertThat(mManager.getBestProvider(criteria, false)).isEqualTo(TEST_PROVIDER);
setTestProviderEnabled(TEST_PROVIDER, false);
- assertNotEquals(TEST_PROVIDER, mManager.getBestProvider(criteria, true));
+ assertThat(mManager.getBestProvider(criteria, true)).isNotEqualTo(TEST_PROVIDER);
}
@Test
public void testGetProvider() {
LocationProvider provider = mManager.getProvider(TEST_PROVIDER);
- assertNotNull(provider);
+ assertThat(provider).isNotNull();
assertThat(provider.getName()).isEqualTo(TEST_PROVIDER);
provider = mManager.getProvider(LocationManager.GPS_PROVIDER);
if (hasGpsFeature()) {
- assertNotNull(provider);
+ assertThat(provider).isNotNull();
assertThat(provider.getName()).isEqualTo(LocationManager.GPS_PROVIDER);
} else {
- assertNull(provider);
+ assertThat(provider).isNull();
}
try {
@@ -691,7 +747,7 @@
public void testSendExtraCommand() {
for (String provider : mManager.getAllProviders()) {
boolean res = mManager.sendExtraCommand(provider, "dontCrash", null);
- assertTrue(res);
+ assertThat(res).isTrue();
try {
mManager.sendExtraCommand(provider, null, null);
@@ -763,25 +819,62 @@
}
@Test
+ public void testSetTestProviderEnabled() {
+ for (String provider : mManager.getAllProviders()) {
+ if (TEST_PROVIDER.equals(provider)) {
+ mManager.setTestProviderEnabled(provider, false);
+ assertThat(mManager.isProviderEnabled(provider)).isFalse();
+ mManager.setTestProviderEnabled(provider, true);
+ assertThat(mManager.isProviderEnabled(provider)).isTrue();
+ } else {
+ try {
+ mManager.setTestProviderEnabled(provider, false);
+ fail("Should throw IllegalArgumentException since " + provider
+ + " is not a test provider!");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+ }
+
+ mManager.removeTestProvider(TEST_PROVIDER);
+ try {
+ mManager.setTestProviderEnabled(TEST_PROVIDER, false);
+ fail("Should throw IllegalArgumentException since " + TEST_PROVIDER
+ + " is not a test provider!");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ try {
+ mManager.setTestProviderEnabled(null, false);
+ fail("Should throw IllegalArgumentException since provider is null!");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+
+ @Test
public void testSetTestProviderLocation() throws Exception {
Location loc1 = createLocation(TEST_PROVIDER, mRandom);
Location loc2 = createLocation(TEST_PROVIDER, mRandom);
for (String provider : mManager.getAllProviders()) {
if (TEST_PROVIDER.equals(provider)) {
- try (GetCurrentLocationCapture capture = new GetCurrentLocationCapture()) {
- mManager.getCurrentLocation(provider, capture.getCancellationSignal(),
- Runnable::run, capture);
+ try (LocationListenerCapture capture = new LocationListenerCapture(mContext)) {
+ mManager.requestLocationUpdates(TEST_PROVIDER, 0, 0,
+ Executors.newSingleThreadExecutor(), capture);
mManager.setTestProviderLocation(provider, loc1);
- Location received = capture.getLocation(TIMEOUT_MS);
+ Location received = capture.getNextLocation(TIMEOUT_MS);
assertThat(received).isEqualTo(loc1);
- assertTrue(received.isFromMockProvider());
+ assertThat(received.isFromMockProvider()).isTrue();
assertThat(mManager.getLastKnownLocation(provider)).isEqualTo(loc1);
setTestProviderEnabled(provider, false);
mManager.setTestProviderLocation(provider, loc2);
- assertNull(mManager.getLastKnownLocation(provider));
+ assertThat(mManager.getLastKnownLocation(provider)).isNull();
+ assertThat(capture.getNextLocation(FAILURE_TIMEOUT_MS)).isNull();
}
} else {
try {
@@ -827,8 +920,8 @@
if (providers.size() <= 2) {
// can't perform the test without any real providers, and no need to do so since there
// are no providers a malicious app could fool
- assertTrue(providers.contains(TEST_PROVIDER));
- assertTrue(providers.contains(PASSIVE_PROVIDER));
+ assertThat(providers.contains(TEST_PROVIDER)).isTrue();
+ assertThat(providers.contains(PASSIVE_PROVIDER)).isTrue();
return;
}
@@ -840,12 +933,12 @@
try (GetCurrentLocationCapture capture = new GetCurrentLocationCapture()) {
mManager.getCurrentLocation(TEST_PROVIDER, capture.getCancellationSignal(),
- Runnable::run, capture);
+ Executors.newSingleThreadExecutor(), capture);
mManager.setTestProviderLocation(TEST_PROVIDER, loc);
Location received = capture.getLocation(TIMEOUT_MS);
assertThat(received).isEqualTo(loc);
- assertTrue(received.isFromMockProvider());
+ assertThat(received.isFromMockProvider()).isTrue();
Location realProvideLocation = mManager.getLastKnownLocation(realProvider);
if (realProvideLocation != null) {
@@ -987,7 +1080,7 @@
Thread.sleep(500);
mManager.setTestProviderLocation(FUSED_PROVIDER, createLocation(FUSED_PROVIDER, 0, 0, 10));
- assertNull(capture.getNextProximityChange(FAILURE_TIMEOUT_MS));
+ assertThat(capture.getNextProximityChange(FAILURE_TIMEOUT_MS)).isNull();
}
}
@@ -1008,7 +1101,7 @@
GnssStatus.Callback callback = new GnssStatus.Callback() {
};
- mManager.registerGnssStatusCallback(Runnable::run, callback);
+ mManager.registerGnssStatusCallback(Executors.newSingleThreadExecutor(), callback);
mManager.unregisterGnssStatusCallback(callback);
}
@@ -1017,7 +1110,7 @@
OnNmeaMessageListener listener = (message, timestamp) -> {
};
- mManager.addNmeaListener(Runnable::run, listener);
+ mManager.addNmeaListener(Executors.newSingleThreadExecutor(), listener);
mManager.removeNmeaListener(listener);
}
@@ -1026,7 +1119,7 @@
GnssMeasurementsEvent.Callback callback = new GnssMeasurementsEvent.Callback() {
};
- mManager.registerGnssMeasurementsCallback(Runnable::run, callback);
+ mManager.registerGnssMeasurementsCallback(Executors.newSingleThreadExecutor(), callback);
mManager.unregisterGnssMeasurementsCallback(callback);
}
@@ -1035,7 +1128,7 @@
GnssNavigationMessage.Callback callback = new GnssNavigationMessage.Callback() {
};
- mManager.registerGnssNavigationMessageCallback(Runnable::run, callback);
+ mManager.registerGnssNavigationMessageCallback(Executors.newSingleThreadExecutor(), callback);
mManager.unregisterGnssNavigationMessageCallback(callback);
}
@@ -1060,7 +1153,7 @@
}
};
mContext.registerReceiver(receiver,
- new IntentFilter(LocationManager.PROVIDERS_CHANGED_ACTION));
+ new IntentFilter(PROVIDERS_CHANGED_ACTION));
mManager.setTestProviderEnabled(provider, enabled);
// it's ok if this times out, as we don't notify for noop changes
diff --git a/tests/location/location_gnss/src/android/location/cts/gnss/asn1/base/Asn1BMPString.java b/tests/location/location_gnss/src/android/location/cts/gnss/asn1/base/Asn1BMPString.java
index 417fa37..2d74aa6 100644
--- a/tests/location/location_gnss/src/android/location/cts/gnss/asn1/base/Asn1BMPString.java
+++ b/tests/location/location_gnss/src/android/location/cts/gnss/asn1/base/Asn1BMPString.java
@@ -23,6 +23,7 @@
import java.nio.ByteBuffer;
import java.util.Collection;
+import java.util.Objects;
/**
* A BMP string is a string from the Basic Multilingual Plane of Unicode, i.e.
@@ -76,7 +77,7 @@
}
private Iterable<BitStream> encodePerImpl(boolean aligned) {
- Preconditions.checkNotNull(value, "No value set.");
+ Objects.requireNonNull(value, "No value set.");
int length = Character.codePointCount(value, 0, value.length());
Preconditions.checkState(length >= minimumSize, "Value too short.");
Preconditions.checkState(maximumSize == null || length <= maximumSize,
diff --git a/tests/location/location_gnss/src/android/location/cts/gnss/asn1/base/Asn1BitString.java b/tests/location/location_gnss/src/android/location/cts/gnss/asn1/base/Asn1BitString.java
index dcf50d7..a5265ef 100644
--- a/tests/location/location_gnss/src/android/location/cts/gnss/asn1/base/Asn1BitString.java
+++ b/tests/location/location_gnss/src/android/location/cts/gnss/asn1/base/Asn1BitString.java
@@ -24,6 +24,7 @@
import java.nio.ByteBuffer;
import java.util.BitSet;
import java.util.Collection;
+import java.util.Objects;
/**
* Implements ASN.1 functionality.
@@ -65,13 +66,13 @@
}
@Override int getBerValueLength() {
- Preconditions.checkNotNull(value, "No value set.");
+ Objects.requireNonNull(value, "No value set.");
// the +1 is for the extra leading octet indicating the number of unused bits in last octet
return (value.length() + 7) / 8 + 1;
}
@Override void encodeBerValue(ByteBuffer buf) {
- Preconditions.checkNotNull(value, "No value set.");
+ Objects.requireNonNull(value, "No value set.");
Preconditions.checkState(
maximumSize == null || value.length() <= maximumSize, "Too large %s",
value.length());
@@ -98,7 +99,7 @@
}
private Iterable<BitStream> encodePerImpl(boolean aligned) {
- Preconditions.checkNotNull(value, "No value set.");
+ Objects.requireNonNull(value, "No value set.");
Preconditions.checkState(
maximumSize == null || value.length() <= maximumSize, "Too large %s",
value.length());
diff --git a/tests/location/location_gnss/src/android/location/cts/gnss/asn1/base/Asn1Enumerated.java b/tests/location/location_gnss/src/android/location/cts/gnss/asn1/base/Asn1Enumerated.java
index d39bb39..5e16c69 100644
--- a/tests/location/location_gnss/src/android/location/cts/gnss/asn1/base/Asn1Enumerated.java
+++ b/tests/location/location_gnss/src/android/location/cts/gnss/asn1/base/Asn1Enumerated.java
@@ -16,12 +16,12 @@
package android.location.cts.asn1.base;
-import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.util.Collection;
+import java.util.Objects;
/**
*/
@@ -85,7 +85,7 @@
}
private Asn1Integer asAsn1Integer() {
- Preconditions.checkNotNull(value, "No value set.");
+ Objects.requireNonNull(value, "No value set.");
Asn1Integer ai = new Asn1Integer();
ai.setInteger(BigInteger.valueOf(value.getAssignedValue()));
return ai;
diff --git a/tests/location/location_gnss/src/android/location/cts/gnss/asn1/base/Asn1GeneralString.java b/tests/location/location_gnss/src/android/location/cts/gnss/asn1/base/Asn1GeneralString.java
index 29b874b..4f0159a 100644
--- a/tests/location/location_gnss/src/android/location/cts/gnss/asn1/base/Asn1GeneralString.java
+++ b/tests/location/location_gnss/src/android/location/cts/gnss/asn1/base/Asn1GeneralString.java
@@ -23,6 +23,7 @@
import java.nio.ByteBuffer;
import java.util.Collection;
+import java.util.Objects;
/**
* A general string is any ISO 646 related 8-bit encoding, presumably agreed on
@@ -75,7 +76,7 @@
}
private Iterable<BitStream> encodePerImpl(boolean aligned) {
- Preconditions.checkNotNull(value, "No value set.");
+ Objects.requireNonNull(value, "No value set.");
Preconditions.checkState(value.length >= minimumSize, "Value too short.");
Preconditions.checkState(maximumSize == null || value.length <= maximumSize,
"Value too long.");
diff --git a/tests/location/location_gnss/src/android/location/cts/gnss/asn1/base/Asn1IA5String.java b/tests/location/location_gnss/src/android/location/cts/gnss/asn1/base/Asn1IA5String.java
index 0c2da9c..dff4822 100644
--- a/tests/location/location_gnss/src/android/location/cts/gnss/asn1/base/Asn1IA5String.java
+++ b/tests/location/location_gnss/src/android/location/cts/gnss/asn1/base/Asn1IA5String.java
@@ -31,6 +31,7 @@
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Collection;
+import java.util.Objects;
/**
* Represents strings in 7-bit US ASCII (actually pages 1 and 6 of ISO
@@ -58,12 +59,12 @@
}
@Override int getBerValueLength() {
- Preconditions.checkNotNull(value, "No value set.");
+ Objects.requireNonNull(value, "No value set.");
return value.length();
}
@Override void encodeBerValue(ByteBuffer buf) {
- Preconditions.checkNotNull(value, "No value set.");
+ Objects.requireNonNull(value, "No value set.");
buf.put(value.getBytes(StandardCharsets.US_ASCII));
}
@@ -72,7 +73,7 @@
}
protected void setAlphabet(String alphabet) {
- Preconditions.checkNotNull(alphabet);
+ Objects.requireNonNull(alphabet);
Preconditions.checkArgument(alphabet.length() > 0, "Empty alphabet");
try {
ByteBuffer buffer = StandardCharsets.US_ASCII.newEncoder().encode(CharBuffer.wrap(alphabet));
@@ -113,7 +114,7 @@
}
private Iterable<BitStream> encodePerImpl(boolean aligned) {
- Preconditions.checkNotNull(value, "No value set.");
+ Objects.requireNonNull(value, "No value set.");
int characterBitCount = calculateBitsPerCharacter(aligned);
diff --git a/tests/location/location_gnss/src/android/location/cts/gnss/asn1/base/Asn1Integer.java b/tests/location/location_gnss/src/android/location/cts/gnss/asn1/base/Asn1Integer.java
index 9b29c98..921d2d3 100644
--- a/tests/location/location_gnss/src/android/location/cts/gnss/asn1/base/Asn1Integer.java
+++ b/tests/location/location_gnss/src/android/location/cts/gnss/asn1/base/Asn1Integer.java
@@ -24,6 +24,7 @@
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.util.Collection;
+import java.util.Objects;
import javax.annotation.Nullable;
@@ -79,7 +80,7 @@
}
private void validateValue() {
- Preconditions.checkNotNull(value, "No value set.");
+ Objects.requireNonNull(value, "No value set.");
Preconditions.checkState(
minimumValue == null || value.compareTo(minimumValue) >= 0,
"Too small value %s", value);
diff --git a/tests/location/location_gnss/src/android/location/cts/gnss/asn1/base/Asn1ObjectIdentifier.java b/tests/location/location_gnss/src/android/location/cts/gnss/asn1/base/Asn1ObjectIdentifier.java
index 946b9a4..0ddfc59 100644
--- a/tests/location/location_gnss/src/android/location/cts/gnss/asn1/base/Asn1ObjectIdentifier.java
+++ b/tests/location/location_gnss/src/android/location/cts/gnss/asn1/base/Asn1ObjectIdentifier.java
@@ -16,7 +16,6 @@
package android.location.cts.asn1.base;
-import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
@@ -24,6 +23,7 @@
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
+import java.util.Objects;
/**
* Object identifiers are similar in concept to URIs (indeed
@@ -70,7 +70,7 @@
}
private byte[] encodeBerInternal() {
- Preconditions.checkNotNull(value);
+ Objects.requireNonNull(value);
// Encode according to BER.
BitStream basicEncoding = new BitStream();
Iterator<Integer> valueIterator = value.iterator();
diff --git a/tests/location/location_gnss/src/android/location/cts/gnss/asn1/base/Asn1OctetString.java b/tests/location/location_gnss/src/android/location/cts/gnss/asn1/base/Asn1OctetString.java
index c47f739..fe0ee03 100644
--- a/tests/location/location_gnss/src/android/location/cts/gnss/asn1/base/Asn1OctetString.java
+++ b/tests/location/location_gnss/src/android/location/cts/gnss/asn1/base/Asn1OctetString.java
@@ -24,6 +24,7 @@
import java.nio.ByteBuffer;
import java.util.Collection;
+import java.util.Objects;
/**
* Implements ASN.1 functionality.
@@ -63,12 +64,12 @@
}
@Override int getBerValueLength() {
- Preconditions.checkNotNull(value, "No value set.");
+ Objects.requireNonNull(value, "No value set.");
return value.length;
}
@Override void encodeBerValue(ByteBuffer buf) {
- Preconditions.checkNotNull(value, "No value set.");
+ Objects.requireNonNull(value, "No value set.");
buf.put(value);
}
@@ -77,7 +78,7 @@
}
private Iterable<BitStream> encodePerImpl(boolean aligned) {
- Preconditions.checkNotNull(value, "No value set.");
+ Objects.requireNonNull(value, "No value set.");
Preconditions.checkState(
maximumSize == null || value.length <= maximumSize, "Too large %s",
value.length);
diff --git a/tests/location/location_gnss/src/android/location/cts/gnss/asn1/base/Asn1Utf8String.java b/tests/location/location_gnss/src/android/location/cts/gnss/asn1/base/Asn1Utf8String.java
index 513c02c..0e04b7b 100644
--- a/tests/location/location_gnss/src/android/location/cts/gnss/asn1/base/Asn1Utf8String.java
+++ b/tests/location/location_gnss/src/android/location/cts/gnss/asn1/base/Asn1Utf8String.java
@@ -22,6 +22,7 @@
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.Collection;
+import java.util.Objects;
/**
* Base class for representing ASN.1 objects of type UTF8String.
@@ -67,12 +68,12 @@
}
@Override int getBerValueLength() {
- Preconditions.checkNotNull(value, "No value set.");
+ Objects.requireNonNull(value, "No value set.");
return getValueBytes().length;
}
@Override void encodeBerValue(ByteBuffer buf) {
- Preconditions.checkNotNull(value, "No value set.");
+ Objects.requireNonNull(value, "No value set.");
buf.put(getValueBytes());
}
@@ -81,7 +82,7 @@
}
private Iterable<BitStream> encodePerImpl(boolean aligned) {
- Preconditions.checkNotNull(value, "No value set.");
+ Objects.requireNonNull(value, "No value set.");
Preconditions.checkState(
maximumSize == null || value.length() <= maximumSize, "Too large %s",
value.length());
diff --git a/tests/providerui/src/android/providerui/cts/MediaStoreUiTest.java b/tests/providerui/src/android/providerui/cts/MediaStoreUiTest.java
index de946b3..8d6b83e 100644
--- a/tests/providerui/src/android/providerui/cts/MediaStoreUiTest.java
+++ b/tests/providerui/src/android/providerui/cts/MediaStoreUiTest.java
@@ -388,13 +388,18 @@
&& !pm.hasSystemFeature("android.hardware.type.watch");
}
+ public File getVolumePath(String volumeName) {
+ return mContext.getSystemService(StorageManager.class)
+ .getStorageVolume(MediaStore.Files.getContentUri(volumeName)).getDirectory();
+ }
+
private void prepareFile() throws Exception {
- final File dir = new File(MediaStore.getVolumePath(mVolumeName),
+ final File dir = new File(getVolumePath(mVolumeName),
Environment.DIRECTORY_DOCUMENTS);
final File file = new File(dir, "cts" + System.nanoTime() + ".txt");
mFile = stageFile(R.raw.text, file);
- mMediaStoreUri = MediaStore.scanFile(mContext, mFile);
+ mMediaStoreUri = MediaStore.scanFile(mContext.getContentResolver(), mFile);
Log.v(TAG, "Staged " + mFile + " as " + mMediaStoreUri);
}
diff --git a/tests/tests/appop/AndroidManifest.xml b/tests/tests/appop/AndroidManifest.xml
index 4e8aea9..616647a 100644
--- a/tests/tests/appop/AndroidManifest.xml
+++ b/tests/tests/appop/AndroidManifest.xml
@@ -20,6 +20,8 @@
package="android.app.appops.cts"
android:targetSandboxVersion="2">
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
+ <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
+ <uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
diff --git a/tests/tests/appop/src/android/app/appops/cts/AppOpsLoggingTest.kt b/tests/tests/appop/src/android/app/appops/cts/AppOpsLoggingTest.kt
index d20b00d..9601d21 100644
--- a/tests/tests/appop/src/android/app/appops/cts/AppOpsLoggingTest.kt
+++ b/tests/tests/appop/src/android/app/appops/cts/AppOpsLoggingTest.kt
@@ -33,6 +33,7 @@
import android.app.SyncNotedAppOp
import android.app.WallpaperManager
import android.app.WallpaperManager.FLAG_SYSTEM
+import android.bluetooth.BluetoothManager
import android.content.BroadcastReceiver
import android.content.ComponentName
import android.content.ContentValues
@@ -41,6 +42,7 @@
import android.content.Intent
import android.content.IntentFilter
import android.content.ServiceConnection
+import android.content.pm.PackageManager.FEATURE_BLUETOOTH
import android.content.pm.PackageManager.FEATURE_TELEPHONY
import android.hardware.camera2.CameraDevice
import android.hardware.camera2.CameraManager
@@ -415,6 +417,27 @@
}
/**
+ * Realistic end-to-end test for scanning bluetooth
+ */
+ @Test
+ fun getBTScanResults() {
+ assumeTrue("Device does not support bluetooth",
+ context.packageManager.hasSystemFeature(FEATURE_BLUETOOTH))
+
+ val btManager = context.createFeatureContext(TEST_FEATURE_ID)
+ .getSystemService(BluetoothManager::class.java)
+
+ btManager.adapter.startDiscovery()
+ try {
+ assertThat(noted[0].first.op).isEqualTo(OPSTR_FINE_LOCATION)
+ assertThat(noted[0].first.featureId).isEqualTo(TEST_FEATURE_ID)
+ assertThat(noted[0].second.map { it.methodName }).contains("getBTScanResults")
+ } finally {
+ btManager.adapter.cancelDiscovery()
+ }
+ }
+
+ /**
* Realistic end-to-end test for getting last location
*/
@Test
diff --git a/tests/tests/binder_ndk/libbinder_ndk_test/test_native_aidl_client.cpp b/tests/tests/binder_ndk/libbinder_ndk_test/test_native_aidl_client.cpp
index d15ec1d..2608830 100644
--- a/tests/tests/binder_ndk/libbinder_ndk_test/test_native_aidl_client.cpp
+++ b/tests/tests/binder_ndk/libbinder_ndk_test/test_native_aidl_client.cpp
@@ -247,6 +247,14 @@
EXPECT_EQ(toString(static_cast<IntEnum>(-1)), "-1");
}
+TEST_P(NdkBinderTest_Aidl, EnumValues) {
+ auto range = ::ndk::enum_range<ByteEnum>();
+ auto iter = range.begin();
+ EXPECT_EQ(ByteEnum::FOO, *iter++);
+ EXPECT_EQ(ByteEnum::BAR, *iter++);
+ EXPECT_EQ(range.end(), iter);
+}
+
TEST_P(NdkBinderTest_Aidl, RepeatBinder) {
SpAIBinder binder = iface->asBinder();
SpAIBinder ret;
diff --git a/tests/tests/binder_ndk/libbinder_ndk_test/test_status.cpp b/tests/tests/binder_ndk/libbinder_ndk_test/test_status.cpp
index 7a7e536..ef3ad7a 100644
--- a/tests/tests/binder_ndk/libbinder_ndk_test/test_status.cpp
+++ b/tests/tests/binder_ndk/libbinder_ndk_test/test_status.cpp
@@ -15,6 +15,9 @@
*/
#define LOG_TAG "Cts-NdkBinderTest"
+#include "utilities.h"
+
+#include <android/binder_auto_utils.h>
#include <android/binder_status.h>
#include <gtest/gtest.h>
@@ -193,3 +196,20 @@
AStatus_delete(status);
}
}
+
+TEST(NdkBinderTest_AStatus, StatusDescription) {
+ using ndk::ScopedAStatus;
+
+ EXPECT_TRUE(
+ ContainsSubstring(ScopedAStatus::fromExceptionCode(EX_TRANSACTION_FAILED).getDescription(),
+ "TRANSACTION_FAILED"));
+ EXPECT_TRUE(ContainsSubstring(
+ ScopedAStatus::fromExceptionCodeWithMessage(EX_TRANSACTION_FAILED, "asdf").getDescription(),
+ "asdf"));
+ EXPECT_TRUE(
+ ContainsSubstring(ScopedAStatus::fromServiceSpecificError(42).getDescription(), "42"));
+ EXPECT_TRUE(ContainsSubstring(
+ ScopedAStatus::fromServiceSpecificErrorWithMessage(42, "asdf").getDescription(), "asdf"));
+ EXPECT_TRUE(
+ ContainsSubstring(ScopedAStatus::fromStatus(STATUS_BAD_TYPE).getDescription(), "BAD_TYPE"));
+}
diff --git a/tests/tests/binder_ndk/libbinder_ndk_test/utilities.h b/tests/tests/binder_ndk/libbinder_ndk_test/utilities.h
index e9d6ad5..009ff31 100644
--- a/tests/tests/binder_ndk/libbinder_ndk_test/utilities.h
+++ b/tests/tests/binder_ndk/libbinder_ndk_test/utilities.h
@@ -48,6 +48,15 @@
return ::testing::AssertionFailure() << "Status: " << t;
}
+inline ::testing::AssertionResult ContainsSubstring(const std::string& s, const std::string& ss) {
+ if (s.find(ss) != std::string::npos) {
+ return ::testing::AssertionSuccess();
+ } else {
+ return ::testing::AssertionFailure()
+ << "String: '" << s << "' does not contain substring: " << ss;
+ }
+}
+
#define EXPECT_OK(THING) EXPECT_TRUE(isOk(THING))
#define ASSERT_OK(THING) ASSERT_TRUE(isOk(THING))
diff --git a/tests/tests/car/src/android/car/cts/CarPropertyManagerTest.java b/tests/tests/car/src/android/car/cts/CarPropertyManagerTest.java
index ceabc3d..bed372c 100644
--- a/tests/tests/car/src/android/car/cts/CarPropertyManagerTest.java
+++ b/tests/tests/car/src/android/car/cts/CarPropertyManagerTest.java
@@ -23,6 +23,7 @@
import static org.junit.Assert.assertNotNull;
import android.car.Car;
+import android.car.VehicleAreaSeat;
import android.car.VehicleAreaType;
import android.car.VehiclePropertyIds;
import android.car.hardware.CarPropertyConfig;
@@ -110,17 +111,63 @@
mPropertyIds.add(VehiclePropertyIds.PERF_VEHICLE_SPEED);
mPropertyIds.add(VehiclePropertyIds.GEAR_SELECTION);
mPropertyIds.add(VehiclePropertyIds.NIGHT_MODE);
+ mPropertyIds.add(VehiclePropertyIds.PARKING_BRAKE_ON);
}
+ /**
+ * Test for {@link CarPropertyManager#getPropertyList()}
+ */
@Test
public void testGetPropertyList() {
List<CarPropertyConfig> allConfigs = mCarPropertyManager.getPropertyList();
assertNotNull(allConfigs);
+ }
+
+ /**
+ * Test for {@link CarPropertyManager#getPropertyList(ArraySet)}
+ */
+ @Test
+ public void testGetPropertyListWithArraySet() {
List<CarPropertyConfig> requiredConfigs = mCarPropertyManager.getPropertyList(mPropertyIds);
// Vehicles need to implement all of those properties
assertEquals(mPropertyIds.size(), requiredConfigs.size());
}
+ /**
+ * Test for {@link CarPropertyManager#getCarPropertyConfig(int)}
+ */
+ @Test
+ public void testGetPropertyConfig() {
+ List<CarPropertyConfig> allConfigs = mCarPropertyManager.getPropertyList();
+ for (CarPropertyConfig cfg : allConfigs) {
+ assertNotNull(mCarPropertyManager.getCarPropertyConfig(cfg.getPropertyId()));
+ }
+ }
+
+ /**
+ * Test for {@link CarPropertyManager#getAreaId(int, int)}
+ */
+ @Test
+ public void testGetAreaId() {
+ // For global properties, getAreaId should always return 0.
+ List<CarPropertyConfig> allConfigs = mCarPropertyManager.getPropertyList();
+ for (CarPropertyConfig cfg : allConfigs) {
+ if (cfg.isGlobalProperty()) {
+ assertEquals(0, mCarPropertyManager.getAreaId(cfg.getPropertyId(),
+ VehicleAreaSeat.SEAT_ROW_1_LEFT));
+ } else {
+ int[] areaIds = cfg.getAreaIds();
+ // Because areaId in propConfig must not be overlapped with each other.
+ // The result should be itself.
+ for (int areaIdInConfig : areaIds) {
+ int areaIdByCarPropertyManager =
+ mCarPropertyManager.getAreaId(cfg.getPropertyId(), areaIdInConfig);
+ assertEquals(areaIdInConfig, areaIdByCarPropertyManager);
+ }
+ }
+ }
+ }
+
@CddTest(requirement="2.5.1")
@Test
public void testMustSupportGearSelection() throws Exception {
diff --git a/tests/tests/carrierapi/src/android/carrierapi/cts/CarrierApiTest.java b/tests/tests/carrierapi/src/android/carrierapi/cts/CarrierApiTest.java
index e73c11a..73897fd 100644
--- a/tests/tests/carrierapi/src/android/carrierapi/cts/CarrierApiTest.java
+++ b/tests/tests/carrierapi/src/android/carrierapi/cts/CarrierApiTest.java
@@ -36,8 +36,8 @@
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.Uri;
-import android.os.Build;
import android.os.AsyncTask;
+import android.os.Build;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.ParcelUuid;
@@ -278,11 +278,15 @@
if (mTelephonyManager.getPhoneCount() == 1) {
return;
}
+
+ /* TODO: b/145993690 */
if (mTelephonyManager.getPhoneCount() == 2 && activeSubscriptionInfoCount != 2) {
- fail("This test requires two SIM cards.");
+ /* This test requires two SIM cards */
+ return;
}
if (subIdWithCarrierPrivilege == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
- failMessage();
+ /* This test requires SIM with carrier privilege */
+ return;
}
List<SubscriptionInfo> subscriptionInfoList =
diff --git a/tests/tests/contactsprovider/src/android/provider/cts/contacts/ContactsContract_RawContactsTest.java b/tests/tests/contactsprovider/src/android/provider/cts/contacts/ContactsContract_RawContactsTest.java
index dc49a2e..fa0572c 100644
--- a/tests/tests/contactsprovider/src/android/provider/cts/contacts/ContactsContract_RawContactsTest.java
+++ b/tests/tests/contactsprovider/src/android/provider/cts/contacts/ContactsContract_RawContactsTest.java
@@ -17,6 +17,7 @@
package android.provider.cts.contacts;
+import android.accounts.Account;
import android.content.ContentProviderClient;
import android.content.ContentResolver;
import android.content.ContentValues;
@@ -120,6 +121,14 @@
lookupContact.getId(), rawContact.load().getContactId());
}
+ public void testGetDeviceAccountNameAndType_haveSameNullness() {
+ String name = RawContacts.getLocalAccountName(mContext);
+ String type = RawContacts.getLocalAccountType(mContext);
+
+ assertTrue("Device account name and type must both be null or both be non-null",
+ (name == null && type == null) || (name != null && type != null));
+ }
+
public void testRawContactDelete_setsDeleteFlag() {
long rawContactid = RawContactUtil.insertRawContact(mResolver,
StaticAccountAuthenticator.ACCOUNT_1);
@@ -142,7 +151,11 @@
}
public void testRawContactDelete_localDeleteRemovesRecord() {
- long rawContactid = RawContactUtil.insertRawContact(mResolver, null);
+ String name = RawContacts.getLocalAccountName(mContext);
+ String type = RawContacts.getLocalAccountType(mContext);
+ Account account = name != null && type != null ? new Account(name, type) : null;
+
+ long rawContactid = RawContactUtil.insertRawContact(mResolver, account);
assertTrue(RawContactUtil.rawContactExistsById(mResolver, rawContactid));
// Local raw contacts should be deleted immediately even if isSyncAdapter=false
@@ -179,6 +192,32 @@
RawContactUtil.delete(mResolver, ids.mRawContactId, true);
}
+ /**
+ * The local account is the default if a raw contact insert does not specify a value for
+ * {@link RawContacts#ACCOUNT_NAME} and {@link RawContacts#ACCOUNT_TYPE}.
+ *
+ * <p>The values returned by {@link RawContacts#getLocalAccountName()} and
+ * {@link RawContacts#getLocalAccountType()} can be customized by overriding the
+ * config_rawContactsLocalAccountName and config_rawContactsLocalAccountType resource strings
+ * defined in platform/frameworks/base/core/res/res/values/config.xml.
+ */
+ public void testRawContactCreate_noAccountUsesLocalAccount() {
+ // Save a raw contact without an account.
+ long rawContactid = RawContactUtil.insertRawContact(mResolver, null);
+
+ String[] row = RawContactUtil.queryByRawContactId(mResolver, rawContactid,
+ new String[] {
+ RawContacts.ACCOUNT_NAME, RawContacts.ACCOUNT_TYPE
+ });
+
+ // When no account is specified the contact is created in the local account.
+ assertEquals(RawContacts.getLocalAccountName(mContext), row[0]);
+ assertEquals(RawContacts.getLocalAccountType(mContext), row[1]);
+
+ // Clean up
+ RawContactUtil.delete(mResolver, rawContactid, true);
+ }
+
public void testRawContactUpdate_updatesContactUpdatedTimestamp() {
DatabaseAsserts.ContactIdPair ids = DatabaseAsserts.assertAndCreateContact(mResolver);
diff --git a/tests/tests/contactsprovider/src/android/provider/cts/contacts/ContactsProvider2_AccountRemovalTest.java b/tests/tests/contactsprovider/src/android/provider/cts/contacts/ContactsProvider2_AccountRemovalTest.java
index 4f82a49..ceaee73 100755
--- a/tests/tests/contactsprovider/src/android/provider/cts/contacts/ContactsProvider2_AccountRemovalTest.java
+++ b/tests/tests/contactsprovider/src/android/provider/cts/contacts/ContactsProvider2_AccountRemovalTest.java
@@ -20,6 +20,7 @@
import android.accounts.AccountManager;
import android.content.ContentResolver;
import android.os.SystemClock;
+import android.provider.ContactsContract;
import android.provider.cts.contacts.DatabaseAsserts.ContactIdPair;
import android.provider.cts.contacts.account.StaticAccountAuthenticator;
import android.test.AndroidTestCase;
@@ -100,6 +101,34 @@
}
/**
+ * Contacts saved to the local account should not be removed when accounts change.
+ *
+ * <p>The local account is a special case that is not added to
+ * {@link AccountManager}. Normally raw contacts with an
+ * {@link android.provider.ContactsContract.RawContacts#ACCOUNT_NAME} and
+ * {@link android.provider.ContactsContract.RawContacts#ACCOUNT_TYPE} that do not correspond
+ * to an added account will be removed but this should not be done for the local account.
+ */
+ public void testAccountRemoval_doesNotDeleteLocalAccountContacts() {
+ mAccountManager.addAccountExplicitly(ACCT_1, null, null);
+ ArrayList<ContactIdPair> acc1Ids = createContacts(ACCT_1, 5);
+
+ String name = ContactsContract.RawContacts.getLocalAccountName(mContext);
+ String type = ContactsContract.RawContacts.getLocalAccountType(mContext);
+ Account deviceAccount = name != null && type != null ? new Account(name, type) : null;
+ long deviceRawContactId = RawContactUtil
+ .createRawContactWithAutoGeneratedName(mResolver, deviceAccount);
+
+ mAccountManager.removeAccount(ACCT_1, null, null);
+
+ // Wait for deletion of the contacts in the removed account to finish before verifying
+ // the existence of the device contacts
+ assertContactsDeletedEventually(System.currentTimeMillis(), acc1Ids);
+
+ assertTrue(RawContactUtil.rawContactExistsById(mResolver, deviceRawContactId));
+ }
+
+ /**
* Contact has merged raw contacts from different accounts. Contact should not be deleted when
* one account is removed. But contact should have last updated timestamp updated.
*/
diff --git a/tests/tests/content/src/android/content/cts/AvailableIntentsTest.java b/tests/tests/content/src/android/content/cts/AvailableIntentsTest.java
index 5ad911f..1198ef8 100644
--- a/tests/tests/content/src/android/content/cts/AvailableIntentsTest.java
+++ b/tests/tests/content/src/android/content/cts/AvailableIntentsTest.java
@@ -281,11 +281,17 @@
}
public void testAlarmClockDismissAlarm() {
+ if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK_ONLY)) {
+ return;
+ }
Intent intent = new Intent(AlarmClock.ACTION_DISMISS_ALARM);
assertCanBeHandled(intent);
}
public void testAlarmClockSnoozeAlarm() {
+ if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK_ONLY)) {
+ return;
+ }
Intent intent = new Intent(AlarmClock.ACTION_SNOOZE_ALARM);
intent.putExtra(AlarmClock.EXTRA_ALARM_SNOOZE_DURATION, 10);
assertCanBeHandled(intent);
diff --git a/tests/tests/content/src/android/content/cts/ContextTest.java b/tests/tests/content/src/android/content/cts/ContextTest.java
index 336c492..03ae82f 100644
--- a/tests/tests/content/src/android/content/cts/ContextTest.java
+++ b/tests/tests/content/src/android/content/cts/ContextTest.java
@@ -18,9 +18,12 @@
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+import static org.junit.Assume.assumeTrue;
+
import android.app.Activity;
import android.app.AppOpsManager;
import android.app.Instrumentation;
+import android.app.WallpaperManager;
import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
@@ -783,6 +786,8 @@
}
public void testAccessWallpaper() throws IOException, InterruptedException {
+ assumeWallpaperSupported();
+
// set Wallpaper by context#setWallpaper(Bitmap)
Bitmap bitmap = Bitmap.createBitmap(20, 30, Bitmap.Config.RGB_565);
// Test getWallpaper
@@ -1089,6 +1094,8 @@
}
public void testGetWallpaperDesiredMinimumHeightAndWidth() {
+ assumeWallpaperSupported();
+
int height = mContext.getWallpaperDesiredMinimumHeight();
int width = mContext.getWallpaperDesiredMinimumWidth();
@@ -1608,4 +1615,9 @@
} catch (IllegalArgumentException expected) {
}
}
+
+ private void assumeWallpaperSupported() {
+ assumeTrue("Device does not support wallpapers",
+ WallpaperManager.getInstance(mContext).isWallpaperSupported());
+ }
}
diff --git a/tests/tests/cronet/Android.bp b/tests/tests/cronet/Android.bp
new file mode 100644
index 0000000..0b50579
--- /dev/null
+++ b/tests/tests/cronet/Android.bp
@@ -0,0 +1,37 @@
+// 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.
+
+
+// TODO: Move this target to cts/tests/tests/net/cronet
+android_test {
+ name: "CtsCronetTestCases",
+ defaults: ["cts_defaults"],
+
+ // Include both the 32 and 64 bit versions
+ compile_multilib: "both",
+
+ static_libs: [
+ "CronetApiCommonTests",
+ "ctstestrunner-axt",
+ ],
+
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ "mts",
+ ],
+
+}
diff --git a/tests/tests/cronet/AndroidManifest.xml b/tests/tests/cronet/AndroidManifest.xml
new file mode 100644
index 0000000..b7ae844
--- /dev/null
+++ b/tests/tests/cronet/AndroidManifest.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.cronet.cts" >
+
+ <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+ <uses-permission android:name="android.permission.INTERNET" />
+
+ <application android:usesCleartextTraffic="true">
+ <uses-library android:name="android.test.runner" />
+ <uses-library android:name="org.chromium.net.cronet" />
+ </application>
+
+ <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.cronet.cts"
+ android:label="CTS tests of android.cronet">
+ <meta-data android:name="listener"
+ android:value="com.android.cts.runner.CtsTestRunListener" />
+ </instrumentation>
+
+</manifest>
diff --git a/tests/tests/cronet/AndroidTest.xml b/tests/tests/cronet/AndroidTest.xml
new file mode 100644
index 0000000..79c37f7
--- /dev/null
+++ b/tests/tests/cronet/AndroidTest.xml
@@ -0,0 +1,30 @@
+<?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="Config for CTS Cronet test cases">
+ <option name="test-suite-tag" value="cts" />
+ <option name="config-descriptor:metadata" key="component" value="networking" />
+ <option name="config-descriptor:metadata" key="parameter" value="instant_app" />
+ <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
+ <option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsCronetTestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.cronet.cts" />
+ <option name="runtime-hint" value="10s" />
+ </test>
+</configuration>
\ No newline at end of file
diff --git a/tests/tests/cronet/OWNERS b/tests/tests/cronet/OWNERS
new file mode 100644
index 0000000..f4525df
--- /dev/null
+++ b/tests/tests/cronet/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 31808
+include ../net/OWNERS
\ No newline at end of file
diff --git a/tests/tests/graphics/src/android/graphics/cts/ImageDecoderTest.java b/tests/tests/graphics/src/android/graphics/cts/ImageDecoderTest.java
index 317acc0..fe13ea4 100644
--- a/tests/tests/graphics/src/android/graphics/cts/ImageDecoderTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/ImageDecoderTest.java
@@ -1533,9 +1533,59 @@
}
}
+ // One static PNG and one animated GIF to test setting invalid crop rects,
+ // to test both paths (animated and non-animated) through ImageDecoder.
+ private static Object[] resourcesForCropTests() {
+ return new Object[] { R.drawable.png_test, R.drawable.animated };
+ }
+
@Test(expected = IllegalStateException.class)
- public void testCropNegativeLeft() {
- ImageDecoder.Source src = mCreators[0].apply(R.drawable.png_test);
+ @Parameters(method = "resourcesForCropTests")
+ public void testInvertCropWidth(int resId) {
+ ImageDecoder.Source src = mCreators[0].apply(resId);
+ try {
+ ImageDecoder.decodeDrawable(src, (decoder, info, s) -> {
+ // This rect is unsorted.
+ decoder.setCrop(new Rect(info.getSize().getWidth(), 0, 0,
+ info.getSize().getHeight()));
+ });
+ } catch (IOException e) {
+ fail("Failed with exception " + e);
+ }
+ }
+
+ @Test(expected = IllegalStateException.class)
+ @Parameters(method = "resourcesForCropTests")
+ public void testInvertCropHeight(int resId) {
+ ImageDecoder.Source src = mCreators[0].apply(resId);
+ try {
+ ImageDecoder.decodeDrawable(src, (decoder, info, s) -> {
+ // This rect is unsorted.
+ decoder.setCrop(new Rect(0, info.getSize().getWidth(),
+ info.getSize().getHeight(), 0));
+ });
+ } catch (IOException e) {
+ fail("Failed with exception " + e);
+ }
+ }
+
+ @Test(expected = IllegalStateException.class)
+ @Parameters(method = "resourcesForCropTests")
+ public void testEmptyCrop(int resId) {
+ ImageDecoder.Source src = mCreators[0].apply(resId);
+ try {
+ ImageDecoder.decodeDrawable(src, (decoder, info, s) -> {
+ decoder.setCrop(new Rect(1, 1, 1, 1));
+ });
+ } catch (IOException e) {
+ fail("Failed with exception " + e);
+ }
+ }
+
+ @Test(expected = IllegalStateException.class)
+ @Parameters(method = "resourcesForCropTests")
+ public void testCropNegativeLeft(int resId) {
+ ImageDecoder.Source src = mCreators[0].apply(resId);
try {
ImageDecoder.decodeDrawable(src, (decoder, info, s) -> {
decoder.setCrop(new Rect(-1, 0, info.getSize().getWidth(),
@@ -1547,21 +1597,9 @@
}
@Test(expected = IllegalStateException.class)
- public void testCropNegativeLeftAnimated() {
- ImageDecoder.Source src = mCreators[0].apply(R.drawable.animated);
- try {
- ImageDecoder.decodeDrawable(src, (decoder, info, s) -> {
- decoder.setCrop(new Rect(-1, 0, info.getSize().getWidth(),
- info.getSize().getHeight()));
- });
- } catch (IOException e) {
- fail("Failed with exception " + e);
- }
- }
-
- @Test(expected = IllegalStateException.class)
- public void testCropNegativeTop() {
- ImageDecoder.Source src = mCreators[0].apply(R.drawable.png_test);
+ @Parameters(method = "resourcesForCropTests")
+ public void testCropNegativeTop(int resId) {
+ ImageDecoder.Source src = mCreators[0].apply(resId);
try {
ImageDecoder.decodeDrawable(src, (decoder, info, s) -> {
decoder.setCrop(new Rect(0, -1, info.getSize().getWidth(),
@@ -1573,21 +1611,9 @@
}
@Test(expected = IllegalStateException.class)
- public void testCropNegativeTopAnimated() {
- ImageDecoder.Source src = mCreators[0].apply(R.drawable.animated);
- try {
- ImageDecoder.decodeDrawable(src, (decoder, info, s) -> {
- decoder.setCrop(new Rect(0, -1, info.getSize().getWidth(),
- info.getSize().getHeight()));
- });
- } catch (IOException e) {
- fail("Failed with exception " + e);
- }
- }
-
- @Test(expected = IllegalStateException.class)
- public void testCropTooWide() {
- ImageDecoder.Source src = mCreators[0].apply(R.drawable.png_test);
+ @Parameters(method = "resourcesForCropTests")
+ public void testCropTooWide(int resId) {
+ ImageDecoder.Source src = mCreators[0].apply(resId);
try {
ImageDecoder.decodeDrawable(src, (decoder, info, s) -> {
decoder.setCrop(new Rect(1, 0, info.getSize().getWidth() + 1,
@@ -1598,22 +1624,11 @@
}
}
- @Test(expected = IllegalStateException.class)
- public void testCropTooWideAnimated() {
- ImageDecoder.Source src = mCreators[0].apply(R.drawable.animated);
- try {
- ImageDecoder.decodeDrawable(src, (decoder, info, s) -> {
- decoder.setCrop(new Rect(1, 0, info.getSize().getWidth() + 1,
- info.getSize().getHeight()));
- });
- } catch (IOException e) {
- fail("Failed with exception " + e);
- }
- }
@Test(expected = IllegalStateException.class)
- public void testCropTooTall() {
- ImageDecoder.Source src = mCreators[0].apply(R.drawable.png_test);
+ @Parameters(method = "resourcesForCropTests")
+ public void testCropTooTall(int resId) {
+ ImageDecoder.Source src = mCreators[0].apply(resId);
try {
ImageDecoder.decodeDrawable(src, (decoder, info, s) -> {
decoder.setCrop(new Rect(0, 1, info.getSize().getWidth(),
@@ -1625,23 +1640,9 @@
}
@Test(expected = IllegalStateException.class)
- public void testCropResize() {
- ImageDecoder.Source src = mCreators[0].apply(R.drawable.png_test);
- try {
- ImageDecoder.decodeDrawable(src, (decoder, info, s) -> {
- Size size = info.getSize();
- decoder.setTargetSize(size.getWidth() / 2, size.getHeight() / 2);
- decoder.setCrop(new Rect(0, 0, size.getWidth(),
- size.getHeight()));
- });
- } catch (IOException e) {
- fail("Failed with exception " + e);
- }
- }
-
- @Test(expected = IllegalStateException.class)
- public void testCropResizeAnimated() {
- ImageDecoder.Source src = mCreators[0].apply(R.drawable.animated);
+ @Parameters(method = "resourcesForCropTests")
+ public void testCropResize(int resId) {
+ ImageDecoder.Source src = mCreators[0].apply(resId);
try {
ImageDecoder.decodeDrawable(src, (decoder, info, s) -> {
Size size = info.getSize();
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/GradientDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/GradientDrawableTest.java
index cfb3af6..b4a4320 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/GradientDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/GradientDrawableTest.java
@@ -34,7 +34,6 @@
import android.graphics.ColorFilter;
import android.graphics.Insets;
import android.graphics.PixelFormat;
-import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.graphics.cts.R;
import android.graphics.drawable.Drawable.ConstantState;
@@ -720,6 +719,7 @@
GradientDrawable drawable = (GradientDrawable)
context.getDrawable(R.drawable.gradientdrawable_mix_theme);
+
// Verify that despite multiple inflation passes are done to inflate both
// the non-theme attributes as well as the themed attributes
assertEquals(GradientDrawable.RADIAL_GRADIENT, drawable.getGradientType());
@@ -765,27 +765,6 @@
Orientation.LEFT_RIGHT);
}
- @Test
- public void testTintedStrokeWithoutSolidColor() {
- final Context context = InstrumentationRegistry.getTargetContext();
- GradientDrawable strokeDrawable = (GradientDrawable)
- context.getDrawable(R.drawable.gradientdrawable_stroke_tint);
- int bgColor = context.getColor(android.R.color.holo_blue_light);
- int tintColor = context.getColor(android.R.color.holo_orange_light);
- int width = 100;
- int height = 100;
- Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
- Canvas canvas = new Canvas(bitmap);
- canvas.drawColor(bgColor);
- strokeDrawable.setTint(tintColor);
- strokeDrawable.setTintMode(PorterDuff.Mode.MULTIPLY);
- strokeDrawable.setBounds(0, 0, width, height);
- strokeDrawable.draw(canvas);
-
- assertEquals(bitmap.getPixel(width / 2, height / 2), bgColor);
- assertEquals(bitmap.getPixel(2, height / 2), tintColor);
- }
-
private void verifyGradientOrientation(int resId, Orientation expected) {
final Context context = InstrumentationRegistry.getTargetContext();
assertEquals(expected,
diff --git a/tests/tests/hardware/res/raw/razer_serval_keyeventtests.json b/tests/tests/hardware/res/raw/razer_serval_keyeventtests.json
new file mode 100644
index 0000000..eed99d7
--- /dev/null
+++ b/tests/tests/hardware/res/raw/razer_serval_keyeventtests.json
@@ -0,0 +1,157 @@
+[
+ {
+ "name": "Press BUTTON_A",
+ "reports": [
+ [0x01, 0x80, 0x80, 0x80, 0x80, 0x18, 0x00, 0x00, 0x00, 0x00, 0xff],
+ [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x00, 0x00, 0x00, 0x00, 0xff]
+ ],
+ "source": "GAMEPAD | KEYBOARD",
+ "events": [
+ {"action": "DOWN", "keycode": "BUTTON_A"},
+ {"action": "UP", "keycode": "BUTTON_A"}
+ ]
+ },
+
+ {
+ "name": "Press BUTTON_B",
+ "reports": [
+ [0x01, 0x80, 0x80, 0x80, 0x80, 0x28, 0x00, 0x00, 0x00, 0x00, 0xff],
+ [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x00, 0x00, 0x00, 0x00, 0xff]
+ ],
+ "source": "GAMEPAD | KEYBOARD",
+ "events": [
+ {"action": "DOWN", "keycode": "BUTTON_B"},
+ {"action": "UP", "keycode": "BUTTON_B"}
+ ]
+ },
+
+ {
+ "name": "Press BUTTON_X",
+ "reports": [
+ [0x01, 0x80, 0x80, 0x80, 0x80, 0x48, 0x00, 0x00, 0x00, 0x00, 0xff],
+ [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x00, 0x00, 0x00, 0x00, 0xff]
+ ],
+ "source": "GAMEPAD | KEYBOARD",
+ "events": [
+ {"action": "DOWN", "keycode": "BUTTON_X"},
+ {"action": "UP", "keycode": "BUTTON_X"}
+ ]
+ },
+
+ {
+ "name": "Press BUTTON_Y",
+ "reports": [
+ [0x01, 0x80, 0x80, 0x80, 0x80, 0x88, 0x00, 0x00, 0x00, 0x00, 0xff],
+ [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x00, 0x00, 0x00, 0x00, 0xff]
+ ],
+ "source": "GAMEPAD | KEYBOARD",
+ "events": [
+ {"action": "DOWN", "keycode": "BUTTON_Y"},
+ {"action": "UP", "keycode": "BUTTON_Y"}
+ ]
+ },
+
+ {
+ "name": "Press BUTTON_L1",
+ "reports": [
+ [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x01, 0x00, 0x00, 0x00, 0xff],
+ [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x00, 0x00, 0x00, 0x00, 0xff]
+ ],
+ "source": "GAMEPAD | KEYBOARD",
+ "events": [
+ {"action": "DOWN", "keycode": "BUTTON_L1"},
+ {"action": "UP", "keycode": "BUTTON_L1"}
+ ]
+ },
+
+ {
+ "name": "Press BUTTON_R1",
+ "reports": [
+ [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x02, 0x00, 0x00, 0x00, 0xff],
+ [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x00, 0x00, 0x00, 0x00, 0xff]
+ ],
+ "source": "GAMEPAD | KEYBOARD",
+ "events": [
+ {"action": "DOWN", "keycode": "BUTTON_R1"},
+ {"action": "UP", "keycode": "BUTTON_R1"}
+ ]
+ },
+
+ {
+ "name": "Press BUTTON_THUMBL",
+ "reports": [
+ [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x10, 0x00, 0x00, 0x00, 0xff],
+ [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x00, 0x00, 0x00, 0x00, 0xff]
+ ],
+ "source": "GAMEPAD | KEYBOARD",
+ "events": [
+ {"action": "DOWN", "keycode": "BUTTON_THUMBL"},
+ {"action": "UP", "keycode": "BUTTON_THUMBL"}
+ ]
+ },
+
+ {
+ "name": "Press BUTTON_THUMBR",
+ "reports": [
+ [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x20, 0x00, 0x00, 0x00, 0xff],
+ [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x00, 0x00, 0x00, 0x00, 0xff]
+ ],
+ "source": "GAMEPAD | KEYBOARD",
+ "events": [
+ {"action": "DOWN", "keycode": "BUTTON_THUMBR"},
+ {"action": "UP", "keycode": "BUTTON_THUMBR"}
+ ]
+ },
+
+ {
+ "name": "Press arrow left button (the button left of 'power key')",
+ "reports": [
+ [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x00, 0x01, 0x00, 0x00, 0xff],
+ [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x00, 0x00, 0x00, 0x00, 0xff]
+ ],
+ "source": "GAMEPAD | KEYBOARD",
+ "events": [
+ {"action": "DOWN", "keycode": "BUTTON_SELECT"},
+ {"action": "UP", "keycode": "BUTTON_SELECT"}
+ ]
+ },
+
+ {
+ "name": "Press 'power key'",
+ "reports": [
+ [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x40, 0x00, 0x00, 0x00, 0xff],
+ [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x00, 0x00, 0x00, 0x00, 0xff]
+ ],
+ "source": "GAMEPAD | KEYBOARD",
+ "events": [
+ {"action": "DOWN", "keycode": "BUTTON_MODE"},
+ {"action": "UP", "keycode": "BUTTON_MODE"}
+ ]
+ },
+
+ {
+ "name": "Press arrow right button (the button right of 'power key')",
+ "reports": [
+ [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x08, 0x00, 0x00, 0x00, 0xff],
+ [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x00, 0x00, 0x00, 0x00, 0xff]
+ ],
+ "source": "GAMEPAD | KEYBOARD",
+ "events": [
+ {"action": "DOWN", "keycode": "BUTTON_START"},
+ {"action": "UP", "keycode": "BUTTON_START"}
+ ]
+ },
+
+ {
+ "name": "Press BACK button (left arrow at the bottom of the controller)",
+ "reports": [
+ [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x04, 0x00, 0x00, 0x00, 0xff],
+ [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x00, 0x00, 0x00, 0x00, 0xff]
+ ],
+ "source": "GAMEPAD | KEYBOARD",
+ "events": [
+ {"action": "DOWN", "keycode": "BACK"},
+ {"action": "UP", "keycode": "BACK"}
+ ]
+ }
+]
\ No newline at end of file
diff --git a/tests/tests/hardware/res/raw/razer_serval_motioneventtests.json b/tests/tests/hardware/res/raw/razer_serval_motioneventtests.json
new file mode 100644
index 0000000..868277c
--- /dev/null
+++ b/tests/tests/hardware/res/raw/razer_serval_motioneventtests.json
@@ -0,0 +1,193 @@
+[
+ {
+ "name": "Sanity check - should not produce any events",
+ "reports": [
+ [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x00, 0x00, 0x00, 0x00, 0xff]
+ ],
+ "events": []
+ },
+
+ {
+ "name": "Press left DPAD key",
+ "reports": [
+ [0x01, 0x80, 0x80, 0x80, 0x80, 0x06, 0x00, 0x00, 0x00, 0x00, 0xff],
+ [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x00, 0x00, 0x00, 0x00, 0xff]
+ ],
+ "source": "JOYSTICK",
+ "events": [
+ {"action": "MOVE", "axes": {"AXIS_HAT_X": -1}},
+ {"action": "MOVE", "axes": {"AXIS_HAT_X": 0}}
+ ]
+ },
+
+ {
+ "name": "Press right DPAD key",
+ "reports": [
+ [0x01, 0x80, 0x80, 0x80, 0x80, 0x02, 0x00, 0x00, 0x00, 0x00, 0xff],
+ [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x00, 0x00, 0x00, 0x00, 0xff]
+ ],
+ "source": "JOYSTICK",
+ "events": [
+ {"action": "MOVE", "axes": {"AXIS_HAT_X": 1}},
+ {"action": "MOVE", "axes": {"AXIS_HAT_X": 0}}
+ ]
+ },
+
+ {
+ "name": "Press up DPAD key",
+ "reports": [
+ [0x01, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff],
+ [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x00, 0x00, 0x00, 0x00, 0xff]
+ ],
+ "source": "JOYSTICK",
+ "events": [
+ {"action": "MOVE", "axes": {"AXIS_HAT_Y": -1}},
+ {"action": "MOVE", "axes": {"AXIS_HAT_Y": 0}}
+ ]
+ },
+
+ {
+ "name": "Press down DPAD key",
+ "reports": [
+ [0x01, 0x80, 0x80, 0x80, 0x80, 0x04, 0x00, 0x00, 0x00, 0x00, 0xff],
+ [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x00, 0x00, 0x00, 0x00, 0xff]
+ ],
+ "source": "JOYSTICK",
+ "events": [
+ {"action": "MOVE", "axes": {"AXIS_HAT_Y": 1}},
+ {"action": "MOVE", "axes": {"AXIS_HAT_Y": 0}}
+ ]
+ },
+
+ {
+ "name": "Left stick - press left",
+ "reports": [
+ [0x01, 0x00, 0x80, 0x80, 0x80, 0x08, 0x00, 0x00, 0x00, 0x00, 0xff],
+ [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x00, 0x00, 0x00, 0x00, 0xff]
+ ],
+ "source": "JOYSTICK",
+ "events": [
+ {"action": "MOVE", "axes": {"AXIS_X": -1}},
+ {"action": "MOVE", "axes": {"AXIS_X": 0}}
+ ]
+ },
+
+ {
+ "name": "Left stick - press right",
+ "reports": [
+ [0x01, 0xff, 0x80, 0x80, 0x80, 0x08, 0x00, 0x00, 0x00, 0x00, 0xff],
+ [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x00, 0x00, 0x00, 0x00, 0xff]
+ ],
+ "source": "JOYSTICK",
+ "events": [
+ {"action": "MOVE", "axes": {"AXIS_X": 1}},
+ {"action": "MOVE", "axes": {"AXIS_X": 0}}
+ ]
+ },
+
+ {
+ "name": "Left stick - press up",
+ "reports": [
+ [0x01, 0x80, 0x00, 0x80, 0x80, 0x08, 0x00, 0x00, 0x00, 0x00, 0xff],
+ [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x00, 0x00, 0x00, 0x00, 0xff]
+ ],
+ "source": "JOYSTICK",
+ "events": [
+ {"action": "MOVE", "axes": {"AXIS_Y": -1}},
+ {"action": "MOVE", "axes": {"AXIS_Y": 0}}
+ ]
+ },
+
+ {
+ "name": "Left stick - press down",
+ "reports": [
+ [0x01, 0x80, 0xff, 0x80, 0x80, 0x08, 0x00, 0x00, 0x00, 0x00, 0xff],
+ [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x00, 0x00, 0x00, 0x00, 0xff]
+ ],
+ "source": "JOYSTICK",
+ "events": [
+ {"action": "MOVE", "axes": {"AXIS_X": 0, "AXIS_Y": 1, "AXIS_Z": 0}},
+ {"action": "MOVE", "axes": {"AXIS_X": 0, "AXIS_Y": 0, "AXIS_Z": 0}}
+ ]
+ },
+
+ {
+ "name": "Right stick - press left",
+ "reports": [
+ [0x01, 0x80, 0x80, 0x00, 0x80, 0x08, 0x00, 0x00, 0x00, 0x00, 0xff],
+ [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x00, 0x00, 0x00, 0x00, 0xff]
+ ],
+ "source": "JOYSTICK",
+ "events": [
+ {"action": "MOVE", "axes": {"AXIS_Z": -1}},
+ {"action": "MOVE", "axes": {"AXIS_Z": 0}}
+ ]
+ },
+
+ {
+ "name": "Right stick - press right",
+ "reports": [
+ [0x01, 0x80, 0x80, 0xff, 0x80, 0x08, 0x00, 0x00, 0x00, 0x00, 0xff],
+ [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x00, 0x00, 0x00, 0x00, 0xff]
+ ],
+ "source": "JOYSTICK",
+ "events": [
+ {"action": "MOVE", "axes": {"AXIS_Z": 1}},
+ {"action": "MOVE", "axes": {"AXIS_Z": 0}}
+ ]
+ },
+
+ {
+ "name": "Right stick - press up",
+ "reports": [
+ [0x01, 0x80, 0x80, 0x80, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0xff],
+ [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x00, 0x00, 0x00, 0x00, 0xff]
+ ],
+ "source": "JOYSTICK",
+ "events": [
+ {"action": "MOVE", "axes": {"AXIS_RZ": -1}},
+ {"action": "MOVE", "axes": {"AXIS_RZ": 0}}
+ ]
+ },
+
+ {
+ "name": "Right stick - press down",
+ "reports": [
+ [0x01, 0x80, 0x80, 0x80, 0xff, 0x08, 0x00, 0x00, 0x00, 0x00, 0xff],
+ [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x00, 0x00, 0x00, 0x00, 0xff]
+ ],
+ "source": "JOYSTICK",
+ "events": [
+ {"action": "MOVE", "axes": {"AXIS_RZ": 1}},
+ {"action": "MOVE", "axes": {"AXIS_RZ": 0}}
+ ]
+ },
+
+ {
+ "name": "Left trigger - quick press",
+ "reports": [
+ [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x00, 0x00, 0xff, 0x00, 0xff],
+ [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x00, 0x00, 0x00, 0x00, 0xff]
+ ],
+ "source": "JOYSTICK",
+ "events": [
+ {"action": "MOVE", "axes": {"AXIS_LTRIGGER": 1.0, "AXIS_BRAKE": 1.0}},
+ {"action": "MOVE", "axes": {"AXIS_LTRIGGER": 0, "AXIS_BRAKE": 0}}
+ ]
+ },
+
+ {
+ "name": "Right trigger - quick press",
+ "reports": [
+ [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x00, 0x00, 0x00, 0xff, 0xff],
+ [0x01, 0x80, 0x80, 0x80, 0x80, 0x08, 0x00, 0x00, 0x00, 0x00, 0xff]
+ ],
+ "source": "JOYSTICK",
+ "events": [
+ {"action": "MOVE", "axes": {"AXIS_RTRIGGER": 1.0, "AXIS_GAS": 1.0}},
+ {"action": "MOVE", "axes": {"AXIS_RTRIGGER": 0, "AXIS_GAS": 0}}
+ ]
+ }
+
+
+]
\ No newline at end of file
diff --git a/tests/tests/hardware/res/raw/razer_serval_register.json b/tests/tests/hardware/res/raw/razer_serval_register.json
new file mode 100644
index 0000000..3d8bb96
--- /dev/null
+++ b/tests/tests/hardware/res/raw/razer_serval_register.json
@@ -0,0 +1,24 @@
+{
+ "id": 1,
+ "command": "register",
+ "name": "Razer Serval (Test)",
+ "vid": 0x1532,
+ "pid": 0x0900,
+ "descriptor": [
+ 0x05, 0x01, 0x09, 0x05, 0xa1, 0x01, 0xa1, 0x02, 0x85, 0x01, 0x75, 0x08, 0x95, 0x04,
+ 0x15, 0x00, 0x26, 0xff, 0x00, 0x09, 0x30, 0x09, 0x31, 0x09, 0x32, 0x09, 0x35, 0x81,
+ 0x02, 0x75, 0x04, 0x95, 0x01, 0x15, 0x00, 0x25, 0x07, 0x09, 0x39, 0x81, 0x42, 0x75,
+ 0x01, 0x95, 0x01, 0x15, 0x00, 0x25, 0x01, 0x05, 0x09, 0x09, 0x01, 0x81, 0x02, 0x09,
+ 0x02, 0x81, 0x02, 0x09, 0x04, 0x81, 0x02, 0x09, 0x05, 0x81, 0x02, 0x09, 0x07, 0x81,
+ 0x02, 0x09, 0x08, 0x81, 0x02, 0x05, 0x0c, 0x0a, 0x24, 0x02, 0x81, 0x02, 0x05, 0x09,
+ 0x09, 0x0c, 0x81, 0x02, 0x09, 0x0e, 0x81, 0x02, 0x09, 0x0f, 0x81, 0x02, 0x09, 0x0d,
+ 0x81, 0x02, 0x05, 0x0c, 0x0a, 0x23, 0x02, 0x81, 0x02, 0x05, 0x09, 0x09, 0x0b, 0x81,
+ 0x02, 0x75, 0x07, 0x95, 0x01, 0x81, 0x03, 0x75, 0x08, 0x95, 0x02, 0x15, 0x00, 0x26,
+ 0xff, 0x00, 0x05, 0x02, 0x09, 0xc5, 0x09, 0xc4, 0x81, 0x02, 0x75, 0x08, 0x95, 0x01,
+ 0x15, 0x00, 0x26, 0xff, 0x00, 0x05, 0x06, 0x09, 0x20, 0x81, 0x02, 0xc0, 0x05, 0xff,
+ 0x09, 0x02, 0x15, 0x00, 0x25, 0xff, 0x75, 0x08, 0x95, 0x5a, 0xb1, 0x01, 0x05, 0x07,
+ 0x85, 0x02, 0x05, 0x08, 0x09, 0x01, 0x09, 0x02, 0x09, 0x03, 0x09, 0x04, 0x09, 0x4f,
+ 0x09, 0x50, 0x09, 0x51, 0x09, 0x52, 0x15, 0x00, 0x25, 0x01, 0x75, 0x01, 0x95, 0x08,
+ 0x91, 0x02, 0xc0
+ ]
+}
diff --git a/tests/tests/hardware/src/android/hardware/input/cts/tests/RazerServalTest.java b/tests/tests/hardware/src/android/hardware/input/cts/tests/RazerServalTest.java
new file mode 100644
index 0000000..2122085
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/input/cts/tests/RazerServalTest.java
@@ -0,0 +1,46 @@
+/*
+ * 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 android.hardware.input.cts.tests;
+
+import android.hardware.cts.R;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.MediumTest;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@MediumTest
+@RunWith(AndroidJUnit4.class)
+public class RazerServalTest extends InputTestCase {
+ public RazerServalTest() {
+ super(R.raw.razer_serval_register);
+ }
+
+ /**
+ * Test all keys except the home key.
+ */
+ @Test
+ public void testAllKeys() {
+ testInputEvents(R.raw.razer_serval_keyeventtests);
+ }
+
+ @Test
+ public void testAllMotions() {
+ testInputEvents(R.raw.razer_serval_motioneventtests);
+ }
+}
diff --git a/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java b/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java
index 7e8be97..0847800 100644
--- a/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java
+++ b/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java
@@ -64,6 +64,7 @@
import android.security.keystore.KeyProperties;
import android.test.AndroidTestCase;
import android.util.ArraySet;
+import android.util.Log;
import com.google.common.collect.ImmutableSet;
@@ -99,6 +100,8 @@
*/
public class KeyAttestationTest extends AndroidTestCase {
+ private static final String TAG = AndroidKeyStoreTest.class.getSimpleName();
+
private static final int ORIGINATION_TIME_OFFSET = 1000000;
private static final int CONSUMPTION_TIME_OFFSET = 2000000;
@@ -880,7 +883,8 @@
RootOfTrust rootOfTrust = attestation.getTeeEnforced().getRootOfTrust();
assertNotNull(rootOfTrust);
assertNotNull(rootOfTrust.getVerifiedBootKey());
- assertTrue(rootOfTrust.getVerifiedBootKey().length >= 32);
+ assertTrue("Verified boot key is only " + rootOfTrust.getVerifiedBootKey().length +
+ " bytes long", rootOfTrust.getVerifiedBootKey().length >= 32);
checkEntropy(rootOfTrust.getVerifiedBootKey());
if (requireLocked) {
assertTrue(rootOfTrust.isDeviceLocked());
@@ -889,8 +893,8 @@
}
private void checkEntropy(byte[] verifiedBootKey) {
- assertTrue(checkShannonEntropy(verifiedBootKey));
- assertTrue(checkTresBiEntropy(verifiedBootKey));
+ assertTrue("Failed Shannon entropy check", checkShannonEntropy(verifiedBootKey));
+ assertTrue("Failed BiEntropy check", checkTresBiEntropy(verifiedBootKey));
}
private boolean checkShannonEntropy(byte[] verifiedBootKey) {
@@ -900,8 +904,10 @@
private double calculateShannonEntropy(double probabilityOfSetBit) {
if (probabilityOfSetBit <= 0.001 || probabilityOfSetBit >= .999) return 0;
- return (-probabilityOfSetBit * logTwo(probabilityOfSetBit)) -
- ((1 - probabilityOfSetBit) * logTwo(1 - probabilityOfSetBit));
+ double entropy = (-probabilityOfSetBit * logTwo(probabilityOfSetBit)) -
+ ((1 - probabilityOfSetBit) * logTwo(1 - probabilityOfSetBit));
+ Log.i(TAG, "Shannon entropy of VB Key: " + entropy);
+ return entropy;
}
private boolean checkTresBiEntropy(byte[] verifiedBootKey) {
@@ -917,6 +923,7 @@
length -= 1;
}
double tresBiEntropy = (1 / weightingFactor) * weightedEntropy;
+ Log.i(TAG, "BiEntropy of VB Key: " + tresBiEntropy);
return tresBiEntropy > 0.9;
}
diff --git a/tests/tests/media/res/raw/sinesweepwav24.wav b/tests/tests/media/res/raw/sinesweepwav24.wav
new file mode 100644
index 0000000..2657b5c
--- /dev/null
+++ b/tests/tests/media/res/raw/sinesweepwav24.wav
Binary files differ
diff --git a/tests/tests/media/src/android/media/cts/AudioPlaybackCaptureTest.java b/tests/tests/media/src/android/media/cts/AudioPlaybackCaptureTest.java
index c2c2a34..47b75bf 100644
--- a/tests/tests/media/src/android/media/cts/AudioPlaybackCaptureTest.java
+++ b/tests/tests/media/src/android/media/cts/AudioPlaybackCaptureTest.java
@@ -489,6 +489,8 @@
// Stopping one AR must allow creating a new one
audioRecords.peek().stop();
audioRecords.pop().release();
+ final long SLEEP_AFTER_STOP_FOR_INACTIVITY_MS = 1000;
+ Thread.sleep(SLEEP_AFTER_STOP_FOR_INACTIVITY_MS);
audioRecords.push(createDefaultPlaybackCaptureRecord());
// That new one must still be able to capture
diff --git a/tests/tests/media/src/android/media/cts/DecoderTest.java b/tests/tests/media/src/android/media/cts/DecoderTest.java
index 7f51672..22549e5 100644
--- a/tests/tests/media/src/android/media/cts/DecoderTest.java
+++ b/tests/tests/media/src/android/media/cts/DecoderTest.java
@@ -172,6 +172,10 @@
decode(R.raw.sinesweepwav, 0.0f);
testTimeStampOrdering(R.raw.sinesweepwav);
}
+ public void testDecodeWav24() throws Exception {
+ decode(R.raw.sinesweepwav24, 0.0f);
+ testTimeStampOrdering(R.raw.sinesweepwav24);
+ }
public void testDecodeFlacMkv() throws Exception {
decode(R.raw.sinesweepflacmkv, 0.0f);
testTimeStampOrdering(R.raw.sinesweepflacmkv);
@@ -3488,7 +3492,8 @@
assertTrue("No video track was found", trackIndex >= 0);
extractor.selectTrack(trackIndex);
- format.setFeatureEnabled(MediaFormat.KEY_LOW_LATENCY, true /* enable */);
+ format.setFeatureEnabled(MediaCodecInfo.CodecCapabilities.FEATURE_LowLatency,
+ true /* enable */);
MediaCodecList mcl = new MediaCodecList(MediaCodecList.ALL_CODECS);
String decoderName = mcl.findDecoderForFormat(format);
@@ -3506,6 +3511,8 @@
} else {
decoder = new SdkMediaCodec(MediaCodec.createByCodecName(decoderName));
}
+ format.removeFeature(MediaCodecInfo.CodecCapabilities.FEATURE_LowLatency);
+ format.setInteger(MediaFormat.KEY_LOW_LATENCY, 1);
decoder.configure(format, 0 /* flags */, surface);
decoder.start();
diff --git a/tests/tests/media/src/android/media/cts/HeifWriterTest.java b/tests/tests/media/src/android/media/cts/HeifWriterTest.java
index 79eda3b..068a5e7 100644
--- a/tests/tests/media/src/android/media/cts/HeifWriterTest.java
+++ b/tests/tests/media/src/android/media/cts/HeifWriterTest.java
@@ -40,28 +40,38 @@
import android.os.HandlerThread;
import android.os.Process;
import android.platform.test.annotations.AppModeFull;
+import android.platform.test.annotations.RequiresDevice;
+import android.system.ErrnoException;
+import android.system.Os;
+import android.system.OsConstants;
import android.test.AndroidTestCase;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.heifwriter.HeifWriter;
+import androidx.test.filters.SmallTest;
import com.android.compatibility.common.util.MediaUtils;
import java.io.Closeable;
import java.io.File;
+import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.io.RandomAccessFile;
import java.util.Arrays;
+@SmallTest
+@RequiresDevice
@AppModeFull(reason = "Instant apps cannot access the SD card")
public class HeifWriterTest extends AndroidTestCase {
private static final String TAG = HeifWriterTest.class.getSimpleName();
private static final boolean DEBUG = false;
+ private static final boolean DUMP_OUTPUT = false;
private static final boolean DUMP_YUV_INPUT = false;
private static final int GRID_WIDTH = 512;
private static final int GRID_HEIGHT = 512;
@@ -349,8 +359,13 @@
mHeight = 1080;
mRotation = 0;
mQuality = 100;
- mOutputPath = new File(Environment.getExternalStorageDirectory(),
- OUTPUT_FILENAME).getAbsolutePath();
+ // use memfd by default
+ if (DUMP_OUTPUT) {
+ mOutputPath = new File(Environment.getExternalStorageDirectory(),
+ OUTPUT_FILENAME).getAbsolutePath();
+ } else {
+ mOutputPath = null;
+ }
}
Builder setInputPath(String inputPath) {
@@ -395,9 +410,11 @@
}
private void cleanupStaleOutputs() {
- File outputFile = new File(mOutputPath);
- if (outputFile.exists()) {
- outputFile.delete();
+ if (mOutputPath != null) {
+ File outputFile = new File(mOutputPath);
+ if (outputFile.exists()) {
+ outputFile.delete();
+ }
}
}
@@ -434,13 +451,22 @@
mInputIndex = 0;
HeifWriter heifWriter = null;
- FileInputStream inputStream = null;
- FileOutputStream outputStream = null;
+ FileInputStream inputYuvStream = null;
+ FileOutputStream outputYuvStream = null;
+ FileDescriptor outputFd = null;
+ RandomAccessFile outputFile = null;
try {
if (DEBUG) Log.d(TAG, "started: " + config);
+ if (config.mOutputPath != null) {
+ outputFile = new RandomAccessFile(config.mOutputPath, "rws");
+ outputFile.setLength(0);
+ outputFd = outputFile.getFD();
+ } else {
+ outputFd = Os.memfd_create("temp", OsConstants.MFD_CLOEXEC);
+ }
heifWriter = new HeifWriter.Builder(
- config.mOutputPath, width, height, config.mInputMode)
+ outputFd, width, height, config.mInputMode)
.setRotation(config.mRotation)
.setGridEnabled(config.mUseGrid)
.setMaxImages(config.mMaxNumImages)
@@ -459,27 +485,27 @@
byte[] data = new byte[width * height * 3 / 2];
if (config.mInputPath != null) {
- inputStream = new FileInputStream(config.mInputPath);
+ inputYuvStream = new FileInputStream(config.mInputPath);
}
if (DUMP_YUV_INPUT) {
- File outputFile = new File("/sdcard/input.yuv");
- outputFile.createNewFile();
- outputStream = new FileOutputStream(outputFile);
+ File outputYuvFile = new File("/sdcard/input.yuv");
+ outputYuvFile.createNewFile();
+ outputYuvStream = new FileOutputStream(outputYuvFile);
}
for (int i = 0; i < actualNumImages; i++) {
if (DEBUG) Log.d(TAG, "fillYuvBuffer: " + i);
- fillYuvBuffer(i, data, width, height, inputStream);
+ fillYuvBuffer(i, data, width, height, inputYuvStream);
if (DUMP_YUV_INPUT) {
Log.d(TAG, "@@@ dumping input YUV");
- outputStream.write(data);
+ outputYuvStream.write(data);
}
heifWriter.addYuvBuffer(ImageFormat.YUV_420_888, data);
}
} else if (config.mInputMode == INPUT_MODE_SURFACE) {
// The input surface is a surface texture using single buffer mode, draws will be
- // blocked until onFrameAvailable is done with the buffer, which is dependant on
+ // blocked until onFrameAvailable is done with the buffer, which is dependent on
// how fast MediaCodec processes them, which is further dependent on how fast the
// MediaCodec callbacks are handled. We can't put draws on the same looper that
// handles MediaCodec callback, it will cause deadlock.
@@ -508,19 +534,25 @@
expectedPrimary = 0;
expectedImageCount = actualNumImages;
}
- verifyResult(config.mOutputPath, width, height, config.mRotation,
+ verifyResult(outputFd, width, height, config.mRotation,
expectedImageCount, expectedPrimary, config.mUseGrid,
config.mInputMode == INPUT_MODE_SURFACE);
if (DEBUG) Log.d(TAG, "finished: PASS");
} finally {
try {
- if (outputStream != null) {
- outputStream.close();
+ if (outputYuvStream != null) {
+ outputYuvStream.close();
}
- if (inputStream != null) {
- inputStream.close();
+ if (inputYuvStream != null) {
+ inputYuvStream.close();
}
- } catch (IOException e) {}
+ if (outputFile != null) {
+ outputFile.close();
+ }
+ if (outputFd != null) {
+ Os.close(outputFd);
+ }
+ } catch (IOException|ErrnoException e) {}
if (heifWriter != null) {
heifWriter.close();
@@ -608,14 +640,14 @@
}
private void verifyResult(
- String filename, int width, int height, int rotation,
+ FileDescriptor fd, int width, int height, int rotation,
int imageCount, int primary, boolean useGrid, boolean checkColor)
throws Exception {
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
- retriever.setDataSource(filename);
+ retriever.setDataSource(fd);
String hasImage = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_HAS_IMAGE);
if (!"yes".equals(hasImage)) {
- throw new Exception("No images found in file " + filename);
+ throw new Exception("No images found in file descriptor");
}
assertEquals("Wrong width", width,
Integer.parseInt(retriever.extractMetadata(
@@ -636,7 +668,7 @@
if (useGrid) {
MediaExtractor extractor = new MediaExtractor();
- extractor.setDataSource(filename);
+ extractor.setDataSource(fd);
MediaFormat format = extractor.getTrackFormat(0);
int tileWidth = format.getInteger(MediaFormat.KEY_TILE_WIDTH);
int tileHeight = format.getInteger(MediaFormat.KEY_TILE_HEIGHT);
@@ -650,7 +682,8 @@
}
if (checkColor) {
- Bitmap bitmap = BitmapFactory.decodeFile(filename);
+ Os.lseek(fd, 0, OsConstants.SEEK_SET);
+ Bitmap bitmap = BitmapFactory.decodeFileDescriptor(fd);
for (int i = 0; i < COLOR_BARS.length; i++) {
Rect r = getColorBarRect(i, width, height);
diff --git a/tests/tests/media/src/android/media/cts/MediaControllerTest.java b/tests/tests/media/src/android/media/cts/MediaControllerTest.java
index d6beefe..1dfdda4 100644
--- a/tests/tests/media/src/android/media/cts/MediaControllerTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaControllerTest.java
@@ -19,6 +19,7 @@
import static android.media.session.PlaybackState.STATE_PLAYING;
import android.content.Intent;
+import android.media.AudioAttributes;
import android.media.AudioManager;
import android.media.Rating;
import android.media.VolumeProvider;
@@ -128,6 +129,15 @@
assertEquals(EXTRAS_VALUE, sessionInfo.getString(EXTRAS_KEY));
}
+ public void testGetTag() {
+ try {
+ String tag = mController.getTag();
+ fail();
+ } catch (SecurityException e) {
+ // expected
+ }
+ }
+
public void testSendCommand() throws Exception {
synchronized (mWaitLock) {
mCallback.reset();
@@ -401,25 +411,6 @@
}
}
- /*
- public void testPlaybackInfo() {
- final int playbackType = MediaController.PlaybackInfo.PLAYBACK_TYPE_LOCAL;
- final int volumeControl = VolumeProvider.VOLUME_CONTROL_ABSOLUTE;
- final int maxVolume = 10;
- final int currentVolume = 3;
-
- AudioAttributes audioAttributes = new AudioAttributes.Builder().build();
- MediaController.PlaybackInfo info = new MediaController.PlaybackInfo(
- playbackType, audioAttributes, volumeControl, maxVolume, currentVolume);
-
- assertEquals(playbackType, info.getPlaybackType());
- assertEquals(audioAttributes, info.getAudioAttributes());
- assertEquals(volumeControl, info.getVolumeControl());
- assertEquals(maxVolume, info.getMaxVolume());
- assertEquals(currentVolume, info.getCurrentVolume());
- }
- */
-
private class MediaSessionCallback extends MediaSession.Callback {
private long mSeekPosition;
private long mQueueItemId;
diff --git a/tests/tests/media/src/android/media/cts/MediaDrmTest.java b/tests/tests/media/src/android/media/cts/MediaDrmTest.java
new file mode 100644
index 0000000..adc927e
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/MediaDrmTest.java
@@ -0,0 +1,58 @@
+/*
+ * 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 android.media.cts;
+
+import android.media.MediaDrm;
+import android.util.Log;
+import androidx.test.runner.AndroidJUnit4;
+import java.util.List;
+import java.util.UUID;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static junit.framework.Assert.assertTrue;
+import static org.testng.Assert.assertThrows;
+
+@NonMediaMainlineTest
+@RunWith(AndroidJUnit4.class)
+public class MediaDrmTest {
+
+ private final String TAG = this.getClass().getName();
+
+ private void testSingleScheme(UUID scheme) throws Exception {
+ MediaDrm md = new MediaDrm(scheme);
+ assertTrue(md.getOpenSessionCount() <= md.getMaxSessionCount());
+ assertThrows(() -> {
+ md.closeSession(null);
+ });
+ md.close();
+ }
+
+ @Test
+ public void testSupportedCryptoSchemes() throws Exception {
+ List<UUID> supportedCryptoSchemes = MediaDrm.getSupportedCryptoSchemes();
+ if (supportedCryptoSchemes.isEmpty()) {
+ Log.w(TAG, "No supported crypto schemes reported");
+ }
+ for (UUID scheme : supportedCryptoSchemes) {
+ Log.d(TAG, "supported scheme: " + scheme.toString());
+ assertTrue(MediaDrm.isCryptoSchemeSupported(scheme));
+ testSingleScheme(scheme);
+ }
+ }
+
+}
diff --git a/tests/tests/media/src/android/media/cts/MediaExtractorTest.java b/tests/tests/media/src/android/media/cts/MediaExtractorTest.java
index 707ff52..21149c6 100644
--- a/tests/tests/media/src/android/media/cts/MediaExtractorTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaExtractorTest.java
@@ -27,6 +27,7 @@
import android.media.MediaDataSource;
import android.media.MediaExtractor;
import android.media.MediaFormat;
+import static android.media.MediaFormat.MIMETYPE_VIDEO_DOLBY_VISION;
import android.media.cts.R;
import android.os.PersistableBundle;
import android.platform.test.annotations.AppModeFull;
@@ -36,6 +37,8 @@
import androidx.test.filters.SmallTest;
+import com.android.compatibility.common.util.MediaUtils;
+
import java.io.BufferedReader;
import java.io.Closeable;
import java.io.IOException;
@@ -50,6 +53,7 @@
import java.util.SortedMap;
import java.util.TreeMap;
+
public class MediaExtractorTest extends AndroidTestCase {
private static final String TAG = "MediaExtractorTest";
@@ -135,24 +139,46 @@
public void testDolbyVisionMediaExtractorProfileDvheDtr() throws Exception {
TestMediaDataSource dataSource = setDataSource(R.raw.video_dovi_1920x1080_30fps_dvhe_04);
- assertEquals(2, mExtractor.getTrackCount());
+ assertTrue("There should be either 1 or 2 tracks",
+ 0 < mExtractor.getTrackCount() && 3 > mExtractor.getTrackCount());
- // First track should be a track with dolby-vision mime
MediaFormat trackFormat = mExtractor.getTrackFormat(0);
- String mimeType = trackFormat.getString(MediaFormat.KEY_MIME);
+ int trackCountForDolbyVision = 1;
- assertEquals("video/dolby-vision", mimeType);
+ // Handle the case where there is a Dolby Vision extractor
+ // Note that it may or may not have a Dolby Vision Decoder
+ if (mExtractor.getTrackCount() == 2) {
+ if (trackFormat.getString(MediaFormat.KEY_MIME)
+ .equalsIgnoreCase(MIMETYPE_VIDEO_DOLBY_VISION)) {
+ trackFormat = mExtractor.getTrackFormat(1);
+ trackCountForDolbyVision = 0;
+ }
+ }
- int profile = trackFormat.getInteger(MediaFormat.KEY_PROFILE);;
- int level = trackFormat.getInteger(MediaFormat.KEY_LEVEL);;
+ if (MediaUtils.hasDecoder(MIMETYPE_VIDEO_DOLBY_VISION)) {
+ assertEquals("There must be 2 tracks", 2, mExtractor.getTrackCount());
- assertEquals(MediaCodecInfo.CodecProfileLevel.DolbyVisionProfileDvheDtr, profile);
- assertEquals(MediaCodecInfo.CodecProfileLevel.DolbyVisionLevelFhd30, level);
+ MediaFormat trackFormatForDolbyVision =
+ mExtractor.getTrackFormat(trackCountForDolbyVision);
- // The second track should be with the mime video/hevc for backward compatibility
- trackFormat = mExtractor.getTrackFormat(1);
- mimeType = trackFormat.getString(MediaFormat.KEY_MIME);
+ final String mimeType = trackFormatForDolbyVision.getString(MediaFormat.KEY_MIME);
+ assertEquals("video/dolby-vision", mimeType);
+ int profile = trackFormatForDolbyVision.getInteger(MediaFormat.KEY_PROFILE);
+ assertEquals(MediaCodecInfo.CodecProfileLevel.DolbyVisionProfileDvheDtr, profile);
+
+ int level = trackFormatForDolbyVision.getInteger(MediaFormat.KEY_LEVEL);
+ assertEquals(MediaCodecInfo.CodecProfileLevel.DolbyVisionLevelFhd30, level);
+
+ final int trackIdForDolbyVision =
+ trackFormatForDolbyVision.getInteger(MediaFormat.KEY_TRACK_ID);
+
+ final int trackIdForBackwardCompat = trackFormat.getInteger(MediaFormat.KEY_TRACK_ID);
+ assertEquals(trackIdForDolbyVision, trackIdForBackwardCompat);
+ }
+
+ // The backward-compatible track should have mime video/hevc
+ final String mimeType = trackFormat.getString(MediaFormat.KEY_MIME);
assertEquals("video/hevc", mimeType);
}
@@ -160,43 +186,68 @@
public void testDolbyVisionMediaExtractorProfileDvheStn() throws Exception {
TestMediaDataSource dataSource = setDataSource(R.raw.video_dovi_1920x1080_60fps_dvhe_05);
- assertEquals(1, mExtractor.getTrackCount());
+ if (MediaUtils.hasDecoder(MIMETYPE_VIDEO_DOLBY_VISION)) {
+ // DvheStn exposes only a single non-backward compatible Dolby Vision HDR track.
+ assertEquals("There must be 1 track", 1, mExtractor.getTrackCount());
+ final MediaFormat trackFormat = mExtractor.getTrackFormat(0);
- // DvheStn exposes only a single non-backward compatible Dolby Vision HDR track.
- MediaFormat trackFormat = mExtractor.getTrackFormat(0);
- final String mimeType = trackFormat.getString(MediaFormat.KEY_MIME);
+ final String mimeType = trackFormat.getString(MediaFormat.KEY_MIME);
+ assertEquals("video/dolby-vision", mimeType);
- assertEquals("video/dolby-vision", mimeType);
+ final int profile = trackFormat.getInteger(MediaFormat.KEY_PROFILE);
+ assertEquals(MediaCodecInfo.CodecProfileLevel.DolbyVisionProfileDvheStn, profile);
- final int profile = trackFormat.getInteger(MediaFormat.KEY_PROFILE);;
- final int level = trackFormat.getInteger(MediaFormat.KEY_LEVEL);;
-
- assertEquals(MediaCodecInfo.CodecProfileLevel.DolbyVisionProfileDvheStn, profile);
- assertEquals(MediaCodecInfo.CodecProfileLevel.DolbyVisionLevelFhd60, level);
+ final int level = trackFormat.getInteger(MediaFormat.KEY_LEVEL);
+ assertEquals(MediaCodecInfo.CodecProfileLevel.DolbyVisionLevelFhd60, level);
+ } else {
+ MediaUtils.skipTest("Device does not provide a Dolby Vision decoder");
+ }
}
// DolbyVisionMediaExtractor for profile-level (DvheSt/Fhd60).
public void testDolbyVisionMediaExtractorProfileDvheSt() throws Exception {
TestMediaDataSource dataSource = setDataSource(R.raw.video_dovi_1920x1080_60fps_dvhe_08);
- assertEquals(2, mExtractor.getTrackCount());
+ assertTrue("There should be either 1 or 2 tracks",
+ 0 < mExtractor.getTrackCount() && 3 > mExtractor.getTrackCount());
- // First track should be a track with dolby-vision mime
MediaFormat trackFormat = mExtractor.getTrackFormat(0);
- String mimeType = trackFormat.getString(MediaFormat.KEY_MIME);
+ int trackCountForDolbyVision = 1;
- assertEquals("video/dolby-vision", mimeType);
+ // Handle the case where there is a Dolby Vision extractor
+ // Note that it may or may not have a Dolby Vision Decoder
+ if (mExtractor.getTrackCount() == 2) {
+ if (trackFormat.getString(MediaFormat.KEY_MIME)
+ .equalsIgnoreCase(MIMETYPE_VIDEO_DOLBY_VISION)) {
+ trackFormat = mExtractor.getTrackFormat(1);
+ trackCountForDolbyVision = 0;
+ }
+ }
- final int profile = trackFormat.getInteger(MediaFormat.KEY_PROFILE);;
- final int level = trackFormat.getInteger(MediaFormat.KEY_LEVEL);;
+ if (MediaUtils.hasDecoder(MIMETYPE_VIDEO_DOLBY_VISION)) {
+ assertEquals("There must be 2 tracks", 2, mExtractor.getTrackCount());
- assertEquals(MediaCodecInfo.CodecProfileLevel.DolbyVisionProfileDvheSt, profile);
- assertEquals(MediaCodecInfo.CodecProfileLevel.DolbyVisionLevelFhd60, level);
+ MediaFormat trackFormatForDolbyVision =
+ mExtractor.getTrackFormat(trackCountForDolbyVision);
- // The second track should be with the mime video/hevc for backward compatibility
- trackFormat = mExtractor.getTrackFormat(1);
- mimeType = trackFormat.getString(MediaFormat.KEY_MIME);
+ final String mimeType = trackFormatForDolbyVision.getString(MediaFormat.KEY_MIME);
+ assertEquals("video/dolby-vision", mimeType);
+ int profile = trackFormatForDolbyVision.getInteger(MediaFormat.KEY_PROFILE);
+ assertEquals(MediaCodecInfo.CodecProfileLevel.DolbyVisionProfileDvheSt, profile);
+
+ int level = trackFormatForDolbyVision.getInteger(MediaFormat.KEY_LEVEL);
+ assertEquals(MediaCodecInfo.CodecProfileLevel.DolbyVisionLevelFhd60, level);
+
+ final int trackIdForDolbyVision =
+ trackFormatForDolbyVision.getInteger(MediaFormat.KEY_TRACK_ID);
+
+ final int trackIdForBackwardCompat = trackFormat.getInteger(MediaFormat.KEY_TRACK_ID);
+ assertEquals(trackIdForDolbyVision, trackIdForBackwardCompat);
+ }
+
+ // The backward-compatible track should have mime video/hevc
+ final String mimeType = trackFormat.getString(MediaFormat.KEY_MIME);
assertEquals("video/hevc", mimeType);
}
@@ -204,69 +255,118 @@
public void testDolbyVisionMediaExtractorProfileDvavSe() throws Exception {
TestMediaDataSource dataSource = setDataSource(R.raw.video_dovi_1920x1080_60fps_dvav_09);
- assertEquals(2, mExtractor.getTrackCount());
+ assertTrue("There should be either 1 or 2 tracks",
+ 0 < mExtractor.getTrackCount() && 3 > mExtractor.getTrackCount());
- // First track should be a track with dolby-vision mime
MediaFormat trackFormat = mExtractor.getTrackFormat(0);
- String mimeType = trackFormat.getString(MediaFormat.KEY_MIME);
+ int trackCountForDolbyVision = 1;
- assertEquals("video/dolby-vision", mimeType);
+ // Handle the case where there is a Dolby Vision extractor
+ // Note that it may or may not have a Dolby Vision Decoder
+ if (mExtractor.getTrackCount() == 2) {
+ if (trackFormat.getString(MediaFormat.KEY_MIME)
+ .equalsIgnoreCase(MIMETYPE_VIDEO_DOLBY_VISION)) {
+ trackFormat = mExtractor.getTrackFormat(1);
+ trackCountForDolbyVision = 0;
+ }
+ }
- final int profile = trackFormat.getInteger(MediaFormat.KEY_PROFILE);;
- final int level = trackFormat.getInteger(MediaFormat.KEY_LEVEL);;
+ if (MediaUtils.hasDecoder(MIMETYPE_VIDEO_DOLBY_VISION)) {
+ assertEquals("There must be 2 tracks", 2, mExtractor.getTrackCount());
- assertEquals(MediaCodecInfo.CodecProfileLevel.DolbyVisionProfileDvavSe, profile);
- assertEquals(MediaCodecInfo.CodecProfileLevel.DolbyVisionLevelFhd60, level);
+ MediaFormat trackFormatForDolbyVision =
+ mExtractor.getTrackFormat(trackCountForDolbyVision);
- // The second track should be with the mime video/hevc for backward compatibility
- trackFormat = mExtractor.getTrackFormat(1);
- mimeType = trackFormat.getString(MediaFormat.KEY_MIME);
+ final String mimeType = trackFormatForDolbyVision.getString(MediaFormat.KEY_MIME);
+ assertEquals("video/dolby-vision", mimeType);
+ int profile = trackFormatForDolbyVision.getInteger(MediaFormat.KEY_PROFILE);
+ assertEquals(MediaCodecInfo.CodecProfileLevel.DolbyVisionProfileDvavSe, profile);
+
+ int level = trackFormatForDolbyVision.getInteger(MediaFormat.KEY_LEVEL);
+ assertEquals(MediaCodecInfo.CodecProfileLevel.DolbyVisionLevelFhd60, level);
+
+ final int trackIdForDolbyVision =
+ trackFormatForDolbyVision.getInteger(MediaFormat.KEY_TRACK_ID);
+
+ final int trackIdForBackwardCompat = trackFormat.getInteger(MediaFormat.KEY_TRACK_ID);
+ assertEquals(trackIdForDolbyVision, trackIdForBackwardCompat);
+ }
+
+ // The backward-compatible track should have mime video/avc
+ final String mimeType = trackFormat.getString(MediaFormat.KEY_MIME);
assertEquals("video/avc", mimeType);
-
}
// DolbyVisionMediaExtractor for profile-level (Dvav1 10.0/Uhd30)
+ @SmallTest
public void testDolbyVisionMediaExtractorProfileDvav1() throws Exception {
TestMediaDataSource dataSource = setDataSource(R.raw.video_dovi_3840x2160_30fps_dav1_10);
- assertEquals(1, mExtractor.getTrackCount());
+ if (MediaUtils.hasDecoder(MIMETYPE_VIDEO_DOLBY_VISION)) {
+ assertEquals(1, mExtractor.getTrackCount());
- // Dvav1 10 exposes a single backward compatible track.
- MediaFormat trackFormat = mExtractor.getTrackFormat(0);
- final String mimeType = trackFormat.getString(MediaFormat.KEY_MIME);
+ // Dvav1 10 exposes a single backward compatible track.
+ final MediaFormat trackFormat = mExtractor.getTrackFormat(0);
+ final String mimeType = trackFormat.getString(MediaFormat.KEY_MIME);
- assertEquals("video/dolby-vision", mimeType);
+ assertEquals("video/dolby-vision", mimeType);
- final int profile = trackFormat.getInteger(MediaFormat.KEY_PROFILE);;
- final int level = trackFormat.getInteger(MediaFormat.KEY_LEVEL);;
+ final int profile = trackFormat.getInteger(MediaFormat.KEY_PROFILE);
+ final int level = trackFormat.getInteger(MediaFormat.KEY_LEVEL);
- assertEquals(MediaCodecInfo.CodecProfileLevel.DolbyVisionProfileDvav110, profile);
- assertEquals(MediaCodecInfo.CodecProfileLevel.DolbyVisionLevelUhd30, level);
+ assertEquals(MediaCodecInfo.CodecProfileLevel.DolbyVisionProfileDvav110, profile);
+ assertEquals(MediaCodecInfo.CodecProfileLevel.DolbyVisionLevelUhd30, level);
+ } else {
+ MediaUtils.skipTest("Device does not provide a Dolby Vision decoder");
+ }
}
// DolbyVisionMediaExtractor for profile-level (Dvav1 10.1/Uhd30)
+ @SmallTest
public void testDolbyVisionMediaExtractorProfileDvav1_2() throws Exception {
TestMediaDataSource dataSource = setDataSource(R.raw.video_dovi_3840x2160_30fps_dav1_10_2);
- assertEquals(2, mExtractor.getTrackCount());
+ assertTrue("There should be either 1 or 2 tracks",
+ 0 < mExtractor.getTrackCount() && 3 > mExtractor.getTrackCount());
- // First track should be a track with dolby-vision mime
MediaFormat trackFormat = mExtractor.getTrackFormat(0);
- String mimeType = trackFormat.getString(MediaFormat.KEY_MIME);
+ int trackCountForDolbyVision = 1;
- assertEquals("video/dolby-vision", mimeType);
+ // Handle the case where there is a Dolby Vision extractor
+ // Note that it may or may not have a Dolby Vision Decoder
+ if (mExtractor.getTrackCount() == 2) {
+ if (trackFormat.getString(MediaFormat.KEY_MIME)
+ .equalsIgnoreCase(MIMETYPE_VIDEO_DOLBY_VISION)) {
+ trackFormat = mExtractor.getTrackFormat(1);
+ trackCountForDolbyVision = 0;
+ }
+ }
- final int profile = trackFormat.getInteger(MediaFormat.KEY_PROFILE);;
- final int level = trackFormat.getInteger(MediaFormat.KEY_LEVEL);;
+ if (MediaUtils.hasDecoder(MIMETYPE_VIDEO_DOLBY_VISION)) {
+ assertEquals("There must be 2 tracks", 2, mExtractor.getTrackCount());
- assertEquals(MediaCodecInfo.CodecProfileLevel.DolbyVisionProfileDvav110, profile);
- assertEquals(MediaCodecInfo.CodecProfileLevel.DolbyVisionLevelUhd30, level);
+ MediaFormat trackFormatForDolbyVision =
+ mExtractor.getTrackFormat(trackCountForDolbyVision);
- // The second track should be with the mime video/av01 for backward compatibility
- trackFormat = mExtractor.getTrackFormat(1);
- mimeType = trackFormat.getString(MediaFormat.KEY_MIME);
+ final String mimeType = trackFormatForDolbyVision.getString(MediaFormat.KEY_MIME);
+ assertEquals("video/dolby-vision", mimeType);
+ int profile = trackFormatForDolbyVision.getInteger(MediaFormat.KEY_PROFILE);
+ assertEquals(MediaCodecInfo.CodecProfileLevel.DolbyVisionProfileDvav110, profile);
+
+ int level = trackFormatForDolbyVision.getInteger(MediaFormat.KEY_LEVEL);
+ assertEquals(MediaCodecInfo.CodecProfileLevel.DolbyVisionLevelUhd30, level);
+
+ final int trackIdForDolbyVision =
+ trackFormatForDolbyVision.getInteger(MediaFormat.KEY_TRACK_ID);
+
+ final int trackIdForBackwardCompat = trackFormat.getInteger(MediaFormat.KEY_TRACK_ID);
+ assertEquals(trackIdForDolbyVision, trackIdForBackwardCompat);
+ }
+
+ // The backward-compatible track should have mime video/av01
+ final String mimeType = trackFormat.getString(MediaFormat.KEY_MIME);
assertEquals("video/av01", mimeType);
}
diff --git a/tests/tests/media/src/android/media/cts/MediaMetricsTest.java b/tests/tests/media/src/android/media/cts/MediaMetricsTest.java
new file mode 100644
index 0000000..7898b2d
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/MediaMetricsTest.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright 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 android.media.cts;
+
+import static org.junit.Assert.assertEquals;
+
+import android.media.MediaMetrics;
+import android.os.Bundle;
+import android.os.Process;
+import androidx.test.runner.AndroidJUnit4;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Tests for MediaMetrics item handling.
+ */
+
+@NonMediaMainlineTest
+@RunWith(AndroidJUnit4.class)
+public class MediaMetricsTest {
+
+ /**
+ * This tests MediaMetrics item creation.
+ */
+ @Test
+ public void testBasicItem() {
+ final String key = "Key";
+ final MediaMetrics.Item item = new MediaMetrics.Item(key);
+
+ item.putInt("int", (int) 1)
+ .putLong("long", (long) 2)
+ .putString("string", "ABCD")
+ .putDouble("double", (double) 3.1);
+
+ // Verify what is in the item by converting to a bundle.
+ // This uses special MediaMetrics.Item APIs for CTS test.
+ // The BUNDLE_* string keys represent internal Item data to be verified.
+ final Bundle bundle = item.toBundle();
+
+ assertEquals(1, bundle.getInt("int"));
+ assertEquals(2, bundle.getLong("long"));
+ assertEquals("ABCD", bundle.getString("string"));
+ assertEquals(3.1, bundle.getDouble("double"), 1e-6 /* delta */);
+
+ assertEquals("Key", bundle.getString(MediaMetrics.Item.BUNDLE_KEY));
+ assertEquals(-1, bundle.getInt(MediaMetrics.Item.BUNDLE_PID)); // default PID
+ assertEquals(-1, bundle.getInt(MediaMetrics.Item.BUNDLE_UID)); // default UID
+ assertEquals(0, bundle.getChar(MediaMetrics.Item.BUNDLE_VERSION));
+ assertEquals(key.length() + 1, bundle.getChar(MediaMetrics.Item.BUNDLE_KEY_SIZE));
+ assertEquals(0, bundle.getLong(MediaMetrics.Item.BUNDLE_TIMESTAMP)); // default Time
+ assertEquals(4, bundle.getInt(MediaMetrics.Item.BUNDLE_PROPERTY_COUNT));
+ }
+
+ /**
+ * This tests MediaMetrics item buffer expansion when the initial buffer capacity is set to 1.
+ */
+ @Test
+ public void testBigItem() {
+ final String key = "Key";
+ final int intKeyCount = 10000;
+ final MediaMetrics.Item item = new MediaMetrics.Item(
+ key, 1 /* pid */, 2 /* uid */, 3 /* time */, 1 /* capacity */);
+
+ item.putInt("int", (int) 1)
+ .putLong("long", (long) 2)
+ .putString("string", "ABCD")
+ .putDouble("double", (double) 3.1);
+
+ // Putting 10000 int properties forces the item to reallocate the buffer several times.
+ for (Integer i = 0; i < intKeyCount; ++i) {
+ item.putInt(i.toString(), i);
+ }
+
+ // Verify what is in the item by converting to a bundle.
+ // This uses special MediaMetrics.Item APIs for CTS test.
+ // The BUNDLE_* string keys represent internal Item data to be verified.
+ final Bundle bundle = item.toBundle();
+
+ assertEquals(1, bundle.getInt("int"));
+ assertEquals(2, bundle.getLong("long"));
+ assertEquals("ABCD", bundle.getString("string"));
+ assertEquals(3.1, bundle.getDouble("double"), 1e-6 /* delta */);
+
+ assertEquals(key, bundle.getString(MediaMetrics.Item.BUNDLE_KEY));
+ assertEquals(1, bundle.getInt(MediaMetrics.Item.BUNDLE_PID));
+ assertEquals(2, bundle.getInt(MediaMetrics.Item.BUNDLE_UID));
+ assertEquals(0, bundle.getChar(MediaMetrics.Item.BUNDLE_VERSION));
+ assertEquals(key.length() + 1, bundle.getChar(MediaMetrics.Item.BUNDLE_KEY_SIZE));
+ assertEquals(3, bundle.getLong(MediaMetrics.Item.BUNDLE_TIMESTAMP));
+
+ for (Integer i = 0; i < intKeyCount; ++i) {
+ assertEquals((int) i, bundle.getInt(i.toString()));
+ }
+
+ assertEquals(intKeyCount + 4, bundle.getInt(MediaMetrics.Item.BUNDLE_PROPERTY_COUNT));
+
+ item.clear(); // removes properties.
+ item.putInt("value", (int) 100);
+
+ final Bundle bundle2 = item.toBundle();
+
+ assertEquals(key, bundle2.getString(MediaMetrics.Item.BUNDLE_KEY));
+ assertEquals(1, bundle2.getInt(MediaMetrics.Item.BUNDLE_PID));
+ assertEquals(2, bundle2.getInt(MediaMetrics.Item.BUNDLE_UID));
+ assertEquals(0, bundle2.getChar(MediaMetrics.Item.BUNDLE_VERSION));
+ assertEquals(key.length() + 1, bundle2.getChar(MediaMetrics.Item.BUNDLE_KEY_SIZE));
+ assertEquals(0, bundle2.getLong(MediaMetrics.Item.BUNDLE_TIMESTAMP)); // time is reset.
+
+ for (Integer i = 0; i < intKeyCount; ++i) {
+ assertEquals(-1, bundle2.getInt(i.toString(), -1));
+ }
+ assertEquals(100, bundle2.getInt("value"));
+ assertEquals(1, bundle2.getInt(MediaMetrics.Item.BUNDLE_PROPERTY_COUNT));
+
+ // Now override pid, uid, and time.
+ item.setPid(10)
+ .setUid(11)
+ .setTimestamp(12);
+ final Bundle bundle3 = item.toBundle();
+ assertEquals(10, bundle3.getInt(MediaMetrics.Item.BUNDLE_PID));
+ assertEquals(11, bundle3.getInt(MediaMetrics.Item.BUNDLE_UID));
+ assertEquals(12, bundle3.getLong(MediaMetrics.Item.BUNDLE_TIMESTAMP));
+ }
+}
diff --git a/tests/tests/media/src/android/media/cts/MediaScannerTest.java b/tests/tests/media/src/android/media/cts/MediaScannerTest.java
index 4f27289..8cb6f3d 100644
--- a/tests/tests/media/src/android/media/cts/MediaScannerTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaScannerTest.java
@@ -618,14 +618,14 @@
public static void startMediaScan() {
new Thread(() -> {
- MediaStore.scanVolume(InstrumentationRegistry.getTargetContext(),
- Environment.getExternalStorageDirectory());
+ MediaStore.scanVolume(InstrumentationRegistry.getTargetContext().getContentResolver(),
+ MediaStore.VOLUME_EXTERNAL_PRIMARY);
}).start();
}
public static void startMediaScanAndWait() {
- MediaStore.scanVolume(InstrumentationRegistry.getTargetContext(),
- Environment.getExternalStorageDirectory());
+ MediaStore.scanVolume(InstrumentationRegistry.getTargetContext().getContentResolver(),
+ MediaStore.VOLUME_EXTERNAL_PRIMARY);
}
private void checkMediaScannerConnection() {
diff --git a/tests/tests/media/src/android/media/cts/ResourceManagerTestActivity2.java b/tests/tests/media/src/android/media/cts/ResourceManagerTestActivity2.java
index 79d0d2d..ea0567f 100644
--- a/tests/tests/media/src/android/media/cts/ResourceManagerTestActivity2.java
+++ b/tests/tests/media/src/android/media/cts/ResourceManagerTestActivity2.java
@@ -22,11 +22,11 @@
public class ResourceManagerTestActivity2 extends ResourceManagerTestActivityBase {
@Override
- protected void onCreate(Bundle savedInstanceState) {
+ protected void onResume() {
TAG = "ResourceManagerTestActivity2";
- Log.d(TAG, "onCreate called.");
- super.onCreate(savedInstanceState);
+ Log.d(TAG, "onResume called.");
+ super.onResume();
int result = (allocateCodecs(1 /* max */) == 1) ? RESULT_OK : RESULT_CANCELED;
finishWithResult(result);
diff --git a/tests/tests/net/src/android/net/cts/MacAddressTest.java b/tests/tests/net/src/android/net/cts/MacAddressTest.java
index af1e760..4d25e62 100644
--- a/tests/tests/net/src/android/net/cts/MacAddressTest.java
+++ b/tests/tests/net/src/android/net/cts/MacAddressTest.java
@@ -20,6 +20,11 @@
import static android.net.MacAddress.TYPE_MULTICAST;
import static android.net.MacAddress.TYPE_UNICAST;
+import static com.android.testutils.ParcelUtilsKt.assertParcelSane;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import android.net.MacAddress;
@@ -30,6 +35,7 @@
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.net.Inet6Address;
import java.util.Arrays;
@SmallTest
@@ -161,4 +167,57 @@
} catch (NullPointerException excepted) {
}
}
+
+ @Test
+ public void testMatches() {
+ // match 4 bytes prefix
+ assertTrue(MacAddress.fromString("aa:bb:cc:dd:ee:11").matches(
+ MacAddress.fromString("aa:bb:cc:dd:00:00"),
+ MacAddress.fromString("ff:ff:ff:ff:00:00")));
+
+ // match bytes 0,1,2 and 5
+ assertTrue(MacAddress.fromString("aa:bb:cc:dd:ee:11").matches(
+ MacAddress.fromString("aa:bb:cc:00:00:11"),
+ MacAddress.fromString("ff:ff:ff:00:00:ff")));
+
+ // match 34 bit prefix
+ assertTrue(MacAddress.fromString("aa:bb:cc:dd:ee:11").matches(
+ MacAddress.fromString("aa:bb:cc:dd:c0:00"),
+ MacAddress.fromString("ff:ff:ff:ff:c0:00")));
+
+ // fail to match 36 bit prefix
+ assertFalse(MacAddress.fromString("aa:bb:cc:dd:ee:11").matches(
+ MacAddress.fromString("aa:bb:cc:dd:40:00"),
+ MacAddress.fromString("ff:ff:ff:ff:f0:00")));
+
+ // match all 6 bytes
+ assertTrue(MacAddress.fromString("aa:bb:cc:dd:ee:11").matches(
+ MacAddress.fromString("aa:bb:cc:dd:ee:11"),
+ MacAddress.fromString("ff:ff:ff:ff:ff:ff")));
+
+ // match none of 6 bytes
+ assertTrue(MacAddress.fromString("aa:bb:cc:dd:ee:11").matches(
+ MacAddress.fromString("00:00:00:00:00:00"),
+ MacAddress.fromString("00:00:00:00:00:00")));
+ }
+
+ /**
+ * Tests that link-local address generation from MAC is valid.
+ */
+ @Test
+ public void testLinkLocalFromMacGeneration() {
+ final MacAddress mac = MacAddress.fromString("52:74:f2:b1:a8:7f");
+ final byte[] inet6ll = {(byte) 0xfe, (byte) 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50,
+ 0x74, (byte) 0xf2, (byte) 0xff, (byte) 0xfe, (byte) 0xb1, (byte) 0xa8, 0x7f};
+ final Inet6Address llv6 = mac.getLinkLocalIpv6FromEui48Mac();
+ assertTrue(llv6.isLinkLocalAddress());
+ assertArrayEquals(inet6ll, llv6.getAddress());
+ }
+
+ @Test
+ public void testParcelMacAddress() {
+ final MacAddress mac = MacAddress.fromString("52:74:f2:b1:a8:7f");
+
+ assertParcelSane(mac, 1);
+ }
}
diff --git a/tests/tests/net/src/android/net/wifi/p2p/cts/WifiP2pConfigTest.java b/tests/tests/net/src/android/net/wifi/p2p/cts/WifiP2pConfigTest.java
index 639db8a..e93d573 100644
--- a/tests/tests/net/src/android/net/wifi/p2p/cts/WifiP2pConfigTest.java
+++ b/tests/tests/net/src/android/net/wifi/p2p/cts/WifiP2pConfigTest.java
@@ -22,41 +22,41 @@
import android.test.AndroidTestCase;
public class WifiP2pConfigTest extends AndroidTestCase {
- static final String TEST_NETWORK_NAME = "DIRECT-xy-Hello";
- static final String TEST_PASSPHRASE = "8etterW0r1d";
- static final int TEST_OWNER_BAND = WifiP2pConfig.GROUP_OWNER_BAND_5GHZ;
- static final int TEST_OWNER_FREQ = 2447;
- static final String TEST_DEVICE_ADDRESS = "aa:bb:cc:dd:ee:ff";
+ private static final String TEST_NETWORK_NAME = "DIRECT-xy-Hello";
+ private static final String TEST_PASSPHRASE = "8etterW0r1d";
+ private static final int TEST_OWNER_BAND = WifiP2pConfig.GROUP_OWNER_BAND_5GHZ;
+ private static final int TEST_OWNER_FREQ = 2447;
+ private static final String TEST_DEVICE_ADDRESS = "aa:bb:cc:dd:ee:ff";
public void testWifiP2pConfigBuilderForPersist() {
- WifiP2pConfig.Builder builder = new WifiP2pConfig.Builder();
- builder.setNetworkName(TEST_NETWORK_NAME)
+ WifiP2pConfig config = new WifiP2pConfig.Builder()
+ .setNetworkName(TEST_NETWORK_NAME)
.setPassphrase(TEST_PASSPHRASE)
.setGroupOperatingBand(TEST_OWNER_BAND)
.setDeviceAddress(MacAddress.fromString(TEST_DEVICE_ADDRESS))
- .enablePersistentMode(true);
- WifiP2pConfig config = builder.build();
+ .enablePersistentMode(true)
+ .build();
- assertTrue(config.deviceAddress.equals(TEST_DEVICE_ADDRESS));
- assertTrue(config.networkName.equals(TEST_NETWORK_NAME));
- assertTrue(config.passphrase.equals(TEST_PASSPHRASE));
- assertEquals(config.groupOwnerBand, TEST_OWNER_BAND);
- assertEquals(config.netId, WifiP2pGroup.PERSISTENT_NET_ID);
+ assertEquals(config.deviceAddress, TEST_DEVICE_ADDRESS);
+ assertEquals(config.getNetworkName(), TEST_NETWORK_NAME);
+ assertEquals(config.getPassphrase(), TEST_PASSPHRASE);
+ assertEquals(config.getGroupOwnerBand(), TEST_OWNER_BAND);
+ assertEquals(config.getNetworkId(), WifiP2pGroup.PERSISTENT_NET_ID);
}
public void testWifiP2pConfigBuilderForNonPersist() {
- WifiP2pConfig.Builder builder = new WifiP2pConfig.Builder();
- builder.setNetworkName(TEST_NETWORK_NAME)
+ WifiP2pConfig config = new WifiP2pConfig.Builder()
+ .setNetworkName(TEST_NETWORK_NAME)
.setPassphrase(TEST_PASSPHRASE)
.setGroupOperatingFrequency(TEST_OWNER_FREQ)
.setDeviceAddress(MacAddress.fromString(TEST_DEVICE_ADDRESS))
- .enablePersistentMode(false);
- WifiP2pConfig config = builder.build();
+ .enablePersistentMode(false)
+ .build();
- assertTrue(config.deviceAddress.equals(TEST_DEVICE_ADDRESS));
- assertTrue(config.networkName.equals(TEST_NETWORK_NAME));
- assertTrue(config.passphrase.equals(TEST_PASSPHRASE));
- assertEquals(config.groupOwnerBand, TEST_OWNER_FREQ);
- assertEquals(config.netId, WifiP2pGroup.TEMPORARY_NET_ID);
+ assertEquals(config.deviceAddress, TEST_DEVICE_ADDRESS);
+ assertEquals(config.getNetworkName(), TEST_NETWORK_NAME);
+ assertEquals(config.getPassphrase(), TEST_PASSPHRASE);
+ assertEquals(config.getGroupOwnerBand(), TEST_OWNER_FREQ);
+ assertEquals(config.getNetworkId(), WifiP2pGroup.TEMPORARY_NET_ID);
}
}
diff --git a/tests/tests/os/src/android/os/storage/cts/CrateInfoTest.java b/tests/tests/os/src/android/os/storage/cts/CrateInfoTest.java
new file mode 100644
index 0000000..8c78d87
--- /dev/null
+++ b/tests/tests/os/src/android/os/storage/cts/CrateInfoTest.java
@@ -0,0 +1,144 @@
+/*
+ * 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 android.os.storage.cts;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.os.Parcel;
+import android.os.Process;
+import android.os.storage.CrateInfo;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TestName;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class CrateInfoTest {
+ @Rule
+ public TestName mTestName = new TestName();
+
+ @Test
+ public void getLabel_shouldMatchTheConstructor() {
+ CrateInfo crateInfo = new CrateInfo(mTestName.getMethodName());
+
+ assertThat(crateInfo.getLabel()).isEqualTo(mTestName.getMethodName());
+ }
+
+ @Test
+ public void newCrateInfo_withNormalLabel_shouldBeSuccess() {
+ CrateInfo crateInfo = new CrateInfo(mTestName.getMethodName());
+
+ assertThat(crateInfo.getLabel()).isEqualTo(mTestName.getMethodName());
+ }
+
+ @Test
+ public void newCrateInfo_withNormalLabelAndExpiration_shouldBeSuccess() {
+ CrateInfo crateInfo = new CrateInfo(mTestName.getMethodName(), 0);
+
+ assertThat(crateInfo.getLabel()).isEqualTo(mTestName.getMethodName());
+ }
+
+ @Test
+ public void newCrateInfo_withNormalLabelAndMaxExpiration_shouldBeSuccess() {
+ CrateInfo crateInfo = new CrateInfo(mTestName.getMethodName(), Long.MAX_VALUE);
+
+ assertThat(crateInfo.getExpirationMillis()).isEqualTo(Long.MAX_VALUE);
+ }
+
+ @Test
+ public void newCrateInfo_nullLabel_throwIllegalArgumentException() {
+ IllegalArgumentException illegalArgumentException = null;
+ try {
+ new CrateInfo(null);
+ } catch (IllegalArgumentException e) {
+ illegalArgumentException = e;
+ }
+
+ assertThat(illegalArgumentException).isNotNull();
+ }
+
+ @Test
+ public void newCrateInfo_emptyString_throwIllegalArgumentException() {
+ IllegalArgumentException illegalArgumentException = null;
+ try {
+ new CrateInfo("");
+ } catch (IllegalArgumentException e) {
+ illegalArgumentException = e;
+ }
+
+ assertThat(illegalArgumentException).isNotNull();
+ }
+
+ @Test
+ public void newCrateInfo_withNegativeExpiration_throwIllegalArgumentException() {
+ IllegalArgumentException illegalArgumentException = null;
+ try {
+ new CrateInfo(mTestName.getMethodName(), -1);
+ } catch (IllegalArgumentException e) {
+ illegalArgumentException = e;
+ }
+
+ assertThat(illegalArgumentException).isNotNull();
+ }
+
+ @Test
+ public void readFromParcel_shouldMatchFromWriteToParcel() {
+ Parcel parcel = Parcel.obtain();
+ CrateInfo crateInfo = new CrateInfo(mTestName.getMethodName(), Long.MAX_VALUE);
+ crateInfo.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+
+ CrateInfo readFromCrateInfo = CrateInfo.CREATOR.createFromParcel(parcel);
+ parcel.recycle();
+
+ assertThat(readFromCrateInfo.getLabel()).isEqualTo(mTestName.getMethodName());
+ assertThat(readFromCrateInfo.getExpirationMillis()).isEqualTo(Long.MAX_VALUE);
+ }
+
+ @Test
+ public void copyFrom_validatedCrate_shouldReturnNonNull() {
+ Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
+
+ CrateInfo crateInfo = CrateInfo.copyFrom(Process.myUid(), context.getOpPackageName(),
+ mTestName.getMethodName());
+
+ assertThat(crateInfo).isNotNull();
+ }
+
+ @Test
+ public void copyFrom_invalidCrate_shouldReturnNull() {
+ Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
+
+ CrateInfo crateInfo = CrateInfo.copyFrom(Process.myUid(), context.getOpPackageName(),
+ null);
+
+ assertThat(crateInfo).isNull();
+ }
+
+ @Test
+ public void copyFrom_invalidPackageName_shouldReturnNull() {
+ CrateInfo crateInfo = CrateInfo.copyFrom(Process.myUid(), null,
+ mTestName.getMethodName());
+
+ assertThat(crateInfo).isNull();
+ }
+}
diff --git a/tests/tests/os/src/android/os/storage/cts/OWNERS b/tests/tests/os/src/android/os/storage/cts/OWNERS
new file mode 100644
index 0000000..948bcad
--- /dev/null
+++ b/tests/tests/os/src/android/os/storage/cts/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 141660526
+per-file CrateInfoTest.java = felkachang@google.com
+per-file StorageCrateTest.java = felkachang@google.com
+per-file StorageStatsManagerTest.java = felkachang@google.com
+
diff --git a/tests/tests/os/src/android/os/storage/cts/StorageCrateTest.java b/tests/tests/os/src/android/os/storage/cts/StorageCrateTest.java
new file mode 100644
index 0000000..99ea30c
--- /dev/null
+++ b/tests/tests/os/src/android/os/storage/cts/StorageCrateTest.java
@@ -0,0 +1,352 @@
+/*
+ * 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 android.os.storage.cts;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TestName;
+import org.junit.runner.RunWith;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.FileVisitResult;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.attribute.BasicFileAttributes;
+
+@RunWith(AndroidJUnit4.class)
+public class StorageCrateTest {
+ private static final String CRATES_ROOT = "crates";
+ @Rule
+ public TestName mTestName = new TestName();
+
+ private Context mContext;
+ private Path mCratesRoot;
+ private String mCrateId;
+ private Path mCratePath;
+
+ private void cleanAllOfCrates() throws IOException {
+ if (!mCratesRoot.toFile().exists()) {
+ return;
+ }
+
+ Files.walkFileTree(mCratesRoot, new SimpleFileVisitor<>() {
+ @Override
+ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
+ throws IOException {
+ Files.deleteIfExists(file);
+ return super.visitFile(file, attrs);
+ }
+
+ @Override
+ public FileVisitResult postVisitDirectory(Path dir, IOException exc)
+ throws IOException {
+ Files.deleteIfExists(dir);
+ return super.postVisitDirectory(dir, exc);
+ }
+ });
+
+ Files.deleteIfExists(mCratesRoot);
+ }
+
+ /**
+ * Setup the necessary member field used by test methods.
+ * <p>It needs to remove all of directories in {@link Context#getCrateDir(String crateId)} that
+ * include {@link Context#getCrateDir(String crateId)} itself.
+ * Why it needs to run cleanAllOfCrates, the process may crashed before tearDown. Running
+ * cleanAllOfCrates to make sure the test environment is clean.</p>
+ */
+ @Before
+ public void setUp() throws IOException {
+ mContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
+ mCratesRoot = mContext.getDataDir().toPath().resolve(CRATES_ROOT);
+ mCrateId = mTestName.getMethodName();
+ mCratePath = mCratesRoot.resolve(mTestName.getMethodName());
+
+ cleanAllOfCrates();
+ }
+
+ @Test
+ public void getCrateDir_notInvoke_cratesRootShouldNotExist() {
+ final File cratesRootDir = mCratesRoot.toFile();
+
+ assertThat(cratesRootDir.exists()).isFalse();
+ }
+
+ @Test
+ public void getCrateDir_withCrateId_cratesRootExist() {
+ final File cratesRootDir = mCratesRoot.toFile();
+
+ mContext.getCrateDir(mCrateId);
+
+ assertThat(cratesRootDir.exists()).isTrue();
+ }
+
+ @Test
+ public void getCrateDir_withCrateId_shouldReturnNonNullDir() {
+ final File crateDir = mContext.getCrateDir(mCrateId);
+
+ assertThat(crateDir).isNotNull();
+ }
+
+ @Test
+ public void getCrateDir_withCrateId_cratePathBeDirectory() {
+ final File crateDir = mContext.getCrateDir(mCrateId);
+
+ assertThat(crateDir.isDirectory()).isTrue();
+ }
+
+ @Test
+ public void getCrateDir_withCrateId_cratePathShouldExist() {
+ final File crateDir = mContext.getCrateDir(mCrateId);
+
+ assertThat(crateDir.exists()).isTrue();
+ }
+
+ @Test
+ public void getCrateDir_withCrateId_cratesRootShouldUnderDataDir() {
+ final File cratesRootDir = mCratesRoot.toFile();
+
+ mContext.getCrateDir(mCrateId);
+
+ assertThat(cratesRootDir.getParentFile().getName())
+ .isEqualTo(mContext.getDataDir().getName());
+ }
+
+ @Test
+ public void getCrateDir_withCrateId_crateDirShouldUnderCratesRootDir() {
+ final File cratesRootDir = mCratesRoot.toFile();
+ final File crateDir = mCratePath.toFile();
+
+ mContext.getCrateDir(mCrateId);
+
+ assertThat(crateDir.getParentFile().getName()).isEqualTo(cratesRootDir.getName());
+ }
+
+ @Test
+ public void getCrateDir_anyExceptionHappened_shouldNotCreateAnyDir() {
+ File crateDir = null;
+
+ try {
+ crateDir = mContext.getCrateDir(null);
+ } catch (Exception e) {
+ }
+
+ assertThat(crateDir).isNull();
+ }
+
+ @Test
+ public void getCrateDir_nullCrateId_crateDirShouldUnderCratesRootDir() {
+ IllegalArgumentException illegalArgumentException = null;
+
+ try {
+ mContext.getCrateDir(null);
+ } catch (IllegalArgumentException e) {
+ illegalArgumentException = e;
+ }
+
+ assertThat(illegalArgumentException).isNotNull();
+ }
+
+ @Test
+ public void getCrateDir_emptyCrateId_crateDirShouldUnderCratesRootDir() {
+ IllegalArgumentException illegalArgumentException = null;
+
+ try {
+ mContext.getCrateDir("");
+ } catch (IllegalArgumentException e) {
+ illegalArgumentException = e;
+ }
+
+ assertThat(illegalArgumentException).isNotNull();
+ }
+
+ @Test
+ public void getCrateDir_crateIdIsDot_crateDirShouldUnderCratesRootDir() {
+ IllegalArgumentException illegalArgumentException = null;
+
+ try {
+ mContext.getCrateDir(".");
+ } catch (IllegalArgumentException e) {
+ illegalArgumentException = e;
+ }
+
+ assertThat(illegalArgumentException).isNotNull();
+ }
+
+ @Test
+ public void getCrateDir_crateIdIsDotDot_crateDirShouldUnderCratesRootDir() {
+ IllegalArgumentException illegalArgumentException = null;
+
+ try {
+ mContext.getCrateDir("..");
+ } catch (IllegalArgumentException e) {
+ illegalArgumentException = e;
+ }
+
+ assertThat(illegalArgumentException).isNotNull();
+ }
+
+ @Test
+ public void getCrateDir_crateIdPrefixContainsDotDot_shouldTriggerIllegalArgumentException() {
+ IllegalArgumentException illegalArgumentException = null;
+
+ try {
+ mContext.getCrateDir("../etc/password");
+ } catch (IllegalArgumentException e) {
+ illegalArgumentException = e;
+ }
+
+ assertThat(illegalArgumentException).isNotNull();
+ }
+
+ @Test
+ public void getCrateDir_crateIdContainsDotDot_shouldTriggerIllegalArgumentException() {
+ IllegalArgumentException illegalArgumentException = null;
+
+ try {
+ mContext.getCrateDir("normalCrate/../../../etc/password");
+ } catch (IllegalArgumentException e) {
+ illegalArgumentException = e;
+ }
+
+ assertThat(illegalArgumentException).isNotNull();
+ }
+
+ @Test
+ public void getCrateDir_crateIdSuffixContainsDotDot_shouldTriggerIllegalArgumentException() {
+ IllegalArgumentException illegalArgumentException = null;
+
+ try {
+ mContext.getCrateDir("normalCrate/etc/password/../../..");
+ } catch (IllegalArgumentException e) {
+ illegalArgumentException = e;
+ }
+
+ assertThat(illegalArgumentException).isNotNull();
+ }
+
+ @Test
+ public void getCrateDir_crateIdStartWithSlashSlash_shouldTriggerIllegalArgumentException() {
+ IllegalArgumentException illegalArgumentException = null;
+
+ try {
+ mContext.getCrateDir("/etc/password");
+ } catch (IllegalArgumentException e) {
+ illegalArgumentException = e;
+ }
+
+ assertThat(illegalArgumentException).isNotNull();
+ }
+
+ @Test
+ public void getCrateDir_crateIdStartWithSlash_shouldTriggerIllegalArgumentException() {
+ IllegalArgumentException illegalArgumentException = null;
+
+ try {
+ mContext.getCrateDir("//etc/password");
+ } catch (IllegalArgumentException e) {
+ illegalArgumentException = e;
+ }
+
+ assertThat(illegalArgumentException).isNotNull();
+ }
+
+ @Test
+ public void getCrateDir_crateIdContainsSlashChar_shouldBeInvalidated() {
+ IllegalArgumentException illegalArgumentException = null;
+
+ try {
+ mContext.getCrateDir("A/B");
+ } catch (IllegalArgumentException e) {
+ illegalArgumentException = e;
+ }
+
+ assertThat(illegalArgumentException).isNotNull();
+ }
+
+ @Test
+ public void getCrateDir_superLongCrateId_shouldBeIllegalArgument() throws IOException {
+ IllegalArgumentException illegalArgumentException = null;
+ StringBuilder sb = new StringBuilder(1024);
+ while (sb.length() > 1024) {
+ sb.append(mCrateId);
+ }
+
+ try {
+ mContext.getCrateDir(sb.toString());
+ } catch (IllegalArgumentException e) {
+ illegalArgumentException = e;
+ }
+
+ assertThat(illegalArgumentException).isNotNull();
+ }
+
+ @Test
+ public void getCrateDir_callWithDifferentCrateId_shouldGenerateTheSameNumberOfCrates() {
+ final String[] expectedCrates = new String[] {"A", "B", "C"};
+
+ for (String crateId : expectedCrates) {
+ mContext.getCrateDir(crateId);
+ }
+
+ String[] newChildDir = mCratesRoot.toFile().list();
+ assertThat(newChildDir).asList().containsAllIn(expectedCrates);
+ }
+
+ @Test
+ public void getCrateDir_withUtf8Characters_shouldCreateSuccess() {
+ String utf8Characters = "æɛəɚʊʌɔ" + "宮商角止羽" + "あいうえお"
+ + "ㅏㅓㅗㅜㅡㅣㅐㅔㅚㅟㅑㅕㅛㅠㅒㅖㅘㅙㅝㅞㅢ";
+
+ File crateDir = mContext.getCrateDir(utf8Characters);
+
+ assertThat(crateDir.getName()).isEqualTo(utf8Characters);
+ }
+
+ @Test
+ public void getCrateDir_withNullCharacter_shouldBeFail() {
+ String utf8Characters = "abcdefg\0hijklmnopqrstuvwxyz";
+
+ IllegalArgumentException illegalArgumentException = null;
+ try {
+ mContext.getCrateDir(utf8Characters);
+ } catch (IllegalArgumentException e) {
+ illegalArgumentException = e;
+ }
+
+ assertThat(illegalArgumentException).isNotNull();
+ }
+
+ @Test
+ public void getCrateDir_withLineFeedCharacter_shouldSuccess() {
+ String utf8Characters = "abcdefg\nhijklmnopqrstuvwxyz";
+
+ File crateDir = mContext.getCrateDir(utf8Characters);
+
+ assertThat(crateDir.exists() && crateDir.isDirectory()).isTrue();
+ }
+}
diff --git a/tests/tests/os/src/android/os/storage/cts/StorageStatsManagerTest.java b/tests/tests/os/src/android/os/storage/cts/StorageStatsManagerTest.java
new file mode 100644
index 0000000..9643aef
--- /dev/null
+++ b/tests/tests/os/src/android/os/storage/cts/StorageStatsManagerTest.java
@@ -0,0 +1,409 @@
+/*
+ * 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 android.os.storage.cts;
+
+import static android.os.UserHandle.MIN_SECONDARY_USER_ID;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.Manifest;
+import android.app.UiAutomation;
+import android.app.usage.StorageStatsManager;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.os.Process;
+import android.os.UserHandle;
+import android.os.storage.CrateInfo;
+import android.os.storage.StorageManager;
+import android.text.TextUtils;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.google.common.truth.Correspondence;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TestName;
+import org.junit.runner.RunWith;
+
+import java.io.IOException;
+import java.nio.file.FileVisitResult;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.Collection;
+import java.util.UUID;
+
+@RunWith(AndroidJUnit4.class)
+public class StorageStatsManagerTest {
+ private static final String CRATES_ROOT = "crates";
+
+ private Context mContext;
+ private StorageManager mStorageManager;
+ private StorageStatsManager mStorageStatsManager;
+
+ @Rule
+ public TestName mTestName = new TestName();
+ private Path mCratesPath;
+ private Path mCrateDirPath;
+ private UUID mUuid;
+ private String mCrateId;
+
+ private void cleanAllOfCrates() throws IOException {
+ if (!mCratesPath.toFile().exists()) {
+ return;
+ }
+
+ Files.walkFileTree(mCratesPath, new SimpleFileVisitor<Path>() {
+ @Override
+ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
+ throws IOException {
+ Files.deleteIfExists(file);
+ return super.visitFile(file, attrs);
+ }
+
+ @Override
+ public FileVisitResult postVisitDirectory(Path dir, IOException exc)
+ throws IOException {
+ Files.deleteIfExists(dir);
+ return super.postVisitDirectory(dir, exc);
+ }
+ });
+ Files.deleteIfExists(mCratesPath);
+ }
+
+ /**
+ * Setup the necessary member field used by test methods.
+ */
+ @Before
+ public void setUp() throws Exception {
+ mContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
+ mStorageManager = (StorageManager) mContext.getSystemService(Context.STORAGE_SERVICE);
+ mStorageStatsManager =
+ (StorageStatsManager) mContext.getSystemService(Context.STORAGE_STATS_SERVICE);
+
+ mCratesPath = mContext.getDataDir().toPath().resolve(CRATES_ROOT);
+ cleanAllOfCrates();
+
+ mCrateId = mTestName.getMethodName();
+
+ mCrateDirPath = mCratesPath.resolve(mCrateId);
+ mUuid = mStorageManager.getUuidForPath(mCratesPath.toFile());
+ }
+
+ /**
+ * To clean all of crated folders to prevent from flaky.
+ * @throws Exception happened when the tearDown tries to removed all of folders and files.
+ */
+ @After
+ public void tearDown() throws Exception {
+ cleanAllOfCrates();
+ }
+
+ @Test
+ public void queryCratesForUid_noCratedFolder_shouldBeEmpty() throws Exception {
+ Collection<CrateInfo> collection = mStorageStatsManager.queryCratesForUid(mUuid,
+ Process.myUid());
+
+ assertThat(collection.size()).isEqualTo(0);
+ }
+
+ private Collection<CrateInfo> queryCratesForUser(boolean byShell, UUID uuid,
+ UserHandle userHandle)
+ throws PackageManager.NameNotFoundException, IOException {
+ final UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation()
+ .getUiAutomation();
+ if (byShell) {
+ uiAutomation.adoptShellPermissionIdentity(Manifest.permission.MANAGE_CRATES);
+ }
+ Collection<CrateInfo> crateInfos = mStorageStatsManager.queryCratesForUser(uuid,
+ userHandle);
+ if (byShell) {
+ uiAutomation.dropShellPermissionIdentity();
+ }
+ return crateInfos;
+ }
+ @Test
+ public void queryCratesForUser_noCratedFolder_shouldBeEmpty() throws Exception {
+ Collection<CrateInfo> collection = queryCratesForUser(true, mUuid,
+ Process.myUserHandle());
+
+ assertThat(collection.size()).isEqualTo(0);
+ }
+
+ @Test
+ public void queryCratesForPackage_noCratedFolder_shouldBeEmpty() throws Exception {
+ Collection<CrateInfo> collection = mStorageStatsManager.queryCratesForPackage(mUuid,
+ mContext.getOpPackageName(), Process.myUserHandle());
+
+ assertThat(collection.size()).isEqualTo(0);
+ }
+
+ @Test
+ public void queryCratesForUid_withOtherUid_shouldRiseSecurityIssueException() throws Exception {
+ int fakeUid = UserHandle.getUid(MIN_SECONDARY_USER_ID,
+ UserHandle.getAppId(Process.myUid()));
+ SecurityException securityException = null;
+
+ try {
+ mStorageStatsManager.queryCratesForUid(mUuid, fakeUid);
+ } catch (SecurityException e) {
+ securityException = e;
+ }
+
+ assertThat(securityException).isNotNull();
+ }
+
+ @Test
+ public void queryCratesForUser_withOtherUid_shouldRiseSecurityIssueException()
+ throws Exception {
+ UserHandle fakeUserHandle = UserHandle.of(MIN_SECONDARY_USER_ID);
+ SecurityException securityException = null;
+
+ try {
+ mStorageStatsManager.queryCratesForUser(mUuid, fakeUserHandle);
+ } catch (SecurityException e) {
+ securityException = e;
+ }
+
+ assertThat(securityException).isNotNull();
+ }
+
+ @Test
+ public void queryCratesForPackage_withOtherUid_shouldRiseSecurityIssueException()
+ throws Exception {
+ UserHandle fakeUserHandle = UserHandle.of(MIN_SECONDARY_USER_ID);
+ SecurityException securityException = null;
+
+ try {
+ mStorageStatsManager.queryCratesForPackage(mUuid,
+ mContext.getOpPackageName(), fakeUserHandle);
+ } catch (SecurityException e) {
+ securityException = e;
+ }
+
+ assertThat(securityException).isNotNull();
+ }
+
+ @Test
+ public void queryCratesForUid_addOneDirectory_shouldIncreasingOneCrate()
+ throws Exception {
+ Collection<CrateInfo> originalCollection = mStorageStatsManager.queryCratesForUid(
+ mUuid, Process.myUid());
+
+ mContext.getCrateDir(mCrateId);
+
+ Collection<CrateInfo> newCollection = mStorageStatsManager.queryCratesForUid(
+ mUuid, Process.myUid());
+ assertThat(newCollection.size()).isEqualTo(originalCollection.size() + 1);
+ }
+
+ @Test
+ public void queryCratesForUser_addOneDirectory_shouldIncreasingOneCrate()
+ throws Exception {
+ Collection<CrateInfo> originalCollection = queryCratesForUser(true, mUuid,
+ Process.myUserHandle());
+
+ mContext.getCrateDir(mCrateId);
+
+ Collection<CrateInfo> newCollection = queryCratesForUser(true,
+ mUuid, Process.myUserHandle());
+ assertThat(newCollection.size()).isEqualTo(originalCollection.size() + 1);
+ }
+
+ @Test
+ public void queryCratesForPackage_addOneDirectory_shouldIncreasingOneCrate()
+ throws Exception {
+ Collection<CrateInfo> originalCollection = mStorageStatsManager.queryCratesForPackage(
+ mUuid, mContext.getOpPackageName(), Process.myUserHandle());
+
+ mContext.getCrateDir(mCrateId);
+
+ Collection<CrateInfo> newCollection = mStorageStatsManager.queryCratesForPackage(
+ mUuid, mContext.getOpPackageName(), Process.myUserHandle());
+ assertThat(newCollection.size()).isEqualTo(originalCollection.size() + 1);
+ }
+
+ @Test
+ public void queryCratesForUid_withoutSetCrateInfo_labelShouldTheSameWithFolderName()
+ throws Exception {
+ mContext.getCrateDir(mCrateId);
+
+ Collection<CrateInfo> crateInfos = mStorageStatsManager.queryCratesForUid(
+ mUuid, Process.myUid());
+
+ assertThat(crateInfos.iterator().next().getLabel()).isEqualTo(mTestName.getMethodName());
+ }
+
+ @Test
+ public void queryCratesForUser_withoutSetCrateInfo_labelShouldTheSameWithFolderName()
+ throws Exception {
+ mContext.getCrateDir(mCrateId);
+
+ Collection<CrateInfo> crateInfos = queryCratesForUser(true, mUuid,
+ Process.myUserHandle());
+
+ assertThat(crateInfos.iterator().next().getLabel()).isEqualTo(mTestName.getMethodName());
+ }
+
+ @Test
+ public void queryCratesForPackage_withoutSetCrateInfo_labelShouldTheSameWithFolderName()
+ throws Exception {
+ mContext.getCrateDir(mCrateId);
+
+ Collection<CrateInfo> crateInfos = mStorageStatsManager.queryCratesForPackage(
+ mUuid, mContext.getOpPackageName(), Process.myUserHandle());
+
+ assertThat(crateInfos.iterator().next().getLabel()).isEqualTo(mTestName.getMethodName());
+ }
+
+ @Test
+ public void queryCratesForUid_withoutSetCrateInfo_expirationShouldBeZero()
+ throws Exception {
+ mContext.getCrateDir(mCrateId);
+
+ Collection<CrateInfo> crateInfos = mStorageStatsManager.queryCratesForUid(
+ mUuid, Process.myUid());
+
+ assertThat(crateInfos.iterator().next().getExpirationMillis()).isEqualTo(0);
+ }
+
+ @Test
+ public void queryCratesForUser_withoutSetCrateInfo_expirationShouldBeZero()
+ throws Exception {
+ mContext.getCrateDir(mCrateId);
+
+ Collection<CrateInfo> crateInfos = queryCratesForUser(true, mUuid,
+ Process.myUserHandle());
+
+ assertThat(crateInfos.iterator().next().getExpirationMillis()).isEqualTo(0);
+ }
+
+ @Test
+ public void queryCratesForPackage_withoutSetCrateInfo_expirationShouldBeZero()
+ throws Exception {
+ mContext.getCrateDir(mCrateId);
+
+ Collection<CrateInfo> crateInfos = mStorageStatsManager.queryCratesForPackage(
+ mUuid, mContext.getOpPackageName(), Process.myUserHandle());
+
+ assertThat(crateInfos.iterator().next().getExpirationMillis()).isEqualTo(0);
+ }
+
+ @Test
+ public void queryCratesForUid_removeCratedDir_shouldDecreaseTheNumberOfCrates()
+ throws Exception {
+ for (int i = 0; i < 3; i++) {
+ mContext.getCrateDir(mCrateId + "_" + i);
+ }
+ Collection<CrateInfo> oldCollection = mStorageStatsManager.queryCratesForUid(mUuid,
+ Process.myUid());
+
+ Files.deleteIfExists(mContext.getCrateDir(mCrateId + "_" + 1).toPath());
+
+ Collection<CrateInfo> newCollection = mStorageStatsManager.queryCratesForUid(
+ mUuid, Process.myUid());
+ assertThat(newCollection.size()).isEqualTo(oldCollection.size() - 1);
+ }
+
+ @Test
+ public void queryCratesForPackage_removeCratedDir_shouldDecreaseTheNumberOfCrates()
+ throws Exception {
+ for (int i = 0; i < 3; i++) {
+ mContext.getCrateDir(mCrateId + "_" + i);
+ }
+ Collection<CrateInfo> oldCollection = mStorageStatsManager.queryCratesForPackage(mUuid,
+ mContext.getOpPackageName(), Process.myUserHandle());
+
+ Files.deleteIfExists(mContext.getCrateDir(mCrateId + "_" + 1).toPath());
+
+ Collection<CrateInfo> newCollection = mStorageStatsManager.queryCratesForPackage(mUuid,
+ mContext.getOpPackageName(), Process.myUserHandle());
+ assertThat(newCollection.size()).isEqualTo(oldCollection.size() - 1);
+ }
+
+ @Test
+ public void queryCratesForUser_removeCratedDir_shouldDecreaseTheNumberOfCrates()
+ throws Exception {
+ for (int i = 0; i < 3; i++) {
+ mContext.getCrateDir(mCrateId + "_" + i);
+ }
+ Collection<CrateInfo> oldCollection = queryCratesForUser(true, mUuid,
+ Process.myUserHandle());
+
+ Files.deleteIfExists(mContext.getCrateDir(mCrateId + "_" + 1).toPath());
+
+ Collection<CrateInfo> newCollection = queryCratesForUser(true, mUuid,
+ Process.myUserHandle());
+ assertThat(newCollection.size()).isEqualTo(oldCollection.size() - 1);
+ }
+
+ Correspondence<CrateInfo, String> mCorrespondenceByLabel = new Correspondence<>() {
+ @Override
+ public boolean compare(CrateInfo crateInfo, String expect) {
+ return TextUtils.equals(crateInfo.getLabel(), expect);
+ }
+
+ @Override
+ public String toString() {
+ return "It should be the crated folder name";
+ }
+ };
+
+ @Test
+ public void queryCratesForUid_createDeepPath_shouldCreateOneCrate()
+ throws Exception {
+ final Path threeLevelPath = mCrateDirPath.resolve("1").resolve("2").resolve("3");
+ Files.createDirectories(threeLevelPath);
+
+ Collection<CrateInfo> crateInfos = mStorageStatsManager.queryCratesForUid(
+ mUuid, Process.myUid());
+
+ assertThat(crateInfos).comparingElementsUsing(mCorrespondenceByLabel)
+ .containsExactly(mCrateId);
+ }
+
+ @Test
+ public void queryCratesForUser_createDeepPath_shouldCreateOneCrate()
+ throws Exception {
+ final Path threeLevelPath = mCrateDirPath.resolve("1").resolve("2").resolve("3");
+ Files.createDirectories(threeLevelPath);
+
+ Collection<CrateInfo> crateInfos = queryCratesForUser(true, mUuid,
+ Process.myUserHandle());
+
+ assertThat(crateInfos).comparingElementsUsing(mCorrespondenceByLabel)
+ .containsExactly(mCrateId);
+ }
+
+ @Test
+ public void queryCratesForPackage_createDeepPath_shouldCreateOneCrate()
+ throws Exception {
+ final Path threeLevelPath = mCrateDirPath.resolve("1").resolve("2").resolve("3");
+ Files.createDirectories(threeLevelPath);
+
+ Collection<CrateInfo> crateInfos = mStorageStatsManager.queryCratesForPackage(
+ mUuid, mContext.getOpPackageName(), Process.myUserHandle());
+
+ assertThat(crateInfos).comparingElementsUsing(mCorrespondenceByLabel)
+ .containsExactly(mCrateId);
+ }
+}
diff --git a/tests/tests/permission2/res/raw/android_manifest.xml b/tests/tests/permission2/res/raw/android_manifest.xml
index d9e2ded..cf6bbe7 100644
--- a/tests/tests/permission2/res/raw/android_manifest.xml
+++ b/tests/tests/permission2/res/raw/android_manifest.xml
@@ -1778,6 +1778,13 @@
android:description="@string/permdesc_vibrate"
android:protectionLevel="normal|instant" />
+ <!-- Allows access to the vibrator always-on settings.
+ <p>Protection level: signature
+ @hide
+ -->
+ <permission android:name="android.permission.VIBRATE_ALWAYS_ON"
+ android:protectionLevel="signature" />
+
<!-- Allows using PowerManager WakeLocks to keep processor from sleeping or screen
from dimming.
<p>Protection level: normal
@@ -2129,6 +2136,14 @@
<permission android:name="android.permission.MANAGE_DOCUMENTS"
android:protectionLevel="signature|documenter" />
+ <!-- Allows an application to manage access to crates, usually as part
+ of a crates picker.
+ @hide
+ @TestApi
+ -->
+ <permission android:name="android.permission.MANAGE_CRATES"
+ android:protectionLevel="signature" />
+
<!-- @hide Allows an application to cache content.
<p>Not for use by third-party applications.
-->
@@ -3187,13 +3202,6 @@
<permission android:name="android.permission.BIND_TV_INPUT"
android:protectionLevel="signature|privileged" />
- <!-- Must be required by an {@link android.service.sms.FinancialSmsService}
- to ensure that only the system can bind to it.
- @hide This is not a third-party API (intended for OEMs and system apps).
- -->
- <permission android:name="android.permission.BIND_FINANCIAL_SMS_SERVICE"
- android:protectionLevel="signature" />
-
<!-- @SystemApi
Must be required by a {@link com.android.media.tv.remoteprovider.TvRemoteProvider}
to ensure that only the system can bind to it.
@@ -4347,6 +4355,12 @@
<permission android:name="android.permission.MANAGE_SOUND_TRIGGER"
android:protectionLevel="signature|privileged" />
+ <!-- Allows preempting sound trigger recognitions for the sake of capturing audio on
+ implementations which do not support running both concurrently.
+ @hide -->
+ <permission android:name="android.permission.PREEMPT_SOUND_TRIGGER"
+ android:protectionLevel="signature|privileged" />
+
<!-- Must be required by system/priv apps implementing sound trigger detection services
@hide
@SystemApi -->
diff --git a/tests/tests/permission2/res/raw/automotive_android_manifest.xml b/tests/tests/permission2/res/raw/automotive_android_manifest.xml
index fac0789..dac484b 100644
--- a/tests/tests/permission2/res/raw/automotive_android_manifest.xml
+++ b/tests/tests/permission2/res/raw/automotive_android_manifest.xml
@@ -281,6 +281,12 @@
android:label="@string/car_permission_label_enroll_trust"
android:description="@string/car_permission_desc_enroll_trust" />
+ <permission
+ android:name="android.car.permission.CAR_TEST_SERVICE"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_car_test_service"
+ android:description="@string/car_permission_desc_car_test_service" />
+
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.DEVICE_POWER" />
<uses-permission android:name="android.permission.GRANT_RUNTIME_PERMISSIONS" />
diff --git a/tests/tests/permission2/src/android/permission2/cts/ProtectedBroadcastsTest.java b/tests/tests/permission2/src/android/permission2/cts/ProtectedBroadcastsTest.java
index ebbd40b..3df5b89 100644
--- a/tests/tests/permission2/src/android/permission2/cts/ProtectedBroadcastsTest.java
+++ b/tests/tests/permission2/src/android/permission2/cts/ProtectedBroadcastsTest.java
@@ -84,7 +84,6 @@
"android.intent.action.SIM_STATE_CHANGED",
"android.intent.action.DATA_CONNECTION_FAILED",
"android.intent.action.NETWORK_SET_TIME",
- "android.intent.action.NETWORK_SET_TIMEZONE",
"android.telephony.action.SUBSCRIPTION_CARRIER_IDENTITY_CHANGED",
"android.telephony.action.SUBSCRIPTION_SPECIFIC_CARRIER_IDENTITY_CHANGED",
"com.android.internal.intent.action.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS",
diff --git a/tests/tests/permission2/src/android/permission2/cts/RestrictedPermissionsTest.java b/tests/tests/permission2/src/android/permission2/cts/RestrictedPermissionsTest.java
index e20b2af..7085078 100644
--- a/tests/tests/permission2/src/android/permission2/cts/RestrictedPermissionsTest.java
+++ b/tests/tests/permission2/src/android/permission2/cts/RestrictedPermissionsTest.java
@@ -437,6 +437,7 @@
@AppModeFull
public void testStorageTargetingSdk28DoesNotLooseAccessWhenOptingIn() throws Exception {
installApp(APK_USES_STORAGE_DEFAULT_28, null);
+ assertHasFullStorageAccess();
installApp(APK_USES_STORAGE_OPT_IN_28, null);
assertHasFullStorageAccess();
@@ -446,6 +447,7 @@
@AppModeFull
public void testStorageTargetingSdk28DoesNotLooseAccessViaUpdate() throws Exception {
installApp(APK_USES_STORAGE_DEFAULT_28, null);
+ assertHasFullStorageAccess();
installApp(APK_USES_STORAGE_DEFAULT_29, null);
assertHasFullStorageAccess();
@@ -455,6 +457,7 @@
@AppModeFull
public void testStorageTargetingSdk29DoesNotLooseAccessViaUpdate() throws Exception {
installApp(APK_USES_STORAGE_OPT_OUT_29, null);
+ assertHasFullStorageAccess();
installApp(APK_USES_STORAGE_DEFAULT_29, null);
assertHasFullStorageAccess();
@@ -464,6 +467,7 @@
@AppModeFull
public void testStorageTargetingSdk29DoesNotLooseAccessWhenOptingIn() throws Exception {
installApp(APK_USES_STORAGE_OPT_OUT_29, null);
+ assertHasFullStorageAccess();
installApp(APK_USES_STORAGE_OPT_IN_28, null);
assertHasFullStorageAccess();
diff --git a/tests/tests/provider/src/android/provider/cts/ProviderTestUtils.java b/tests/tests/provider/src/android/provider/cts/ProviderTestUtils.java
index e2cdb45..f7b726b 100644
--- a/tests/tests/provider/src/android/provider/cts/ProviderTestUtils.java
+++ b/tests/tests/provider/src/android/provider/cts/ProviderTestUtils.java
@@ -29,6 +29,8 @@
import android.os.FileUtils;
import android.os.ParcelFileDescriptor;
import android.os.UserManager;
+import android.os.storage.StorageManager;
+import android.os.storage.StorageVolume;
import android.provider.MediaStore;
import android.provider.MediaStore.MediaColumns;
import android.provider.cts.media.MediaStoreUtils;
@@ -186,6 +188,10 @@
executeShellCommand("bmgr wipe " + backupTransport + " " + packageName, uiAutomation);
}
+ public static void waitForIdle() {
+ MediaStore.waitForIdle(InstrumentationRegistry.getTargetContext().getContentResolver());
+ }
+
/**
* Waits until a file exists, or fails.
*
@@ -201,11 +207,20 @@
}
}
+ public static File getVolumePath(String volumeName) {
+ final Context context = InstrumentationRegistry.getTargetContext();
+ return context.getSystemService(StorageManager.class)
+ .getStorageVolume(MediaStore.Files.getContentUri(volumeName)).getDirectory();
+ }
+
public static File stageDir(String volumeName) throws IOException {
if (MediaStore.VOLUME_EXTERNAL.equals(volumeName)) {
volumeName = MediaStore.VOLUME_EXTERNAL_PRIMARY;
}
- File dir = Environment.buildPath(MediaStore.getVolumePath(volumeName), "Android", "media",
+ final StorageVolume vol = InstrumentationRegistry.getTargetContext()
+ .getSystemService(StorageManager.class)
+ .getStorageVolume(MediaStore.Files.getContentUri(volumeName));
+ File dir = Environment.buildPath(vol.getDirectory(), "Android", "media",
"android.provider.cts");
Log.d(TAG, "stageDir(" + volumeName + "): returning " + dir);
return dir;
@@ -215,7 +230,10 @@
if (MediaStore.VOLUME_EXTERNAL.equals(volumeName)) {
volumeName = MediaStore.VOLUME_EXTERNAL_PRIMARY;
}
- return Environment.buildPath(MediaStore.getVolumePath(volumeName),
+ final StorageVolume vol = InstrumentationRegistry.getTargetContext()
+ .getSystemService(StorageManager.class)
+ .getStorageVolume(MediaStore.Files.getContentUri(volumeName));
+ return Environment.buildPath(vol.getDirectory(),
Environment.DIRECTORY_DOWNLOADS, "android.provider.cts");
}
@@ -271,19 +289,21 @@
}
public static Uri scanFile(File file) throws Exception {
- Uri uri = MediaStore.scanFile(InstrumentationRegistry.getTargetContext(), file);
+ final Uri uri = MediaStore
+ .scanFile(InstrumentationRegistry.getTargetContext().getContentResolver(), file);
assertWithMessage("no URI for '%s'", file).that(uri).isNotNull();
return uri;
}
public static Uri scanFileFromShell(File file) throws Exception {
- Uri uri = MediaStore.scanFileFromShell(InstrumentationRegistry.getTargetContext(), file);
- assertWithMessage("no URI for '%s'", file).that(uri).isNotNull();
- return uri;
+ return scanFile(file);
}
public static void scanVolume(File file) throws Exception {
- MediaStore.scanVolume(InstrumentationRegistry.getTargetContext(), file);
+ final StorageVolume vol = InstrumentationRegistry.getTargetContext()
+ .getSystemService(StorageManager.class).getStorageVolume(file);
+ MediaStore.scanVolume(InstrumentationRegistry.getTargetContext().getContentResolver(),
+ vol.getMediaStoreVolumeName());
}
public static byte[] hash(InputStream in) throws Exception {
diff --git a/tests/tests/provider/src/android/provider/cts/media/MediaStorePlacementTest.java b/tests/tests/provider/src/android/provider/cts/media/MediaStorePlacementTest.java
index 98df653..a2c6fd6 100644
--- a/tests/tests/provider/src/android/provider/cts/media/MediaStorePlacementTest.java
+++ b/tests/tests/provider/src/android/provider/cts/media/MediaStorePlacementTest.java
@@ -209,7 +209,7 @@
public void testDirectory_InsideSandbox() throws Exception {
Assume.assumeFalse(MediaStore.VOLUME_EXTERNAL.equals(mVolumeName));
- final File dir = MediaStore.getVolumePath(mVolumeName);
+ final File dir = ProviderTestUtils.getVolumePath(mVolumeName);
final File file = ProviderTestUtils.stageFile(R.drawable.scenery, Environment.buildPath(dir,
"Android", "media", "android.provider.cts", System.nanoTime() + ".jpg"));
final Uri uri = ProviderTestUtils.scanFile(file);
@@ -301,7 +301,7 @@
Assume.assumeFalse(MediaStore.VOLUME_EXTERNAL.equals(mVolumeName));
final String displayName = "cts" + System.nanoTime() + ".jpg";
- final File file = Environment.buildPath(MediaStore.getVolumePath(mVolumeName),
+ final File file = Environment.buildPath(ProviderTestUtils.getVolumePath(mVolumeName),
Environment.DIRECTORY_ALARMS, displayName);
return ProviderTestUtils.scanFileFromShell(
ProviderTestUtils.stageFile(R.raw.scenery, file));
diff --git a/tests/tests/provider/src/android/provider/cts/media/MediaStoreTest.java b/tests/tests/provider/src/android/provider/cts/media/MediaStoreTest.java
index 96fcaaf..01ff267 100644
--- a/tests/tests/provider/src/android/provider/cts/media/MediaStoreTest.java
+++ b/tests/tests/provider/src/android/provider/cts/media/MediaStoreTest.java
@@ -22,18 +22,13 @@
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
-import android.app.usage.StorageStatsManager;
import android.content.ContentResolver;
-import android.content.ContentUris;
import android.content.Context;
-import android.content.res.AssetFileDescriptor;
import android.database.Cursor;
import android.net.Uri;
-import android.os.SystemClock;
import android.os.storage.StorageManager;
import android.os.storage.StorageVolume;
import android.provider.MediaStore;
-import android.provider.MediaStore.MediaColumns;
import android.provider.cts.ProviderTestUtils;
import android.provider.cts.R;
import android.util.Log;
@@ -49,10 +44,7 @@
import org.junit.runners.Parameterized.Parameter;
import org.junit.runners.Parameterized.Parameters;
-import java.io.File;
-import java.util.HashSet;
import java.util.Set;
-import java.util.UUID;
@RunWith(Parameterized.class)
public class MediaStoreTest {
@@ -181,120 +173,4 @@
} catch (IllegalArgumentException expected) {
}
}
-
- @Test
- public void testContributedMedia() throws Exception {
- // STOPSHIP: remove this once isolated storage is always enabled
- Assume.assumeTrue(StorageManager.hasIsolatedStorage());
- Assume.assumeTrue(MediaStore.VOLUME_EXTERNAL_PRIMARY.equals(mVolumeName));
-
- InstrumentationRegistry.getInstrumentation().getUiAutomation().adoptShellPermissionIdentity(
- android.Manifest.permission.CLEAR_APP_USER_DATA,
- android.Manifest.permission.PACKAGE_USAGE_STATS);
-
- // Start by cleaning up contributed items
- MediaStore.deleteContributedMedia(getContext(), getContext().getPackageName(),
- android.os.Process.myUserHandle());
-
- // Force sync to try updating other views
- ProviderTestUtils.executeShellCommand("sync");
- SystemClock.sleep(500);
-
- // Measure usage before
- final long beforePackage = getExternalPackageSize();
- final long beforeTotal = getExternalTotalSize();
- final long beforeContributed = MediaStore.getContributedMediaSize(getContext(),
- getContext().getPackageName(), android.os.Process.myUserHandle());
-
- final long stageSize;
- try (AssetFileDescriptor fd = getContext().getResources()
- .openRawResourceFd(R.raw.volantis)) {
- stageSize = fd.getLength();
- }
-
- // Create media both inside and outside sandbox
- final Uri inside;
- final Uri outside;
- final File file = new File(ProviderTestUtils.stageDir(mVolumeName),
- "cts" + System.nanoTime() + ".jpg");
- ProviderTestUtils.stageFile(R.raw.volantis, file);
- inside = ProviderTestUtils.scanFileFromShell(file);
- outside = ProviderTestUtils.stageMedia(R.raw.volantis, mExternalImages);
-
- {
- final HashSet<Long> visible = getVisibleIds(mExternalImages);
- assertTrue(visible.contains(ContentUris.parseId(inside)));
- assertTrue(visible.contains(ContentUris.parseId(outside)));
-
- // Force sync to try updating other views
- ProviderTestUtils.executeShellCommand("sync");
- SystemClock.sleep(500);
-
- final long afterPackage = getExternalPackageSize();
- final long afterTotal = getExternalTotalSize();
- final long afterContributed = MediaStore.getContributedMediaSize(getContext(),
- getContext().getPackageName(), android.os.Process.myUserHandle());
-
- assertMostlyEquals(beforePackage + stageSize, afterPackage, SIZE_DELTA);
- assertMostlyEquals(beforeTotal + stageSize + stageSize, afterTotal, SIZE_DELTA);
- assertMostlyEquals(beforeContributed + stageSize, afterContributed, SIZE_DELTA);
- }
-
- // Delete only contributed items
- MediaStore.deleteContributedMedia(getContext(), getContext().getPackageName(),
- android.os.Process.myUserHandle());
- {
- final HashSet<Long> visible = getVisibleIds(mExternalImages);
- assertTrue(visible.contains(ContentUris.parseId(inside)));
- assertFalse(visible.contains(ContentUris.parseId(outside)));
-
- // Force sync to try updating other views
- ProviderTestUtils.executeShellCommand("sync");
- SystemClock.sleep(500);
-
- final long afterPackage = getExternalPackageSize();
- final long afterTotal = getExternalTotalSize();
- final long afterContributed = MediaStore.getContributedMediaSize(getContext(),
- getContext().getPackageName(), android.os.Process.myUserHandle());
-
- assertMostlyEquals(beforePackage + stageSize, afterPackage, SIZE_DELTA);
- assertMostlyEquals(beforeTotal + stageSize, afterTotal, SIZE_DELTA);
- assertMostlyEquals(0, afterContributed, SIZE_DELTA);
- }
- }
-
- private long getExternalPackageSize() throws Exception {
- final StorageManager storage = getContext().getSystemService(StorageManager.class);
- final StorageStatsManager stats = getContext().getSystemService(StorageStatsManager.class);
-
- final UUID externalUuid = storage.getUuidForPath(MediaStore.getVolumePath(mVolumeName));
- return stats.queryStatsForPackage(externalUuid, getContext().getPackageName(),
- android.os.Process.myUserHandle()).getDataBytes();
- }
-
- private long getExternalTotalSize() throws Exception {
- final StorageManager storage = getContext().getSystemService(StorageManager.class);
- final StorageStatsManager stats = getContext().getSystemService(StorageStatsManager.class);
-
- final UUID externalUuid = storage.getUuidForPath(MediaStore.getVolumePath(mVolumeName));
- return stats.queryExternalStatsForUser(externalUuid, android.os.Process.myUserHandle())
- .getTotalBytes();
- }
-
- private HashSet<Long> getVisibleIds(Uri collectionUri) {
- final HashSet<Long> res = new HashSet<>();
- try (Cursor c = mContentResolver.query(collectionUri,
- new String[] { MediaColumns._ID }, null, null)) {
- while (c.moveToNext()) {
- res.add(c.getLong(0));
- }
- }
- return res;
- }
-
- private static void assertMostlyEquals(long expected, long actual, long delta) {
- if (Math.abs(expected - actual) > delta) {
- fail("Expected roughly " + expected + " but was " + actual);
- }
- }
}
diff --git a/tests/tests/provider/src/android/provider/cts/media/MediaStore_DownloadsTest.java b/tests/tests/provider/src/android/provider/cts/media/MediaStore_DownloadsTest.java
index 0b6af08..748e284 100644
--- a/tests/tests/provider/src/android/provider/cts/media/MediaStore_DownloadsTest.java
+++ b/tests/tests/provider/src/android/provider/cts/media/MediaStore_DownloadsTest.java
@@ -95,9 +95,9 @@
mExternalImages = MediaStore.Images.Media.getContentUri(mVolumeName);
mExternalDownloads = MediaStore.Downloads.getContentUri(mVolumeName);
- mDownloadsDir = new File(MediaStore.getVolumePath(resolveVolumeName(mVolumeName)),
+ mDownloadsDir = new File(ProviderTestUtils.getVolumePath(resolveVolumeName(mVolumeName)),
Environment.DIRECTORY_DOWNLOADS);
- mPicturesDir = new File(MediaStore.getVolumePath(resolveVolumeName(mVolumeName)),
+ mPicturesDir = new File(ProviderTestUtils.getVolumePath(resolveVolumeName(mVolumeName)),
Environment.DIRECTORY_PICTURES);
mDownloadsDir.mkdirs();
mPicturesDir.mkdirs();
diff --git a/tests/tests/provider/src/android/provider/cts/media/MediaStore_FilesTest.java b/tests/tests/provider/src/android/provider/cts/media/MediaStore_FilesTest.java
index 757766e..2b91cc4 100644
--- a/tests/tests/provider/src/android/provider/cts/media/MediaStore_FilesTest.java
+++ b/tests/tests/provider/src/android/provider/cts/media/MediaStore_FilesTest.java
@@ -213,7 +213,7 @@
@Test
public void testAccess() throws Exception {
- final String path = MediaStore.getVolumePath(resolveVolumeName(mVolumeName))
+ final String path = ProviderTestUtils.getVolumePath(resolveVolumeName(mVolumeName))
.getAbsolutePath();
final Uri updateUri = ContentUris.withAppendedId(mExternalFiles,
ContentUris.parseId(ProviderTestUtils.stageMedia(R.raw.volantis, mExternalImages)));
diff --git a/tests/tests/provider/src/android/provider/cts/media/MediaStore_Images_ThumbnailsTest.java b/tests/tests/provider/src/android/provider/cts/media/MediaStore_Images_ThumbnailsTest.java
index 5d0199b..874d82c 100644
--- a/tests/tests/provider/src/android/provider/cts/media/MediaStore_Images_ThumbnailsTest.java
+++ b/tests/tests/provider/src/android/provider/cts/media/MediaStore_Images_ThumbnailsTest.java
@@ -125,7 +125,7 @@
mBlue = ProviderTestUtils.stageMedia(R.raw.scenery, mExternalImages);
mRowsAdded.add(mRed);
mRowsAdded.add(mBlue);
- MediaStore.waitForIdle(mContext);
+ ProviderTestUtils.waitForIdle();
}
public static void assertMostlyEquals(long expected, long actual, long delta) {
@@ -208,7 +208,7 @@
String imagePath = c.getString(c.getColumnIndex(Media.DATA));
c.close();
- MediaStore.waitForIdle(mContext);
+ ProviderTestUtils.waitForIdle();
assertExists("image file does not exist", imagePath);
assertNotNull(Thumbnails.getThumbnail(resolver, imageId, Thumbnails.MINI_KIND, null));
assertNotNull(Thumbnails.getThumbnail(resolver, imageId, Thumbnails.MICRO_KIND, null));
@@ -219,7 +219,7 @@
mContentResolver.delete(stringUri, null, null);
mRowsAdded.remove(stringUri);
- MediaStore.waitForIdle(mContext);
+ ProviderTestUtils.waitForIdle();
assertNotExists("image file should no longer exist", imagePath);
assertNull(Thumbnails.getThumbnail(resolver, imageId, Thumbnails.MINI_KIND, null));
assertNull(Thumbnails.getThumbnail(resolver, imageId, Thumbnails.MICRO_KIND, null));
@@ -306,14 +306,14 @@
"test description"));
long imageId = ContentUris.parseId(uri);
- MediaStore.waitForIdle(mContext);
+ ProviderTestUtils.waitForIdle();
assertNotNull(Thumbnails.getThumbnail(resolver, imageId, Thumbnails.MINI_KIND, null));
assertNotNull(Thumbnails.getThumbnail(resolver, imageId, Thumbnails.MICRO_KIND, null));
// delete the source image and check that the thumbnail is gone too
mContentResolver.delete(uri, null /* where clause */, null /* where args */);
- MediaStore.waitForIdle(mContext);
+ ProviderTestUtils.waitForIdle();
assertNull(Thumbnails.getThumbnail(resolver, imageId, Thumbnails.MINI_KIND, null));
assertNull(Thumbnails.getThumbnail(resolver, imageId, Thumbnails.MICRO_KIND, null));
@@ -323,7 +323,7 @@
imageId = ContentUris.parseId(uri);
// query its thumbnail again
- MediaStore.waitForIdle(mContext);
+ ProviderTestUtils.waitForIdle();
assertNotNull(Thumbnails.getThumbnail(resolver, imageId, Thumbnails.MINI_KIND, null));
assertNotNull(Thumbnails.getThumbnail(resolver, imageId, Thumbnails.MICRO_KIND, null));
@@ -334,7 +334,7 @@
1, mContentResolver.update(uri, values, null /* where */, null /* where args */));
// image was marked as regular file in the database, which should have deleted its thumbnail
- MediaStore.waitForIdle(mContext);
+ ProviderTestUtils.waitForIdle();
assertNull(Thumbnails.getThumbnail(resolver, imageId, Thumbnails.MINI_KIND, null));
assertNull(Thumbnails.getThumbnail(resolver, imageId, Thumbnails.MICRO_KIND, null));
@@ -371,7 +371,7 @@
Media.insertImage(mContentResolver, src, "cts" + System.nanoTime(), null));
mRowsAdded.add(url[i]);
long origId = Long.parseLong(url[i].getLastPathSegment());
- MediaStore.waitForIdle(mContext);
+ ProviderTestUtils.waitForIdle();
Bitmap foo = MediaStore.Images.Thumbnails.getThumbnail(mContentResolver,
origId, Thumbnails.MICRO_KIND, null);
assertNotNull(foo);
@@ -388,7 +388,7 @@
long remainingId2 = Long.parseLong(url[2].getLastPathSegment());
// check if a thumbnail is still being returned for the image that was removed
- MediaStore.waitForIdle(mContext);
+ ProviderTestUtils.waitForIdle();
Bitmap foo = MediaStore.Images.Thumbnails.getThumbnail(mContentResolver,
removedId, Thumbnails.MICRO_KIND, null);
assertNull(foo);
@@ -399,7 +399,7 @@
MediaColumns._ID + order);
while (c.moveToNext()) {
long id = c.getLong(c.getColumnIndex(MediaColumns._ID));
- MediaStore.waitForIdle(mContext);
+ ProviderTestUtils.waitForIdle();
foo = MediaStore.Images.Thumbnails.getThumbnail(
mContentResolver, id,
MediaStore.Images.Thumbnails.MICRO_KIND, null);
@@ -439,7 +439,7 @@
{
// Thumbnail should be smaller
- MediaStore.waitForIdle(mContext);
+ ProviderTestUtils.waitForIdle();
final Bitmap thumb = mContentResolver.loadThumbnail(finalUri, new Size(32, 32), null);
assertTrue(thumb.getWidth() < full.getWidth());
assertTrue(thumb.getHeight() < full.getHeight());
@@ -456,7 +456,7 @@
MediaStore.Images.Thumbnails.MICRO_KIND
}) {
// Thumbnail should be smaller
- MediaStore.waitForIdle(mContext);
+ ProviderTestUtils.waitForIdle();
final Bitmap thumb = MediaStore.Images.Thumbnails.getThumbnail(mContentResolver,
ContentUris.parseId(finalUri), kind, null);
assertTrue(thumb.getWidth() < full.getWidth());
@@ -473,11 +473,11 @@
}
// Wait a few moments for events to settle
- MediaStore.waitForIdle(mContext);
+ ProviderTestUtils.waitForIdle();
{
// Thumbnail should match updated contents
- MediaStore.waitForIdle(mContext);
+ ProviderTestUtils.waitForIdle();
final Bitmap thumb = mContentResolver.loadThumbnail(finalUri, new Size(32, 32), null);
assertColorMostlyEquals(Color.BLUE, thumb.getPixel(16, 16));
}
@@ -487,7 +487,7 @@
// Thumbnail should no longer exist
try {
- MediaStore.waitForIdle(mContext);
+ ProviderTestUtils.waitForIdle();
mContentResolver.loadThumbnail(finalUri, new Size(32, 32), null);
fail("Funky; we somehow made a thumbnail out of nothing?");
} catch (FileNotFoundException expected) {
diff --git a/tests/tests/provider/src/android/provider/cts/media/MediaStore_Video_ThumbnailsTest.java b/tests/tests/provider/src/android/provider/cts/media/MediaStore_Video_ThumbnailsTest.java
index 379e55d..31b2e7e 100644
--- a/tests/tests/provider/src/android/provider/cts/media/MediaStore_Video_ThumbnailsTest.java
+++ b/tests/tests/provider/src/android/provider/cts/media/MediaStore_Video_ThumbnailsTest.java
@@ -116,14 +116,14 @@
// Don't run the test if the codec isn't supported.
if (!hasCodec()) {
// Calling getThumbnail should not generate a new thumbnail.
- MediaStore.waitForIdle(mContext);
+ ProviderTestUtils.waitForIdle();
assertNull(Thumbnails.getThumbnail(mResolver, videoId, Thumbnails.MINI_KIND, null));
Log.i(TAG, "SKIPPING testGetThumbnail(): codec not supported");
return;
}
// Calling getThumbnail should generate a new thumbnail.
- MediaStore.waitForIdle(mContext);
+ ProviderTestUtils.waitForIdle();
assertNotNull(Thumbnails.getThumbnail(mResolver, videoId, Thumbnails.MINI_KIND, null));
assertNotNull(Thumbnails.getThumbnail(mResolver, videoId, Thumbnails.MICRO_KIND, null));
@@ -144,13 +144,13 @@
Uri uri = insertVideo();
// request thumbnail creation
- MediaStore.waitForIdle(mContext);
+ ProviderTestUtils.waitForIdle();
assertNotNull(Thumbnails.getThumbnail(mResolver, Long.valueOf(uri.getLastPathSegment()),
Thumbnails.MINI_KIND, null /* options */));
// delete the source video and check that the thumbnail is gone too
mResolver.delete(uri, null /* where clause */, null /* where args */);
- MediaStore.waitForIdle(mContext);
+ ProviderTestUtils.waitForIdle();
assertNull(Thumbnails.getThumbnail(mResolver, Long.valueOf(uri.getLastPathSegment()),
Thumbnails.MINI_KIND, null /* options */));
@@ -158,7 +158,7 @@
uri = insertVideo();
// request thumbnail creation
- MediaStore.waitForIdle(mContext);
+ ProviderTestUtils.waitForIdle();
assertNotNull(Thumbnails.getThumbnail(mResolver, Long.valueOf(uri.getLastPathSegment()),
Thumbnails.MINI_KIND, null));
@@ -169,7 +169,7 @@
1, mResolver.update(uri, values, null /* where */, null /* where args */));
// video was marked as regular file in the database, which should have deleted its thumbnail
- MediaStore.waitForIdle(mContext);
+ ProviderTestUtils.waitForIdle();
assertNull(Thumbnails.getThumbnail(mResolver, Long.valueOf(uri.getLastPathSegment()),
Thumbnails.MINI_KIND, null /* options */));
@@ -224,7 +224,7 @@
}
// Thumbnail should be smaller
- MediaStore.waitForIdle(mContext);
+ ProviderTestUtils.waitForIdle();
final Bitmap beforeThumb = mResolver.loadThumbnail(finalUri, new Size(64, 64), null);
assertTrue(beforeThumb.getWidth() < full.getWidth());
assertTrue(beforeThumb.getHeight() < full.getHeight());
@@ -237,7 +237,7 @@
MediaStore.Video.Thumbnails.FULL_SCREEN_KIND,
MediaStore.Video.Thumbnails.MICRO_KIND
}) {
- MediaStore.waitForIdle(mContext);
+ ProviderTestUtils.waitForIdle();
assertNotNull(MediaStore.Video.Thumbnails.getThumbnail(mResolver,
ContentUris.parseId(finalUri), kind, null));
}
@@ -250,7 +250,7 @@
}
// Thumbnail should match updated contents
- MediaStore.waitForIdle(mContext);
+ ProviderTestUtils.waitForIdle();
final Bitmap afterThumb = mResolver.loadThumbnail(finalUri, new Size(64, 64), null);
final int afterColor = afterThumb.getPixel(32, 32);
assertNotColorMostlyEquals(beforeColor, afterColor);
@@ -260,7 +260,7 @@
// Thumbnail should no longer exist
try {
- MediaStore.waitForIdle(mContext);
+ ProviderTestUtils.waitForIdle();
mResolver.loadThumbnail(finalUri, new Size(64, 64), null);
fail("Funky; we somehow made a thumbnail out of nothing?");
} catch (FileNotFoundException expected) {
diff --git a/tests/tests/sdkext/Android.bp b/tests/tests/sdkext/Android.bp
new file mode 100644
index 0000000..9ad6c7f
--- /dev/null
+++ b/tests/tests/sdkext/Android.bp
@@ -0,0 +1,30 @@
+// 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.
+
+android_test {
+ name: "CtsSdkExtTestCases",
+ defaults: ["cts_defaults"],
+ static_libs: [
+ "androidx.test.rules",
+ "ctstestrunner-axt",
+ ],
+ srcs: [ "src/**/*.java" ],
+ test_config: "CtsSdkExtTestCases.xml",
+ test_suites: [
+ "cts",
+ "mts",
+ "general-tests",
+ ],
+ sdk_version: "system_current",
+}
diff --git a/tests/tests/sdkext/AndroidManifest.xml b/tests/tests/sdkext/AndroidManifest.xml
new file mode 100644
index 0000000..a6391b5
--- /dev/null
+++ b/tests/tests/sdkext/AndroidManifest.xml
@@ -0,0 +1,28 @@
+<?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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.os.ext.cts">
+
+ <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.os.ext.cts"
+ android:label="CTS tests of android.os.ext">
+ <meta-data android:name="listener"
+ android:value="com.android.cts.runner.CtsTestRunListener" />
+ </instrumentation>
+
+</manifest>
diff --git a/tests/tests/sdkext/CtsSdkExtTestCases.xml b/tests/tests/sdkext/CtsSdkExtTestCases.xml
new file mode 100644
index 0000000..b22653c
--- /dev/null
+++ b/tests/tests/sdkext/CtsSdkExtTestCases.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Configuration for SdkExt Tests">
+ <option name="test-suite-tag" value="cts" />
+ <option name="config-descriptor:metadata" key="component" value="framework" />
+ <option name="config-descriptor:metadata" key="parameter" value="instant_app" />
+ <option name="config-descriptor:metadata" key="parameter" value="multi_abi" />
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsSdkExtTestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.os.ext.cts" />
+ </test>
+</configuration>
diff --git a/tests/tests/sdkext/TEST_MAPPING b/tests/tests/sdkext/TEST_MAPPING
new file mode 100644
index 0000000..91947f3
--- /dev/null
+++ b/tests/tests/sdkext/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "presubmit": [
+ {
+ "name": "CtsSdkExtTestCases"
+ }
+ ]
+}
diff --git a/tests/tests/sdkext/src/android/os/ext/cts/SdkExtensionsTest.java b/tests/tests/sdkext/src/android/os/ext/cts/SdkExtensionsTest.java
new file mode 100644
index 0000000..884f5ef
--- /dev/null
+++ b/tests/tests/sdkext/src/android/os/ext/cts/SdkExtensionsTest.java
@@ -0,0 +1,43 @@
+/*
+ * 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 android.os.ext.cts;
+
+import android.os.Build;
+import android.os.ext.SdkExtensions;
+import junit.framework.TestCase;
+
+public class SdkExtensionsTest extends TestCase {
+
+ /** Verify that getExtensionVersion only accepts valid extension SDKs */
+ public void testBadArgument() throws Exception {
+ // R is the first SDK version with extensions.
+ for (int sdk = -1_000_000; sdk < Build.VERSION_CODES.R; sdk++) {
+ try {
+ SdkExtensions.getExtensionVersion(sdk);
+ fail("expected IllegalArgumentException");
+ } catch (IllegalArgumentException expected) { }
+ }
+ }
+
+ /** Verifies that getExtensionVersion only return existing versions */
+ public void testValidValues() throws Exception {
+ for (int sdk = Build.VERSION_CODES.R; sdk <= 1_000_000; sdk++) {
+ // No extension SDKs versions yet.
+ assertEquals(0, SdkExtensions.getExtensionVersion(sdk));
+ }
+ }
+}
diff --git a/tests/tests/security/res/raw/cve_2017_0637.mp4 b/tests/tests/security/res/raw/cve_2017_0637.mp4
new file mode 100644
index 0000000..5765dbb
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2017_0637.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2017_13233_hevc.mp4 b/tests/tests/security/res/raw/cve_2017_13233_hevc.mp4
new file mode 100644
index 0000000..8b4858b
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2017_13233_hevc.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/cve_2019_2106_hevc.mp4 b/tests/tests/security/res/raw/cve_2019_2106_hevc.mp4
new file mode 100644
index 0000000..e8899bd
--- /dev/null
+++ b/tests/tests/security/res/raw/cve_2019_2106_hevc.mp4
Binary files differ
diff --git a/tests/tests/security/src/android/security/cts/NanoAppBundleTest.java b/tests/tests/security/src/android/security/cts/NanoAppBundleTest.java
index 4f7dffc..b621491 100644
--- a/tests/tests/security/src/android/security/cts/NanoAppBundleTest.java
+++ b/tests/tests/security/src/android/security/cts/NanoAppBundleTest.java
@@ -20,12 +20,14 @@
import android.platform.test.annotations.SecurityTest;
import androidx.test.InstrumentationRegistry;
+import android.content.pm.ActivityInfo;
import android.content.ComponentName;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
import android.app.Activity;
import android.app.ActivityManager;
@@ -114,17 +116,25 @@
private void trigger() {
Log.i(TAG, "start...");
+ String pkg = isCar(mContext) ? "com.android.car.settings" : "com.android.settings";
+ String cls = isCar(mContext)
+ ? "com.android.car.settings.accounts.AddAccountActivity"
+ : "com.android.settings.accounts.AddAccountSettings";
Intent intent = new Intent();
- intent.setComponent(new ComponentName(
- "com.android.settings",
- "com.android.settings.accounts.AddAccountSettings"));
+ intent.setComponent(new ComponentName(pkg, cls));
intent.setAction(Intent.ACTION_RUN);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
String authTypes[] = { SECURITY_CTS_PACKAGE_NAME };
intent.putExtra("account_types", authTypes);
- mContext.startActivity(intent);
-
+ ActivityInfo info = intent.resolveActivityInfo(
+ mContext.getPackageManager(), intent.getFlags());
+ // Will throw NullPointerException if activity not found.
+ if (info.exported) {
+ mContext.startActivity(intent);
+ } else {
+ Log.i(TAG, "Activity is not exported");
+ }
Log.i(TAG, "finsihed.");
}
@@ -356,4 +366,9 @@
return data;
}
}
+
+ private static boolean isCar(Context context) {
+ PackageManager pm = context.getPackageManager();
+ return pm.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE);
+ }
}
diff --git a/tests/tests/security/src/android/security/cts/ServicePermissionsTest.java b/tests/tests/security/src/android/security/cts/ServicePermissionsTest.java
index 60e27e6..bccbe59 100644
--- a/tests/tests/security/src/android/security/cts/ServicePermissionsTest.java
+++ b/tests/tests/security/src/android/security/cts/ServicePermissionsTest.java
@@ -107,6 +107,7 @@
} catch (SecurityException e) {
String msg = e.getMessage();
if ((msg == null) || msg.contains("android.permission.DUMP")) {
+ Log.d(TAG, "Service " + service + " correctly checked permission");
// Service correctly checked for DUMP permission, yay
} else {
// Service is throwing about something else; they're
@@ -115,7 +116,9 @@
continue;
}
} catch (TransactionTooLargeException | DeadObjectException e) {
- // SELinux likely prevented the dump - assume safe
+ // SELinux likely prevented the dump - assume safe, but log anywasy
+ // (as the exception might happens in some devices but not on others)
+ Log.w(TAG, "Service " + service + " threw exception: " + e);
continue;
} finally {
out.close();
diff --git a/tests/tests/security/src/android/security/cts/StagefrightTest.java b/tests/tests/security/src/android/security/cts/StagefrightTest.java
index 20c7632..4981a09 100644
--- a/tests/tests/security/src/android/security/cts/StagefrightTest.java
+++ b/tests/tests/security/src/android/security/cts/StagefrightTest.java
@@ -976,6 +976,87 @@
}
@SecurityTest(minPatchLevel = "2018-04")
+ public void testStagefright_cve_2017_13279() throws Exception {
+ Thread server = new Thread() {
+ @Override
+ public void run(){
+ try (ServerSocket serverSocket = new ServerSocket(8080);
+ Socket conn = serverSocket.accept()){
+ OutputStream stream = conn.getOutputStream();
+ byte http[] = ("HTTP/1.0 200 OK\r\nContent-Type: application/x-mpegURL\r\n\r\n"
+ + "#EXTM3U\n#EXT-X-STREAM-INF:\n").getBytes();
+ stream.write(http);
+ while(!conn.isClosed())
+ stream.write(("a\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\n"
+ + "a\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\n"
+ + "a\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\n"
+ + "a\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\n"
+ + "a\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\n"
+ + "a\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\n"
+ + "a\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\n"
+ + "a\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\n"
+ + "a\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\n"
+ + "a\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\n"
+ + "a\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\n"
+ + "a\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\n"
+ + "a\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\n"
+ + "a\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\n"
+ + "a\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\n"
+ + "a\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\n"
+ + "a\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\n"
+ + "a\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\n"
+ + "a\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\n"
+ + "a\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\n"
+ + "a\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\n"
+ + "a\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\n"
+ + "a\na\na\na\na\na\na\na\n").getBytes());
+ }
+ catch(IOException e){
+ }
+ }
+ };
+ server.start();
+ String uri = "http://127.0.0.1:8080/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/"
+ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.m3u8";
+ final MediaPlayerCrashListener mpcl = new MediaPlayerCrashListener();
+
+ LooperThread t = new LooperThread(new Runnable() {
+ @Override
+ public void run() {
+
+ MediaPlayer mp = new MediaPlayer();
+ mp.setOnErrorListener(mpcl);
+ mp.setOnPreparedListener(mpcl);
+ mp.setOnCompletionListener(mpcl);
+ RenderTarget renderTarget = RenderTarget.create();
+ Surface surface = renderTarget.getSurface();
+ mp.setSurface(surface);
+ AssetFileDescriptor fd = null;
+ try {
+ mp.setDataSource(uri);
+ mp.prepareAsync();
+ } catch (IOException e) {
+ Log.e(TAG, e.toString());
+ } finally {
+ closeQuietly(fd);
+ }
+
+ Looper.loop();
+ mp.release();
+ }
+ });
+ t.start();
+ Thread.sleep(60000); // Poc takes a while to crash mediaserver, waitForError
+ // doesn't wait long enough
+ assertFalse("Device *IS* vulnerable to CVE-2017-13279",
+ mpcl.waitForError() == MediaPlayer.MEDIA_ERROR_SERVER_DIED);
+ t.stopLooper();
+ t.join(); // wait for thread to exit so we're sure the player was released
+ server.join();
+ }
+
+ @SecurityTest(minPatchLevel = "2018-04")
public void testStagefright_cve_2017_13276() throws Exception {
doStagefrightTest(R.raw.cve_2017_13276);
}
@@ -1000,6 +1081,24 @@
before any existing test methods
***********************************************************/
+ @SecurityTest(minPatchLevel = "2018-02")
+ public void testStagefright_cve_2017_13233() throws Exception {
+ doStagefrightTestRawBlob(R.raw.cve_2017_13233_hevc, "video/hevc", 640,
+ 480);
+ }
+
+ @SecurityTest(minPatchLevel = "2019-07")
+ public void testStagefright_cve_2019_2106() throws Exception {
+ int[] frameSizes = {943, 3153};
+ doStagefrightTestRawBlob(R.raw.cve_2019_2106_hevc, "video/hevc", 320,
+ 240, frameSizes);
+ }
+
+ @SecurityTest(minPatchLevel = "2017-06")
+ public void testStagefright_cve_2017_0637() throws Exception {
+ doStagefrightTest(R.raw.cve_2017_0637, 2 * 72000);
+ }
+
@SecurityTest(minPatchLevel = "2018-09")
public void testStagefright_cve_2018_11287() throws Exception {
doStagefrightTest(R.raw.cve_2018_11287, 180000);
diff --git a/tests/tests/selinux/TEST_MAPPING b/tests/tests/selinux/TEST_MAPPING
new file mode 100644
index 0000000..a8bae77
--- /dev/null
+++ b/tests/tests/selinux/TEST_MAPPING
@@ -0,0 +1,20 @@
+{
+ "presubmit": [
+ {
+ "name": "CtsSelinuxEphemeralTestCases"
+ },
+ {
+ "name": "CtsSelinuxTargetSdk25TestCases"
+ },
+ {
+ "name": "CtsSelinuxTargetSdk27TestCases"
+ },
+ {
+ "name": "CtsSelinuxTargetSdk28TestCases"
+ },
+ {
+ "name": "CtsSelinuxTargetSdkCurrentTestCases"
+ }
+ ]
+}
+
diff --git a/tests/tests/systemui/src/android/systemui/cts/LightBarTests.java b/tests/tests/systemui/src/android/systemui/cts/LightBarTests.java
index 137c003..dc414ef 100644
--- a/tests/tests/systemui/src/android/systemui/cts/LightBarTests.java
+++ b/tests/tests/systemui/src/android/systemui/cts/LightBarTests.java
@@ -59,6 +59,13 @@
*/
private static final int COLOR_COMPONENT_ERROR_MARGIN = 20;
+ /**
+ * It's possible for the device to have color sampling enabled in the nav bar -- in that
+ * case we need to pick a background color that would result in the same dark icon tint
+ * that matches the default visibility flags used when color sampling is not enabled.
+ */
+ private static final int LIGHT_BG_COLOR = Color.rgb(255, 128, 128);
+
private final String NOTIFICATION_TAG = "TEST_TAG";
private final String NOTIFICATION_CHANNEL_ID = "test_channel";
private final String NOTIFICATION_GROUP_KEY = "test_group";
@@ -92,11 +99,11 @@
mNm.notify(NOTIFICATION_TAG, i, noti1.build());
}
- requestLightBars(Color.RED /* background */);
+ requestLightBars(LIGHT_BG_COLOR);
Thread.sleep(WAIT_TIME);
Bitmap bitmap = takeStatusBarScreenshot(mActivityRule.getActivity());
- Stats s = evaluateLightBarBitmap(bitmap, Color.RED /* background */, 0);
+ Stats s = evaluateLightBarBitmap(bitmap, LIGHT_BG_COLOR, 0);
assertLightStats(bitmap, s);
mNm.cancelAll();
@@ -107,7 +114,7 @@
public void testLightNavigationBar() throws Throwable {
assumeHasColoredNavigationBar(mActivityRule);
- requestLightBars(Color.RED /* background */);
+ requestLightBars(LIGHT_BG_COLOR);
Thread.sleep(WAIT_TIME);
// Inject a cancelled interaction with the nav bar to ensure it is at full opacity.
@@ -118,7 +125,7 @@
LightBarActivity activity = mActivityRule.getActivity();
Bitmap bitmap = takeNavigationBarScreenshot(activity);
- Stats s = evaluateLightBarBitmap(bitmap, Color.RED /* background */, activity.getBottom());
+ Stats s = evaluateLightBarBitmap(bitmap, LIGHT_BG_COLOR, activity.getBottom());
assertLightStats(bitmap, s);
}
diff --git a/tests/tests/telecom/CallScreeningServiceTestApp/AndroidManifest.xml b/tests/tests/telecom/CallScreeningServiceTestApp/AndroidManifest.xml
index c0b4673..7428130 100644
--- a/tests/tests/telecom/CallScreeningServiceTestApp/AndroidManifest.xml
+++ b/tests/tests/telecom/CallScreeningServiceTestApp/AndroidManifest.xml
@@ -33,5 +33,12 @@
<action android:name="android.telecom.cts.screeningtestapp.ACTION_CONTROL_CALL_SCREENING_SERVICE" />
</intent-filter>
</service>
+ <activity android:name=".CtsPostCallActivity"
+ android:label="CtsPostCallActivity">
+ <intent-filter>
+ <action android:name="android.telecom.action.POST_CALL" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ </activity>
</application>
</manifest>
diff --git a/tests/tests/telecom/CallScreeningServiceTestApp/aidl/android/telecom/cts/screeningtestapp/ICallScreeningControl.aidl b/tests/tests/telecom/CallScreeningServiceTestApp/aidl/android/telecom/cts/screeningtestapp/ICallScreeningControl.aidl
index 8da8769..9e7cc2c 100644
--- a/tests/tests/telecom/CallScreeningServiceTestApp/aidl/android/telecom/cts/screeningtestapp/ICallScreeningControl.aidl
+++ b/tests/tests/telecom/CallScreeningServiceTestApp/aidl/android/telecom/cts/screeningtestapp/ICallScreeningControl.aidl
@@ -26,4 +26,10 @@
boolean shouldSkipCall, boolean shouldSkipCallLog, boolean shouldSkipNotification);
boolean waitForBind();
+
+ boolean waitForActivity();
+
+ String getCachedHandle();
+
+ int getCachedDisconnectCause();
}
diff --git a/tests/tests/telecom/CallScreeningServiceTestApp/src/android/telecom/cts/screeningtestapp/CallScreeningServiceControl.java b/tests/tests/telecom/CallScreeningServiceTestApp/src/android/telecom/cts/screeningtestapp/CallScreeningServiceControl.java
index 954d9af..96f4173 100644
--- a/tests/tests/telecom/CallScreeningServiceTestApp/src/android/telecom/cts/screeningtestapp/CallScreeningServiceControl.java
+++ b/tests/tests/telecom/CallScreeningServiceTestApp/src/android/telecom/cts/screeningtestapp/CallScreeningServiceControl.java
@@ -52,6 +52,7 @@
.setSkipNotification(false)
.build();
mBindingLatch = new CountDownLatch(1);
+ CtsPostCallActivity.resetPostCallActivity();
}
@Override
@@ -78,6 +79,21 @@
return false;
}
}
+
+ @Override
+ public boolean waitForActivity() {
+ return CtsPostCallActivity.waitForActivity();
+ }
+
+ @Override
+ public String getCachedHandle() {
+ return CtsPostCallActivity.getCachedHandle().getSchemeSpecificPart();
+ }
+
+ @Override
+ public int getCachedDisconnectCause() {
+ return CtsPostCallActivity.getCachedDisconnectCause();
+ }
};
private CallScreeningService.CallResponse mCallResponse =
diff --git a/tests/tests/telecom/CallScreeningServiceTestApp/src/android/telecom/cts/screeningtestapp/CtsPostCallActivity.java b/tests/tests/telecom/CallScreeningServiceTestApp/src/android/telecom/cts/screeningtestapp/CtsPostCallActivity.java
new file mode 100644
index 0000000..ac5ce01
--- /dev/null
+++ b/tests/tests/telecom/CallScreeningServiceTestApp/src/android/telecom/cts/screeningtestapp/CtsPostCallActivity.java
@@ -0,0 +1,73 @@
+/*
+ * 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 android.telecom.cts.screeningtestapp;
+
+import static android.telecom.TelecomManager.EXTRA_DISCONNECT_CAUSE;
+import static android.telecom.TelecomManager.EXTRA_HANDLE;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+public class CtsPostCallActivity extends Activity {
+ private static final String ACTION_POST_CALL = "android.telecom.action.POST_CALL";
+ private static final int DEFAULT_DISCONNECT_CAUSE = -1;
+ private static final long TEST_TIMEOUT = 5000;
+
+ private static Uri cachedHandle;
+ private static int cachedDisconnectCause;
+ private static CountDownLatch sLatch = new CountDownLatch(1);
+
+ @Override
+ protected void onCreate(Bundle bundle) {
+ super.onCreate(bundle);
+ final Intent intent = getIntent();
+ final String action = intent != null ? intent.getAction() : null;
+ if (ACTION_POST_CALL.equals(action)) {
+ cachedHandle = intent.getParcelableExtra(EXTRA_HANDLE);
+ cachedDisconnectCause = intent
+ .getIntExtra(EXTRA_DISCONNECT_CAUSE, DEFAULT_DISCONNECT_CAUSE);
+ sLatch.countDown();
+ }
+ }
+
+ public static Uri getCachedHandle() {
+ return cachedHandle;
+ }
+
+ public static int getCachedDisconnectCause() {
+ return cachedDisconnectCause;
+ }
+
+ public static void resetPostCallActivity() {
+ sLatch = new CountDownLatch(1);
+ cachedHandle = null;
+ cachedDisconnectCause = DEFAULT_DISCONNECT_CAUSE;
+ }
+
+ public static boolean waitForActivity() {
+ try {
+ return sLatch.await(TEST_TIMEOUT, TimeUnit.MILLISECONDS);
+ } catch (InterruptedException e) {
+ return false;
+ }
+ }
+}
diff --git a/tests/tests/telecom/src/android/telecom/cts/CarModeInCallServiceTest.java b/tests/tests/telecom/src/android/telecom/cts/CarModeInCallServiceTest.java
index d498de0..7d81184 100644
--- a/tests/tests/telecom/src/android/telecom/cts/CarModeInCallServiceTest.java
+++ b/tests/tests/telecom/src/android/telecom/cts/CarModeInCallServiceTest.java
@@ -76,10 +76,10 @@
mCarModeIncallServiceControlTwo.reset();
}
+ assertUiMode(Configuration.UI_MODE_TYPE_NORMAL);
+
InstrumentationRegistry.getInstrumentation().getUiAutomation()
.dropShellPermissionIdentity();
-
- assertUiMode(Configuration.UI_MODE_TYPE_NORMAL);
}
/**
diff --git a/tests/tests/telecom/src/android/telecom/cts/ExtendedInCallServiceTest.java b/tests/tests/telecom/src/android/telecom/cts/ExtendedInCallServiceTest.java
index e7dddd2..10cd943 100644
--- a/tests/tests/telecom/src/android/telecom/cts/ExtendedInCallServiceTest.java
+++ b/tests/tests/telecom/src/android/telecom/cts/ExtendedInCallServiceTest.java
@@ -400,7 +400,11 @@
}
private Uri blockNumber(Uri phoneNumberUri) {
- return insertBlockedNumber(mContext, phoneNumberUri.getSchemeSpecificPart());
+ Uri number = insertBlockedNumber(mContext, phoneNumberUri.getSchemeSpecificPart());
+ if (number == null) {
+ fail("Failed to insert into blocked number provider");
+ }
+ return number;
}
private int unblockNumber(Uri uri) {
diff --git a/tests/tests/telecom/src/android/telecom/cts/ThirdPartyCallScreeningServiceTest.java b/tests/tests/telecom/src/android/telecom/cts/ThirdPartyCallScreeningServiceTest.java
index 532c69e..76c7c72 100644
--- a/tests/tests/telecom/src/android/telecom/cts/ThirdPartyCallScreeningServiceTest.java
+++ b/tests/tests/telecom/src/android/telecom/cts/ThirdPartyCallScreeningServiceTest.java
@@ -273,6 +273,32 @@
assertFalse(mCallScreeningControl.waitForBind());
}
+ public void testNoPostCallActivityWithoutRole() throws Exception {
+ if (!shouldTestTelecom(mContext)) {
+ return;
+ }
+
+ removeRoleHolder(ROLE_CALL_SCREENING, CtsCallScreeningService.class.getPackage().getName());
+ addIncomingAndVerifyAllowed(false);
+ assertFalse(mCallScreeningControl.waitForActivity());
+ }
+
+ public void testAllowCall() throws Exception {
+ mCallScreeningControl.setCallResponse(false /* shouldDisallowCall */,
+ false /* shouldRejectCall */, false /* shouldSilenceCall */,
+ false /* shouldSkipCallLog */, false /* shouldSkipNotification */);
+ addIncomingAndVerifyAllowed(false /* addContact */);
+ assertTrue(mCallScreeningControl.waitForActivity());
+ }
+
+ public void testNoPostCallActivityWhenBlocked() throws Exception {
+ mCallScreeningControl.setCallResponse(true /* shouldDisallowCall */,
+ true /* shouldRejectCall */, false /* shouldSilenceCall */,
+ false /* shouldSkipCallLog */, true /* shouldSkipNotification */);
+ addIncomingAndVerifyBlocked(false /* addContact */);
+ assertFalse(mCallScreeningControl.waitForActivity());
+ }
+
private void placeOutgoingCall(boolean addContact) throws Exception {
// Setup content observer to notify us when we call log entry is added.
CountDownLatch callLogEntryLatch = getCallLogEntryLatch();
diff --git a/tests/tests/telecom/src/android/telecom/cts/carmodetestapp/CtsCarModeInCallServiceControl.java b/tests/tests/telecom/src/android/telecom/cts/carmodetestapp/CtsCarModeInCallServiceControl.java
index c815b75..3ec5d83 100644
--- a/tests/tests/telecom/src/android/telecom/cts/carmodetestapp/CtsCarModeInCallServiceControl.java
+++ b/tests/tests/telecom/src/android/telecom/cts/carmodetestapp/CtsCarModeInCallServiceControl.java
@@ -43,7 +43,7 @@
@Override
public boolean isUnbound() {
- return CtsCarModeInCallService.isBound();
+ return CtsCarModeInCallService.isUnbound();
}
@Override
diff --git a/tests/tests/telephony/OWNERS b/tests/tests/telephony/OWNERS
index 73fa25e..d4ae5d0 100644
--- a/tests/tests/telephony/OWNERS
+++ b/tests/tests/telephony/OWNERS
@@ -4,11 +4,10 @@
jackyu@google.com
rgreenwalt@google.com
refuhoo@google.com
-mpq@google.com
jminjie@google.com
shuoq@google.com
hallliu@google.com
tgunn@google.com
breadley@google.com
-paulye@google.com
nazaninb@google.com
+sarahchin@google.com
diff --git a/tests/tests/telephony/current/TestExternalImsServiceApp/aidl/android/telephony/cts/externalimsservice/ITestExternalImsService.aidl b/tests/tests/telephony/current/TestExternalImsServiceApp/aidl/android/telephony/cts/externalimsservice/ITestExternalImsService.aidl
index 6a34175..86c8305 100644
--- a/tests/tests/telephony/current/TestExternalImsServiceApp/aidl/android/telephony/cts/externalimsservice/ITestExternalImsService.aidl
+++ b/tests/tests/telephony/current/TestExternalImsServiceApp/aidl/android/telephony/cts/externalimsservice/ITestExternalImsService.aidl
@@ -28,4 +28,8 @@
boolean isRcsFeatureCreated();
boolean isMmTelFeatureCreated();
void resetState();
-}
\ No newline at end of file
+ void updateImsRegistration(int radioTech);
+ void notifyRcsCapabilitiesStatusChanged(int capability);
+ boolean isRcsCapable(int capability, int radioTech);
+ boolean isRcsAvailable(int capability);
+}
diff --git a/tests/tests/telephony/current/TestExternalImsServiceApp/src/android/telephony/cts/externalimsservice/TestExternalImsService.java b/tests/tests/telephony/current/TestExternalImsServiceApp/src/android/telephony/cts/externalimsservice/TestExternalImsService.java
index 48e71a3..1f1c747 100644
--- a/tests/tests/telephony/current/TestExternalImsServiceApp/src/android/telephony/cts/externalimsservice/TestExternalImsService.java
+++ b/tests/tests/telephony/current/TestExternalImsServiceApp/src/android/telephony/cts/externalimsservice/TestExternalImsService.java
@@ -20,7 +20,9 @@
import android.os.IBinder;
import android.telephony.ims.cts.ImsUtils;
import android.telephony.ims.cts.TestImsService;
+import android.telephony.ims.feature.RcsFeature.RcsImsCapabilities;
import android.telephony.ims.stub.ImsFeatureConfiguration;
+import android.telephony.ims.stub.ImsRegistrationImplBase;
import android.util.Log;
/**
@@ -40,18 +42,41 @@
public boolean waitForLatchCountdown(int latchIndex) {
return TestExternalImsService.this.waitForLatchCountdown(latchIndex);
}
+
public void setFeatureConfig(ImsFeatureConfiguration f) {
TestExternalImsService.this.setFeatureConfig(f);
}
+
public boolean isRcsFeatureCreated() {
return (getRcsFeature() != null);
}
+
public boolean isMmTelFeatureCreated() {
return (getMmTelFeature() != null);
}
+
public void resetState() {
TestExternalImsService.this.resetState();
}
+
+ public void updateImsRegistration(int imsRadioTech) {
+ ImsRegistrationImplBase imsReg = TestExternalImsService.this.getImsRegistration();
+ imsReg.onRegistered(imsRadioTech);
+ }
+
+ public void notifyRcsCapabilitiesStatusChanged(int capability) {
+ RcsImsCapabilities capabilities = new RcsImsCapabilities(capability);
+ getRcsFeature().notifyCapabilitiesStatusChanged(capabilities);
+ }
+
+ public boolean isRcsCapable(int capability, int radioTech) {
+ return getRcsFeature().queryCapabilityConfiguration(capability, radioTech);
+ }
+
+ public boolean isRcsAvailable(int capability) {
+ RcsImsCapabilities capabilityStatus = getRcsFeature().queryCapabilityStatus();
+ return capabilityStatus.isCapable(capability);
+ }
}
@Override
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/CarrierConfigManagerTest.java b/tests/tests/telephony/current/src/android/telephony/cts/CarrierConfigManagerTest.java
index aeeb9b1..83aaa0b 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/CarrierConfigManagerTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/CarrierConfigManagerTest.java
@@ -51,6 +51,7 @@
import org.junit.After;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
import java.io.IOException;
@@ -145,6 +146,7 @@
}
@SecurityTest
+ @Ignore // TODO(b/146238285) -- Appop commands not working.
@Test
public void testRevokePermission() {
if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/SmsCbMessageTest.java b/tests/tests/telephony/current/src/android/telephony/cts/SmsCbMessageTest.java
index 211f9ff..6b1ca39 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/SmsCbMessageTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/SmsCbMessageTest.java
@@ -67,6 +67,12 @@
@Before
public void setUp() {
+ TEST_GEOS.add(new CbGeoUtils.Geometry() {
+ @Override
+ public boolean contains(CbGeoUtils.LatLng p) {
+ return false;
+ }
+ });
mSmsCbMessage = new SmsCbMessage(TEST_MESSAGE_FORMAT, TEST_GEO_SCOPE, TEST_SERIAL,
TEST_LOCATION, TEST_SERVICE_CATEGORY, TEST_LANGUAGE, TEST_BODY, TEST_PRIORITY,
TEST_ETWS_INFO, null, TEST_MAX_WAIT_TIME, TEST_GEOS, TEST_RECEIVED_TIME,
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/SmsManagerTest.java b/tests/tests/telephony/current/src/android/telephony/cts/SmsManagerTest.java
index c272764..328fe82 100755
--- a/tests/tests/telephony/current/src/android/telephony/cts/SmsManagerTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/SmsManagerTest.java
@@ -366,24 +366,6 @@
}
@Test
- public void testGetSmsMessagesForFinancialAppPermissionNotRequested() throws Exception {
- final CountDownLatch latch = new CountDownLatch(1);
-
- try {
- getSmsManager().getSmsMessagesForFinancialApp(new Bundle(),
- getInstrumentation().getContext().getMainExecutor(),
- new SmsManager.FinancialSmsCallback() {
- public void onFinancialSmsMessages(CursorWindow msgs) {
- assertNull(msgs);
- latch.countDown();
- }});
- assertTrue(latch.await(500, TimeUnit.MILLISECONDS));
- } catch (Exception e) {
- // do nothing
- }
- }
-
- @Test
public void testGetSmsMessagesForFinancialAppPermissionRequestedNotGranted() throws Exception {
CompletableFuture<Bundle> callbackResult = new CompletableFuture<>();
@@ -690,6 +672,9 @@
private void blockNumber(String number) {
mBlockedNumberUri = insertBlockedNumber(mContext, number);
+ if (mBlockedNumberUri == null) {
+ fail("Failed to insert into blocked number provider.");
+ }
}
private void unblockNumber(Uri uri) {
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java b/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java
index 0169b4b..052a21f 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java
@@ -467,6 +467,8 @@
mTelephonyManager.isVoicemailVibrationEnabled(defaultAccount);
mTelephonyManager.getSubscriptionId(defaultAccount);
mTelephonyManager.getCarrierConfig();
+ ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
+ (tm) -> tm.isAnyRadioPoweredOn());
TelephonyManager.getDefaultRespondViaMessageApplication(getContext(), false);
}
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/TelephonyPermissionPolicyTest.java b/tests/tests/telephony/current/src/android/telephony/cts/TelephonyPermissionPolicyTest.java
index caf9b4c..37228c8 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/TelephonyPermissionPolicyTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/TelephonyPermissionPolicyTest.java
@@ -34,6 +34,8 @@
KNOWN_TELEPHONY_PACKAGES.add("com.android.providers.telephony");
KNOWN_TELEPHONY_PACKAGES.add("com.android.ons");
KNOWN_TELEPHONY_PACKAGES.add("com.android.cellbroadcastservice");
+ KNOWN_TELEPHONY_PACKAGES.add("com.android.cellbroadcastreceiver");
+ KNOWN_TELEPHONY_PACKAGES.add("com.android.shell");
}
@Test
diff --git a/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsServiceConnector.java b/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsServiceConnector.java
index 9215672..dcc0f9a 100644
--- a/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsServiceConnector.java
+++ b/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsServiceConnector.java
@@ -26,6 +26,7 @@
import android.telephony.cts.TelephonyUtils;
import android.telephony.cts.externalimsservice.ITestExternalImsService;
import android.telephony.cts.externalimsservice.TestExternalImsService;
+import android.telephony.ims.feature.ImsFeature;
import android.telephony.ims.stub.ImsFeatureConfiguration;
import android.util.Log;
@@ -56,6 +57,7 @@
private static final String COMMAND_CARRIER_SERVICE_IDENTIFIER = "-c ";
private static final String COMMAND_DEVICE_SERVICE_IDENTIFIER = "-d ";
private static final String COMMAND_SLOT_IDENTIFIER = "-s ";
+ private static final String COMMAND_FEATURE_IDENTIFIER = "-f ";
private static final String COMMAND_ENABLE_IMS = "ims enable ";
private static final String COMMAND_DISABLE_IMS = "ims disable ";
@@ -106,7 +108,9 @@
private static final int CONNECTION_TYPE_DEFAULT_SMS_APP = 3;
private boolean mIsServiceOverridden = false;
- private String mOrigServicePackage;
+ private String mOrigMmTelServicePackage;
+ private String mOrigRcsServicePackage;
+ private String mOrigSmsPackage;
private int mConnectionType;
private int mSlotId;
Connection(int connectionType, int slotId) {
@@ -118,7 +122,7 @@
mIsServiceOverridden = true;
switch (mConnectionType) {
case CONNECTION_TYPE_IMS_SERVICE_CARRIER: {
- setCarrierImsService("");
+ setCarrierImsService("none");
break;
}
case CONNECTION_TYPE_IMS_SERVICE_DEVICE: {
@@ -152,21 +156,28 @@
if (!mIsServiceOverridden) {
return;
}
- if (mOrigServicePackage == null) {
- mOrigServicePackage = "";
+
+ if (mOrigRcsServicePackage == null) {
+ mOrigRcsServicePackage = "";
+ }
+
+ if (mOrigMmTelServicePackage == null) {
+ mOrigMmTelServicePackage = "";
}
switch (mConnectionType) {
case CONNECTION_TYPE_IMS_SERVICE_CARRIER: {
- setCarrierImsService(mOrigServicePackage);
+ setCarrierImsService(mOrigMmTelServicePackage, ImsFeature.FEATURE_MMTEL);
+ setCarrierImsService(mOrigRcsServicePackage, ImsFeature.FEATURE_RCS);
break;
}
case CONNECTION_TYPE_IMS_SERVICE_DEVICE: {
- setDeviceImsService(mOrigServicePackage);
+ setDeviceImsService(mOrigMmTelServicePackage, ImsFeature.FEATURE_MMTEL);
+ setDeviceImsService(mOrigRcsServicePackage, ImsFeature.FEATURE_RCS);
break;
}
case CONNECTION_TYPE_DEFAULT_SMS_APP: {
- setDefaultSmsApp(mOrigServicePackage);
+ setDefaultSmsApp(mOrigSmsPackage);
break;
}
}
@@ -175,15 +186,17 @@
private void storeOriginalPackage() throws Exception {
switch (mConnectionType) {
case CONNECTION_TYPE_IMS_SERVICE_CARRIER: {
- mOrigServicePackage = getOriginalCarrierService();
+ mOrigMmTelServicePackage = getOriginalMmTelCarrierService();
+ mOrigRcsServicePackage = getOriginalRcsCarrierService();
break;
}
case CONNECTION_TYPE_IMS_SERVICE_DEVICE: {
- mOrigServicePackage = getOriginalDeviceService();
+ mOrigMmTelServicePackage = getOriginalMmTelDeviceService();
+ mOrigRcsServicePackage = getOriginalRcsDeviceService();
break;
}
case CONNECTION_TYPE_DEFAULT_SMS_APP: {
- mOrigServicePackage = getDefaultSmsApp();
+ mOrigSmsPackage = getDefaultSmsApp();
break;
}
}
@@ -191,18 +204,40 @@
private boolean setDeviceImsService(String packageName) throws Exception {
String result = TelephonyUtils.executeShellCommand(mInstrumentation,
- constructSetImsServiceOverrideCommand(false, packageName));
+ constructSetImsServiceOverrideCommand(false, packageName, new int[] {
+ ImsFeature.FEATURE_MMTEL, ImsFeature.FEATURE_RCS}));
if (ImsUtils.VDBG) {
- Log.d(TAG, "setDeviceImsService result: " + result);
+ Log.d(TAG, "setDeviceMmTelImsService result: " + result);
}
return "true".equals(result);
}
private boolean setCarrierImsService(String packageName) throws Exception {
String result = TelephonyUtils.executeShellCommand(mInstrumentation,
- constructSetImsServiceOverrideCommand(true, packageName));
+ constructSetImsServiceOverrideCommand(true, packageName, new int[] {
+ ImsFeature.FEATURE_MMTEL, ImsFeature.FEATURE_RCS}));
if (ImsUtils.VDBG) {
- Log.d(TAG, "setCarrierImsService result: " + result);
+ Log.d(TAG, "setCarrierMmTelImsService result: " + result);
+ }
+ return "true".equals(result);
+ }
+
+ private boolean setDeviceImsService(String packageName, int featureType) throws Exception {
+ String result = TelephonyUtils.executeShellCommand(mInstrumentation,
+ constructSetImsServiceOverrideCommand(false, packageName,
+ new int[]{featureType}));
+ if (ImsUtils.VDBG) {
+ Log.d(TAG, "setDeviceMmTelImsService result: " + result);
+ }
+ return "true".equals(result);
+ }
+
+ private boolean setCarrierImsService(String packageName, int featureType) throws Exception {
+ String result = TelephonyUtils.executeShellCommand(mInstrumentation,
+ constructSetImsServiceOverrideCommand(true, packageName,
+ new int[]{featureType}));
+ if (ImsUtils.VDBG) {
+ Log.d(TAG, "setCarrierMmTelImsService result: " + result);
}
return "true".equals(result);
}
@@ -249,36 +284,67 @@
TestImsService.LATCH_FEATURES_READY);
}
- private String getOriginalCarrierService() throws Exception {
+ private String getOriginalMmTelCarrierService() throws Exception {
String result = TelephonyUtils.executeShellCommand(mInstrumentation,
- constructGetImsServiceCommand(true));
+ constructGetImsServiceCommand(true, ImsFeature.FEATURE_MMTEL));
if (ImsUtils.VDBG) {
- Log.d(TAG, "getOriginalCarrierService result: " + result);
+ Log.d(TAG, "getOriginalMmTelCarrierService result: " + result);
}
return result;
}
- private String getOriginalDeviceService() throws Exception {
+ private String getOriginalRcsCarrierService() throws Exception {
String result = TelephonyUtils.executeShellCommand(mInstrumentation,
- constructGetImsServiceCommand(false));
+ constructGetImsServiceCommand(true, ImsFeature.FEATURE_RCS));
if (ImsUtils.VDBG) {
- Log.d(TAG, "getOriginalDeviceService result: " + result);
+ Log.d(TAG, "getOriginalRcsCarrierService result: " + result);
+ }
+ return result;
+ }
+
+ private String getOriginalMmTelDeviceService() throws Exception {
+ String result = TelephonyUtils.executeShellCommand(mInstrumentation,
+ constructGetImsServiceCommand(false, ImsFeature.FEATURE_MMTEL));
+ if (ImsUtils.VDBG) {
+ Log.d(TAG, "getOriginalMmTelDeviceService result: " + result);
+ }
+ return result;
+ }
+
+ private String getOriginalRcsDeviceService() throws Exception {
+ String result = TelephonyUtils.executeShellCommand(mInstrumentation,
+ constructGetImsServiceCommand(false, ImsFeature.FEATURE_RCS));
+ if (ImsUtils.VDBG) {
+ Log.d(TAG, "getOriginalRcsDeviceService result: " + result);
}
return result;
}
private String constructSetImsServiceOverrideCommand(boolean isCarrierService,
- String packageName) {
+ String packageName, int[] featureTypes) {
return COMMAND_BASE + COMMAND_SET_IMS_SERVICE + COMMAND_SLOT_IDENTIFIER + mSlotId + " "
+ (isCarrierService
? COMMAND_CARRIER_SERVICE_IDENTIFIER : COMMAND_DEVICE_SERVICE_IDENTIFIER)
+ + COMMAND_FEATURE_IDENTIFIER + getFeatureTypesString(featureTypes) + " "
+ packageName;
}
- private String constructGetImsServiceCommand(boolean isCarrierService) {
+ private String constructGetImsServiceCommand(boolean isCarrierService, int featureType) {
return COMMAND_BASE + COMMAND_GET_IMS_SERVICE + COMMAND_SLOT_IDENTIFIER + mSlotId + " "
+ (isCarrierService
- ? COMMAND_CARRIER_SERVICE_IDENTIFIER : COMMAND_DEVICE_SERVICE_IDENTIFIER);
+ ? COMMAND_CARRIER_SERVICE_IDENTIFIER : COMMAND_DEVICE_SERVICE_IDENTIFIER)
+ + COMMAND_FEATURE_IDENTIFIER + featureType;
+ }
+
+ private String getFeatureTypesString(int[] featureTypes) {
+ if (featureTypes.length == 0) return "";
+ StringBuilder builder = new StringBuilder();
+ builder.append(featureTypes[0]);
+ for (int i = 1; i < featureTypes.length; i++) {
+ builder.append(",");
+ builder.append(featureTypes[i]);
+ }
+ return builder.toString();
}
}
diff --git a/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsServiceTest.java b/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsServiceTest.java
index d6698c9..1772152 100644
--- a/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsServiceTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsServiceTest.java
@@ -40,13 +40,17 @@
import android.telephony.TelephonyManager;
import android.telephony.cts.AsyncSmsMessageListener;
import android.telephony.cts.SmsReceiverHelper;
+import android.telephony.cts.externalimsservice.ITestExternalImsService;
import android.telephony.ims.ImsException;
+import android.telephony.ims.ImsManager;
import android.telephony.ims.ImsMmTelManager;
+import android.telephony.ims.ImsRcsManager;
import android.telephony.ims.ImsReasonInfo;
import android.telephony.ims.ProvisioningManager;
import android.telephony.ims.RegistrationManager;
import android.telephony.ims.feature.ImsFeature;
import android.telephony.ims.feature.MmTelFeature;
+import android.telephony.ims.feature.RcsFeature.RcsImsCapabilities;
import android.telephony.ims.stub.ImsFeatureConfiguration;
import android.telephony.ims.stub.ImsRegistrationImplBase;
import android.util.Base64;
@@ -77,6 +81,10 @@
private static ImsServiceConnector sServiceConnector;
+ private static final int RCS_CAP_NONE = RcsImsCapabilities.CAPABILITY_TYPE_NONE;
+ private static final int RCS_CAP_OPTIONS = RcsImsCapabilities.CAPABILITY_TYPE_OPTIONS_UCE;
+ private static final int RCS_CAP_PRESENCE = RcsImsCapabilities.CAPABILITY_TYPE_PRESENCE_UCE;
+
private static final String MSG_CONTENTS = "hi";
private static final String EXPECTED_RECEIVED_MESSAGE = "foo5";
private static final String DEST_NUMBER = "5555554567";
@@ -899,6 +907,107 @@
}
@Test
+ public void testRcsCapabilityStatusCallback() throws Exception {
+ if (!ImsUtils.shouldTestImsService()) {
+ return;
+ }
+
+ ImsManager imsManager = getContext().getSystemService(ImsManager.class);
+ if (imsManager == null) {
+ fail("Cannot find IMS service");
+ }
+
+ // Connect to device ImsService with RcsFeature
+ triggerFrameworkConnectToDeviceImsServiceBindRcsFeature();
+
+ int registrationTech = ImsRegistrationImplBase.REGISTRATION_TECH_LTE;
+ ImsRcsManager imsRcsManager = imsManager.getImsRcsManager(sTestSub);
+
+ ITestExternalImsService testImsService = sServiceConnector.getExternalService();
+ // Wait for the framework to set the capabilities on the ImsService
+ testImsService.waitForLatchCountdown(TestImsService.LATCH_RCS_CAP_SET);
+ // Make sure we start off with none-capability
+ testImsService.updateImsRegistration(ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
+ testImsService.notifyRcsCapabilitiesStatusChanged(RCS_CAP_NONE);
+
+ // Make sure the capabilities match the API getter for capabilities
+ final UiAutomation automan = InstrumentationRegistry.getInstrumentation().getUiAutomation();
+ // Latch will count down here (we callback on the state during registration).
+ try {
+ automan.adoptShellPermissionIdentity();
+ // Make sure we are tracking voice capability over LTE properly.
+ assertEquals(testImsService.isRcsAvailable(RCS_CAP_PRESENCE),
+ imsRcsManager.isAvailable(RCS_CAP_PRESENCE));
+ } finally {
+ automan.dropShellPermissionIdentity();
+ }
+
+ // Trigger carrier config changed
+ PersistableBundle bundle = new PersistableBundle();
+ bundle.putBoolean(CarrierConfigManager.KEY_USE_RCS_SIP_OPTIONS_BOOL, true);
+ bundle.putBoolean(CarrierConfigManager.KEY_USE_RCS_PRESENCE_BOOL, true);
+ overrideCarrierConfig(bundle);
+
+ // The carrier config changed should trigger RcsFeature#changeEnabledCapabilities
+ try {
+ automan.adoptShellPermissionIdentity();
+ // Checked by isCapable api to make sure RcsFeature#changeEnabledCapabilities is called
+ assertTrue(ImsUtils.retryUntilTrue(() ->
+ imsRcsManager.isCapable(RCS_CAP_OPTIONS, registrationTech)));
+ assertTrue(ImsUtils.retryUntilTrue(() ->
+ imsRcsManager.isCapable(RCS_CAP_PRESENCE, registrationTech)));
+ } finally {
+ automan.dropShellPermissionIdentity();
+ }
+
+ // A queue to receive capability changed
+ LinkedBlockingQueue<RcsImsCapabilities> mQueue = new LinkedBlockingQueue<>();
+ ImsRcsManager.AvailabilityCallback callback = new ImsRcsManager.AvailabilityCallback() {
+ @Override
+ public void onAvailabilityChanged(RcsImsCapabilities capabilities) {
+ mQueue.offer(capabilities);
+ }
+ };
+
+ // Latch will count down here (we callback on the state during registration).
+ try {
+ automan.adoptShellPermissionIdentity();
+ imsRcsManager.registerRcsAvailabilityCallback(getContext().getMainExecutor(), callback);
+ } finally {
+ automan.dropShellPermissionIdentity();
+ }
+
+ // We should not have any availabilities here, we notified the framework earlier.
+ RcsImsCapabilities capCb = waitForResult(mQueue);
+
+ // The SIP OPTIONS capability from onAvailabilityChanged should be disabled.
+ // Moreover, ImsRcsManager#isAvailable also return FALSE with SIP OPTIONS
+ assertTrue(capCb.isCapable(RCS_CAP_NONE));
+ try {
+ automan.adoptShellPermissionIdentity();
+ assertFalse(imsRcsManager.isAvailable(RCS_CAP_OPTIONS));
+ } finally {
+ automan.dropShellPermissionIdentity();
+ }
+
+ // Notify the SIP OPTIONS capability status changed
+ testImsService.notifyRcsCapabilitiesStatusChanged(RCS_CAP_OPTIONS);
+ capCb = waitForResult(mQueue);
+
+ // The SIP OPTIONS capability from onAvailabilityChanged should be enabled.
+ // Verify ImsRcsManager#isAvailable also return true with SIP OPTIONS
+ assertTrue(capCb.isCapable(RCS_CAP_OPTIONS));
+ try {
+ automan.adoptShellPermissionIdentity();
+ assertTrue(imsRcsManager.isAvailable(RCS_CAP_OPTIONS));
+ } finally {
+ automan.dropShellPermissionIdentity();
+ }
+
+ overrideCarrierConfig(null);
+ }
+
+ @Test
public void testProvisioningManagerSetConfig() throws Exception {
if (!ImsUtils.shouldTestImsService()) {
return;
@@ -1037,6 +1146,20 @@
sServiceConnector.getCarrierService().getMmTelFeature());
}
+ private void triggerFrameworkConnectToDeviceImsServiceBindRcsFeature() throws Exception {
+ // Connect to the ImsService with the RCS feature.
+ assertTrue(sServiceConnector.connectDeviceImsService(new ImsFeatureConfiguration.Builder()
+ .addFeature(sTestSlot, ImsFeature.FEATURE_RCS)
+ .build()));
+ // The RcsFeature is created when the ImsService is bound. If it wasn't created, then the
+ // Framework did not call it.
+ sServiceConnector.getExternalService().waitForLatchCountdown(
+ TestImsService.LATCH_CREATE_RCS);
+ // Make sure the RcsFeature was created in the test service.
+ assertTrue("Device ImsService created, but TestDeviceImsService#createRcsFeature was not"
+ + "called!", sServiceConnector.getExternalService().isRcsFeatureCreated());
+ }
+
private void verifyRegistrationState(RegistrationManager regManager, int expectedState)
throws Exception {
LinkedBlockingQueue<Integer> mQueue = new LinkedBlockingQueue<>();
diff --git a/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsUtils.java b/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsUtils.java
index 406d61a..6562d01 100644
--- a/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsUtils.java
+++ b/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsUtils.java
@@ -33,7 +33,6 @@
import java.util.concurrent.Callable;
public class ImsUtils {
- public static final String TAG = "GtsImsServiceTests";
public static final boolean VDBG = false;
// ImsService rebind has an exponential backoff capping at 64 seconds. Wait for 70 seconds to
diff --git a/tests/tests/telephony/current/src/android/telephony/ims/cts/TestImsService.java b/tests/tests/telephony/current/src/android/telephony/ims/cts/TestImsService.java
index c21d8ba..c793d00 100644
--- a/tests/tests/telephony/current/src/android/telephony/ims/cts/TestImsService.java
+++ b/tests/tests/telephony/current/src/android/telephony/ims/cts/TestImsService.java
@@ -58,8 +58,10 @@
public static final int LATCH_REMOVE_MMTEL = 5;
public static final int LATCH_REMOVE_RCS = 6;
public static final int LATCH_MMTEL_READY = 7;
- public static final int LATCH_MMTEL_CAP_SET = 8;
- private static final int LATCH_MAX = 9;
+ public static final int LATCH_RCS_READY = 8;
+ public static final int LATCH_MMTEL_CAP_SET = 9;
+ public static final int LATCH_RCS_CAP_SET = 10;
+ private static final int LATCH_MAX = 11;
protected static final CountDownLatch[] sLatches = new CountDownLatch[LATCH_MAX];
static {
for (int i = 0; i < LATCH_MAX; i++) {
@@ -123,12 +125,27 @@
public RcsFeature createRcsFeature(int slotId) {
synchronized (mLock) {
countDownLatch(LATCH_CREATE_RCS);
- mTestRcsFeature = new TestRcsFeature(() -> {
- synchronized (mLock) {
- countDownLatch(LATCH_REMOVE_RCS);
- mTestRcsFeature = null;
- }
- });
+ mTestRcsFeature = new TestRcsFeature(
+ //onReady
+ () -> {
+ synchronized (mLock) {
+ countDownLatch(LATCH_RCS_READY);
+ }
+ },
+ //onRemoved
+ () -> {
+ synchronized (mLock) {
+ countDownLatch(LATCH_REMOVE_RCS);
+ mTestRcsFeature = null;
+ }
+ },
+ //onCapabilitiesSet
+ () -> {
+ synchronized (mLock) {
+ countDownLatch(LATCH_RCS_CAP_SET);
+ }
+ }
+ );
return mTestRcsFeature;
}
}
diff --git a/tests/tests/telephony/current/src/android/telephony/ims/cts/TestRcsFeature.java b/tests/tests/telephony/current/src/android/telephony/ims/cts/TestRcsFeature.java
index 8781550..9752258 100644
--- a/tests/tests/telephony/current/src/android/telephony/ims/cts/TestRcsFeature.java
+++ b/tests/tests/telephony/current/src/android/telephony/ims/cts/TestRcsFeature.java
@@ -16,18 +16,77 @@
package android.telephony.ims.cts;
+import android.telephony.ims.feature.CapabilityChangeRequest;
import android.telephony.ims.feature.RcsFeature;
+import android.telephony.ims.stub.ImsRegistrationImplBase;
+import android.util.Log;
+
+import java.util.List;
public class TestRcsFeature extends RcsFeature {
+ private static final String TAG = "CtsTestImsService";
+ private final TestImsService.ReadyListener mReadyListener;
private final TestImsService.RemovedListener mRemovedListener;
+ private final TestImsService.CapabilitiesSetListener mCapSetListener;
- TestRcsFeature(TestImsService.RemovedListener listener) {
+ private RcsImsCapabilities mCapabilities =
+ new RcsImsCapabilities(RcsImsCapabilities.CAPABILITY_TYPE_NONE);
+
+ TestRcsFeature(TestImsService.ReadyListener readyListener,
+ TestImsService.RemovedListener listener,
+ TestImsService.CapabilitiesSetListener setListener) {
+ mReadyListener = readyListener;
mRemovedListener = listener;
+ mCapSetListener = setListener;
+
+ setFeatureState(STATE_READY);
+ }
+
+ @Override
+ public void onFeatureReady() {
+ if (ImsUtils.VDBG) {
+ Log.d(TAG, "TestRcsFeature.onFeatureReady called");
+ }
+ mReadyListener.onReady();
}
@Override
public void onFeatureRemoved() {
+ if (ImsUtils.VDBG) {
+ Log.d(TAG, "TestRcsFeature.onFeatureRemoved called");
+ }
mRemovedListener.onRemoved();
}
+
+
+ @Override
+ public boolean queryCapabilityConfiguration(int capability, int radioTech) {
+ if (ImsUtils.VDBG) {
+ Log.d(TAG, "TestRcsFeature.queryCapabilityConfiguration called with capability: "
+ + capability);
+ }
+ return mCapabilities.isCapable(capability);
+ }
+
+ @Override
+ public void changeEnabledCapabilities(CapabilityChangeRequest request,
+ CapabilityCallbackProxy c) {
+ if (ImsUtils.VDBG) {
+ Log.d(TAG, "TestRcsFeature.changeEnabledCapabilities");
+ }
+ List<CapabilityChangeRequest.CapabilityPair> pairs = request.getCapabilitiesToEnable();
+ for (CapabilityChangeRequest.CapabilityPair pair : pairs) {
+ if (pair.getRadioTech() == ImsRegistrationImplBase.REGISTRATION_TECH_LTE) {
+ mCapabilities.addCapabilities(pair.getCapability());
+ }
+ }
+ pairs = request.getCapabilitiesToDisable();
+ for (CapabilityChangeRequest.CapabilityPair pair : pairs) {
+ if (pair.getRadioTech() == ImsRegistrationImplBase.REGISTRATION_TECH_LTE) {
+ mCapabilities.removeCapabilities(pair.getCapability());
+ }
+ }
+ mCapSetListener.onSet();
+ }
}
diff --git a/tests/tests/tethering/Android.bp b/tests/tests/tethering/Android.bp
new file mode 100644
index 0000000..0f98125
--- /dev/null
+++ b/tests/tests/tethering/Android.bp
@@ -0,0 +1,44 @@
+// 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.
+
+android_test {
+ name: "CtsTetheringTest",
+ defaults: ["cts_defaults"],
+
+ libs: [
+ "android.test.base.stubs",
+ ],
+
+ srcs: [
+ "src/**/*.java",
+ ],
+
+ static_libs: [
+ "compatibility-device-util-axt",
+ "ctstestrunner-axt",
+ "junit",
+ "junit-params",
+ ],
+
+ // Change to system current when TetheringManager move to bootclass path.
+ platform_apis: true,
+
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "general-tests",
+ "mts",
+ ],
+
+}
diff --git a/tests/tests/tethering/AndroidManifest.xml b/tests/tests/tethering/AndroidManifest.xml
new file mode 100644
index 0000000..665002e
--- /dev/null
+++ b/tests/tests/tethering/AndroidManifest.xml
@@ -0,0 +1,33 @@
+<?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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.tethering.cts">
+
+ <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+
+ <application android:debuggable="true">
+ <uses-library android:name="android.test.runner" />
+ </application>
+ <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.tethering.cts"
+ android:label="CTS tests of android.tethering">
+ <meta-data android:name="listener"
+ android:value="com.android.cts.runner.CtsTestRunListener" />
+ </instrumentation>
+
+</manifest>
diff --git a/tests/tests/tethering/AndroidTest.xml b/tests/tests/tethering/AndroidTest.xml
new file mode 100644
index 0000000..217d53a
--- /dev/null
+++ b/tests/tests/tethering/AndroidTest.xml
@@ -0,0 +1,29 @@
+<?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="Config for CTS Tethering test cases">
+ <option name="test-suite-tag" value="cts" />
+ <option name="config-descriptor:metadata" key="component" value="networking" />
+ <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
+ <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
+ <option name="not-shardable" value="true" />
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsTetheringTest.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.tethering.cts" />
+ </test>
+</configuration>
diff --git a/tests/tests/tethering/src/android/tethering/cts/TetheringManagerTest.java b/tests/tests/tethering/src/android/tethering/cts/TetheringManagerTest.java
new file mode 100644
index 0000000..9efb8f3
--- /dev/null
+++ b/tests/tests/tethering/src/android/tethering/cts/TetheringManagerTest.java
@@ -0,0 +1,222 @@
+/*
+ * 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 android.tethering.test;
+
+import static org.junit.Assert.fail;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.ConnectivityManager;
+import android.os.ConditionVariable;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+
+@RunWith(AndroidJUnit4.class)
+public class TetheringManagerTest {
+
+ private Context mContext;
+
+ private ConnectivityManager mCM;
+
+ private TetherChangeReceiver mTetherChangeReceiver;
+
+ private String[] mTetheredList;
+
+ private static final int DEFAULT_TIMEOUT_MS = 60_000;
+
+ @Before
+ public void setUp() throws Exception {
+ InstrumentationRegistry.getInstrumentation()
+ .getUiAutomation()
+ .adoptShellPermissionIdentity();
+ mContext = InstrumentationRegistry.getContext();
+ mCM = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
+ mTetherChangeReceiver = new TetherChangeReceiver();
+ final IntentFilter filter = new IntentFilter(
+ ConnectivityManager.ACTION_TETHER_STATE_CHANGED);
+ final Intent intent = mContext.registerReceiver(mTetherChangeReceiver, filter);
+ if (intent != null) mTetherChangeReceiver.onReceive(null, intent);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ mContext.unregisterReceiver(mTetherChangeReceiver);
+ InstrumentationRegistry.getInstrumentation()
+ .getUiAutomation()
+ .dropShellPermissionIdentity();
+ }
+
+ private class TetherChangeReceiver extends BroadcastReceiver {
+ private class TetherState {
+ final ArrayList<String> mAvailable;
+ final ArrayList<String> mActive;
+ final ArrayList<String> mErrored;
+
+ TetherState(Intent intent) {
+ mAvailable = intent.getStringArrayListExtra(
+ ConnectivityManager.EXTRA_AVAILABLE_TETHER);
+ mActive = intent.getStringArrayListExtra(
+ ConnectivityManager.EXTRA_ACTIVE_TETHER);
+ mErrored = intent.getStringArrayListExtra(
+ ConnectivityManager.EXTRA_ERRORED_TETHER);
+ }
+ }
+
+ @Override
+ public void onReceive(Context content, Intent intent) {
+ String action = intent.getAction();
+ if (action.equals(ConnectivityManager.ACTION_TETHER_STATE_CHANGED)) {
+ mResult.add(new TetherState(intent));
+ }
+ }
+
+ public final LinkedBlockingQueue<TetherState> mResult = new LinkedBlockingQueue<>();
+
+ // This method expects either an event where one of the interfaces is active, or an event
+ // where one of the interface is available followed by one where one of the interfaces is
+ // active.
+ public void expectActiveTethering(String[] ifaceRegexs) {
+ TetherState state = pollAndAssertNoError(DEFAULT_TIMEOUT_MS);
+ if (state == null) fail("Do not receive tethering state change broadcast");
+
+ if (isIfaceActive(ifaceRegexs, state)) return;
+
+ if (isIfaceAvailable(ifaceRegexs, state)) {
+ state = pollAndAssertNoError(DEFAULT_TIMEOUT_MS);
+ if (isIfaceActive(ifaceRegexs, state)) return;
+ }
+
+ fail("Tethering is not actived, available ifaces: " + state.mAvailable.toString()
+ + ", active ifaces: " + state.mActive.toString());
+ }
+
+ private TetherState pollAndAssertNoError(final int timeout) {
+ final TetherState state = pollTetherState(timeout);
+ assertNoErroredIfaces(state);
+ return state;
+ }
+
+ private TetherState pollTetherState(final int timeout) {
+ try {
+ return mResult.poll(timeout, TimeUnit.MILLISECONDS);
+ } catch (InterruptedException e) {
+ fail("No result after " + timeout + " ms");
+ return null;
+ }
+ }
+
+ private boolean isIfaceActive(final String[] ifaceRegexs, final TetherState state) {
+ return isIfaceMatch(ifaceRegexs, state.mActive);
+ }
+
+ private boolean isIfaceAvailable(final String[] ifaceRegexs, final TetherState state) {
+ return isIfaceMatch(ifaceRegexs, state.mAvailable);
+ }
+
+ // This method requires a broadcast to have been recorded iff the timeout is non-zero.
+ public void expectNoActiveTethering(final int timeout) {
+ final TetherState state = pollAndAssertNoError(timeout);
+
+ if (state == null) {
+ if (timeout != 0) {
+ fail("Do not receive tethering state change broadcast");
+ }
+ return;
+ }
+
+ assertNoActiveIfaces(state);
+
+ for (final TetherState ts : mResult) {
+ assertNoErroredIfaces(ts);
+
+ assertNoActiveIfaces(ts);
+ }
+ }
+
+ private void assertNoErroredIfaces(final TetherState state) {
+ if (state == null || state.mErrored == null) return;
+
+ if (state.mErrored.size() > 0) {
+ fail("Found failed tethering interfaces: " + state.mErrored.toArray());
+ }
+ }
+
+ private void assertNoActiveIfaces(final TetherState state) {
+ if (state.mActive != null && state.mActive.size() > 0) {
+ fail("Found active tethering interface: " + state.mActive.toArray());
+ }
+ }
+ }
+
+ private class OnStartTetheringCallback extends
+ ConnectivityManager.OnStartTetheringCallback {
+ @Override
+ public void onTetheringStarted() {
+ // Do nothing, TetherChangeReceiver will wait until it receives the broadcast.
+ }
+
+ @Override
+ public void onTetheringFailed() {
+ fail("startTethering fail");
+ }
+ }
+
+ private static boolean isIfaceMatch(final String[] ifaceRegexs,
+ final ArrayList<String> ifaces) {
+ if (ifaceRegexs == null) fail("ifaceRegexs should not be null");
+
+ if (ifaces == null) return false;
+
+ for (String s : ifaces) {
+ for (String regex : ifaceRegexs) {
+ if (s.matches(regex)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ @Test
+ public void testStartTetheringWithStateChangeBroadcast() throws Exception {
+ if (!mCM.isTetheringSupported()) return;
+
+ final String[] wifiRegexs = mCM.getTetherableWifiRegexs();
+ if (wifiRegexs.length == 0) return;
+
+ mTetherChangeReceiver.expectNoActiveTethering(0 /** timeout */);
+
+ final OnStartTetheringCallback startTetheringCallback = new OnStartTetheringCallback();
+ mCM.startTethering(ConnectivityManager.TETHERING_WIFI, true, startTetheringCallback);
+ mTetherChangeReceiver.expectActiveTethering(wifiRegexs);
+
+ mCM.stopTethering(ConnectivityManager.TETHERING_WIFI);
+ mTetherChangeReceiver.expectNoActiveTethering(DEFAULT_TIMEOUT_MS);
+ }
+}
diff --git a/tests/tests/text/TEST_MAPPING b/tests/tests/text/TEST_MAPPING
index cc40b03..05e9696 100644
--- a/tests/tests/text/TEST_MAPPING
+++ b/tests/tests/text/TEST_MAPPING
@@ -2,6 +2,9 @@
"presubmit": [
{
"name": "CtsTextTestCases"
+ },
+ {
+ "name": "minikin_tests"
}
]
-}
\ No newline at end of file
+}
diff --git a/tests/tests/view/TEST_MAPPING b/tests/tests/view/TEST_MAPPING
new file mode 100644
index 0000000..279657d
--- /dev/null
+++ b/tests/tests/view/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "presubmit": [
+ {
+ "name": "minikin_tests"
+ }
+ ]
+}
diff --git a/tests/tests/view/src/android/view/textclassifier/cts/TextClassifierTestWatcher.java b/tests/tests/view/src/android/view/textclassifier/cts/TextClassifierTestWatcher.java
index 660cb24..c921da2 100644
--- a/tests/tests/view/src/android/view/textclassifier/cts/TextClassifierTestWatcher.java
+++ b/tests/tests/view/src/android/view/textclassifier/cts/TextClassifierTestWatcher.java
@@ -144,13 +144,6 @@
if (!TextUtils.isEmpty(deviceConfigSetting) && !deviceConfigSetting.equals("null")) {
return deviceConfigSetting;
}
- // TODO(b/143585708): remove the logic when text_classifier_constants is removed
- final String globalSetting = runShellCommand(
- "settings get global text_classifier_constants");
- if (!TextUtils.isEmpty(globalSetting) && globalSetting.contains(
- "extclassifier_service_package_override")) {
- return globalSetting.substring(globalSetting.indexOf('=') + 1);
- }
return DEFAULT_TEXT_CLASSIFIER_SERVICE_PACKAGE_OVERRIDE;
}
@@ -160,14 +153,6 @@
if (!TextUtils.isEmpty(deviceConfigSetting) && !deviceConfigSetting.equals("null")) {
return deviceConfigSetting.toLowerCase().equals("true");
}
- // TODO(b/143585708): remove the logic when text_classifier_constants is removed
- final String globalSetting = runShellCommand(
- "settings get global text_classifier_constants");
- if (!TextUtils.isEmpty(globalSetting) && globalSetting.contains(
- "system_textclassifier_enabled")) {
- return globalSetting.substring(globalSetting.indexOf('=') + 1).toLowerCase().equals(
- "true");
- }
return SYSTEM_TEXT_CLASSIFIER_ENABLED_DEFAULT;
}
diff --git a/tests/tests/webkit/src/android/webkit/cts/WebViewClientTest.java b/tests/tests/webkit/src/android/webkit/cts/WebViewClientTest.java
index 8c3b252..9b26397 100644
--- a/tests/tests/webkit/src/android/webkit/cts/WebViewClientTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/WebViewClientTest.java
@@ -634,7 +634,8 @@
* Modifications to this test should be reflected in that test as necessary. See
* http://go/modifying-webview-cts.
*/
- public void testOnSafeBrowsingHitBackToSafety() throws Throwable {
+ // TODO(ntfschr): re-enable when https://crbug.com/1006953 is fixed and dropped into Android.
+ public void disabled_testOnSafeBrowsingHitBackToSafety() throws Throwable {
if (!NullWebViewUtils.isWebViewAvailable()) {
return;
}
@@ -674,7 +675,8 @@
* Modifications to this test should be reflected in that test as necessary. See
* http://go/modifying-webview-cts.
*/
- public void testOnSafeBrowsingHitProceed() throws Throwable {
+ // TODO(ntfschr): re-enable when https://crbug.com/1006953 is fixed and dropped into Android.
+ public void disabled_testOnSafeBrowsingHitProceed() throws Throwable {
if (!NullWebViewUtils.isWebViewAvailable()) {
return;
}
@@ -735,22 +737,26 @@
}
}
- public void testOnSafeBrowsingMalwareCode() throws Throwable {
+ // TODO(ntfschr): re-enable when https://crbug.com/1006953 is fixed and dropped into Android.
+ public void disabled_testOnSafeBrowsingMalwareCode() throws Throwable {
testOnSafeBrowsingCode(TEST_SAFE_BROWSING_MALWARE_URL,
WebViewClient.SAFE_BROWSING_THREAT_MALWARE);
}
- public void testOnSafeBrowsingPhishingCode() throws Throwable {
+ // TODO(ntfschr): re-enable when https://crbug.com/1006953 is fixed and dropped into Android.
+ public void disabled_testOnSafeBrowsingPhishingCode() throws Throwable {
testOnSafeBrowsingCode(TEST_SAFE_BROWSING_PHISHING_URL,
WebViewClient.SAFE_BROWSING_THREAT_PHISHING);
}
- public void testOnSafeBrowsingUnwantedSoftwareCode() throws Throwable {
+ // TODO(ntfschr): re-enable when https://crbug.com/1006953 is fixed and dropped into Android.
+ public void disabled_testOnSafeBrowsingUnwantedSoftwareCode() throws Throwable {
testOnSafeBrowsingCode(TEST_SAFE_BROWSING_UNWANTED_SOFTWARE_URL,
WebViewClient.SAFE_BROWSING_THREAT_UNWANTED_SOFTWARE);
}
- public void testOnSafeBrowsingBillingCode() throws Throwable {
+ // TODO(ntfschr): re-enable when https://crbug.com/1006953 is fixed and dropped into Android.
+ public void disabled_testOnSafeBrowsingBillingCode() throws Throwable {
testOnSafeBrowsingCode(TEST_SAFE_BROWSING_BILLING_URL,
WebViewClient.SAFE_BROWSING_THREAT_BILLING);
}
diff --git a/tests/tests/widget/src/android/widget/cts/RadioGroupTest.java b/tests/tests/widget/src/android/widget/cts/RadioGroupTest.java
index 74852c5..a8b3c8f 100644
--- a/tests/tests/widget/src/android/widget/cts/RadioGroupTest.java
+++ b/tests/tests/widget/src/android/widget/cts/RadioGroupTest.java
@@ -31,6 +31,7 @@
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.OnHierarchyChangeListener;
+import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.LinearLayout;
import android.widget.RadioButton;
import android.widget.RadioGroup;
@@ -412,6 +413,31 @@
assertEquals(5, mRadioGroup.getChildCount());
}
+ @UiThreadTest
+ @Test
+ public void testOnInitializeAccessibilityNodeInfo_populatesCollectionInfo() {
+ AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain();
+ mRadioGroup.onInitializeAccessibilityNodeInfo(info);
+
+ AccessibilityNodeInfo.CollectionInfo colInfo = info.getCollectionInfo();
+ assertNotNull(colInfo);
+ assertEquals(colInfo.getRowCount(), mRadioGroup.getChildCount());
+ }
+
+ @UiThreadTest
+ @Test
+ public void testOnInitializeAccessibilityNodeInfo_populatesCollectionItemInfo() {
+ RadioButton child = (RadioButton) mRadioGroup.getChildAt(1);
+ child.setChecked(true);
+
+ AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain();
+ child.onInitializeAccessibilityNodeInfo(info);
+
+ AccessibilityNodeInfo.CollectionItemInfo colItemInfo = info.getCollectionItemInfo();
+ assertEquals(colItemInfo.getRowIndex(), 1);
+ assertEquals(colItemInfo.isSelected(), true);
+ }
+
private AttributeSet getAttributeSet(int resId) {
XmlPullParser parser = mActivity.getResources().getLayout(resId);
assertNotNull(parser);
diff --git a/tools/cts-device-info/src/com/android/cts/deviceinfo/CameraDeviceInfo.java b/tools/cts-device-info/src/com/android/cts/deviceinfo/CameraDeviceInfo.java
index 96675c3..1ca3cfa 100644
--- a/tools/cts-device-info/src/com/android/cts/deviceinfo/CameraDeviceInfo.java
+++ b/tools/cts-device-info/src/com/android/cts/deviceinfo/CameraDeviceInfo.java
@@ -464,6 +464,7 @@
charsKeyNames.add(CameraCharacteristics.CONTROL_AVAILABLE_MODES.getName());
charsKeyNames.add(CameraCharacteristics.CONTROL_POST_RAW_SENSITIVITY_BOOST_RANGE.getName());
charsKeyNames.add(CameraCharacteristics.CONTROL_AVAILABLE_BOKEH_CAPABILITIES.getName());
+ charsKeyNames.add(CameraCharacteristics.CONTROL_ZOOM_RATIO_RANGE.getName());
charsKeyNames.add(CameraCharacteristics.EDGE_AVAILABLE_EDGE_MODES.getName());
charsKeyNames.add(CameraCharacteristics.FLASH_INFO_AVAILABLE.getName());
charsKeyNames.add(CameraCharacteristics.HOT_PIXEL_AVAILABLE_HOT_PIXEL_MODES.getName());