Merge changes I800833ab,I75f82e2d,Id5fb4325,I40a765be,I2057a0ef, ... into rvc-dev
* changes:
Remove resultCode test from CredentialEnrolledTests
Add tests for BiometricPrompt negative button
Add MAC tests
Add signature tests
Add Biometric, Biometric|Credential Cipher tests
Add CtsVerifier tests for setUserAuthenticationParameters
diff --git a/apps/CameraITS/tests/scene2_a/test_jpeg_quality.py b/apps/CameraITS/tests/scene2_a/test_jpeg_quality.py
new file mode 100644
index 0000000..b52fb1e
--- /dev/null
+++ b/apps/CameraITS/tests/scene2_a/test_jpeg_quality.py
@@ -0,0 +1,256 @@
+# Copyright 2020 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.
+
+import math
+import os.path
+
+import its.caps
+import its.device
+import its.image
+import its.objects
+
+from matplotlib import pylab
+import matplotlib.pyplot
+import numpy as np
+
+JPEG_APPN_MARKERS = [[255, 224], [255, 225], [255, 226], [255, 227], [255, 228],
+ [255, 235]]
+JPEG_DHT_MARKER = [255, 196] # JPEG Define Huffman Table
+JPEG_DQT_MARKER = [255, 219] # JPEG Define Quantization Table
+JPEG_DQT_TOL = 0.8 # -20% for each +20 in jpeg.quality (empirical number)
+JPEG_EOI_MARKER = [255, 217] # JPEG End of Image
+JPEG_SOI_MARKER = [255, 216] # JPEG Start of Image
+JPEG_SOS_MARKER = [255, 218] # JPEG Start of Scan
+NAME = os.path.basename(__file__).split('.')[0]
+QUALITIES = [25, 45, 65, 85]
+SYMBOLS = ['o', 's', 'v', '^', '<', '>']
+
+
+def is_square(integer):
+ root = math.sqrt(integer)
+ return integer == int(root + 0.5) ** 2
+
+
+def strip_soi_marker(jpeg):
+ """strip off start of image marker.
+
+ SOI is of form [xFF xD8] and JPEG needs to start with marker.
+
+ Args:
+ jpeg: 1-D numpy int [0:255] array; values from JPEG capture
+
+ Returns:
+ jpeg with SOI marker stripped off.
+ """
+
+ soi = jpeg[0:2]
+ assert list(soi) == JPEG_SOI_MARKER, 'JPEG has no Start Of Image marker'
+ return jpeg[2:]
+
+
+def strip_appn_data(jpeg):
+ """strip off application specific data at beginning of JPEG.
+
+ APPN markers are of form [xFF, xE*, size_msb, size_lsb] and should follow
+ SOI marker.
+
+ Args:
+ jpeg: 1-D numpy int [0:255] array; values from JPEG capture
+
+ Returns:
+ jpeg with APPN marker(s) and data stripped off.
+ """
+
+ length = 0
+ i = 0
+ # find APPN markers and strip off payloads at beginning of jpeg
+ while i < len(jpeg)-1:
+ if [jpeg[i], jpeg[i+1]] in JPEG_APPN_MARKERS:
+ length = jpeg[i+2] * 256 + jpeg[i+3] + 2
+ print ' stripped APPN length:', length
+ jpeg = np.concatenate((jpeg[0:i], jpeg[length:]), axis=None)
+ elif ([jpeg[i], jpeg[i+1]] == JPEG_DQT_MARKER or
+ [jpeg[i], jpeg[i+1]] == JPEG_DHT_MARKER):
+ break
+ else:
+ i += 1
+
+ return jpeg
+
+
+def find_dqt_markers(marker, jpeg):
+ """Find location(s) of marker list in jpeg.
+
+ DQT marker is of form [xFF, xDB].
+
+ Args:
+ marker: list; marker values
+ jpeg: 1-D numpy int [0:255] array; JPEG capture w/ SOI & APPN stripped
+
+ Returns:
+ locs: list; marker locations in jpeg
+ """
+ locs = []
+ marker_len = len(marker)
+ for i in xrange(len(jpeg)-marker_len+1):
+ if list(jpeg[i:i+marker_len]) == marker:
+ locs.append(i)
+ return locs
+
+
+def extract_dqts(jpeg, debug=False):
+ """Find and extract the DQT info in the JPEG.
+
+ SOI marker and APPN markers plus data are stripped off front of JPEG.
+ DQT marker is of form [xFF, xDB] followed by [size_msb, size_lsb].
+ Size includes the size values, but not the marker values.
+ Luma DQT is prefixed by 0, Chroma DQT by 1.
+ DQTs can have both luma & chroma or each individually.
+ There can be more than one DQT table for luma and chroma.
+
+ Args:
+ jpeg: 1-D numpy int [0:255] array; values from JPEG capture
+ debug: bool; command line flag to print debug data
+
+ Returns:
+ lumas, chromas: lists of numpy means of luma & chroma DQT matrices.
+ Higher values represent higher compression.
+ """
+
+ dqt_markers = find_dqt_markers(JPEG_DQT_MARKER, jpeg)
+ print 'DQT header loc(s):', dqt_markers
+ lumas = []
+ chromas = []
+ for i, dqt in enumerate(dqt_markers):
+ if debug:
+ print '\n DQT %d start: %d, marker: %s, length: %s' % (
+ i, dqt, jpeg[dqt:dqt+2], jpeg[dqt+2:dqt+4])
+ dqt_size = jpeg[dqt+2]*256 + jpeg[dqt+3] - 2 # strip off size marker
+ if dqt_size % 2 == 0: # even payload means luma & chroma
+ print ' both luma & chroma DQT matrices in marker'
+ dqt_size = (dqt_size - 2) / 2 # subtact off luma/chroma markers
+ assert is_square(dqt_size), 'DQT size: %d' % dqt_size
+ luma_start = dqt + 5 # skip header, length, & matrix id
+ chroma_start = luma_start + dqt_size + 1 # skip lumen & matrix_id
+ luma = np.array(jpeg[luma_start:luma_start+dqt_size])
+ chroma = np.array(jpeg[chroma_start:chroma_start+dqt_size])
+ lumas.append(np.mean(luma))
+ chromas.append(np.mean(chroma))
+ if debug:
+ h = int(math.sqrt(dqt_size))
+ print ' luma:', luma.reshape(h, h)
+ print ' chroma:', chroma.reshape(h, h)
+ else: # odd payload means only 1 matrix
+ print ' single DQT matrix in marker'
+ dqt_size = dqt_size - 1 # subtract off luma/chroma marker
+ assert is_square(dqt_size), 'DQT size: %d' % dqt_size
+ start = dqt + 5
+ matrix = np.array(jpeg[start:start+dqt_size])
+ if jpeg[dqt+4]: # chroma == 1
+ chromas.append(np.mean(matrix))
+ if debug:
+ h = int(math.sqrt(dqt_size))
+ print ' chroma:', matrix.reshape(h, h)
+ else: # luma == 0
+ lumas.append(np.mean(matrix))
+ if debug:
+ h = int(math.sqrt(dqt_size))
+ print ' luma:', matrix.reshape(h, h)
+
+ return lumas, chromas
+
+
+def plot_data(qualities, lumas, chromas):
+ """Create plot of data."""
+ print 'qualities: %s' % str(qualities)
+ print 'luma DQT avgs: %s' % str(lumas)
+ print 'chroma DQT avgs: %s' % str(chromas)
+ pylab.title(NAME)
+ for i in range(lumas.shape[1]):
+ pylab.plot(qualities, lumas[:, i], '-g'+SYMBOLS[i],
+ label='luma_dqt'+str(i))
+ pylab.plot(qualities, chromas[:, i], '-r'+SYMBOLS[i],
+ label='chroma_dqt'+str(i))
+ pylab.xlim([0, 100])
+ pylab.ylim([0, None])
+ pylab.xlabel('jpeg.quality')
+ pylab.ylabel('DQT luma/chroma matrix averages')
+ pylab.legend(loc='upper right', numpoints=1, fancybox=True)
+ matplotlib.pyplot.savefig('%s_plot.png' % NAME)
+
+
+def main():
+ """Test the camera JPEG compression quality.
+
+ Step JPEG qualities through android.jpeg.quality. Ensure quanitization
+ matrix decreases with quality increase. Matrix should decrease as the
+ matrix represents the division factor. Higher numbers --> fewer quantization
+ levels.
+ """
+
+ # determine debug
+ debug = its.caps.debug_mode()
+
+ # init variables
+ lumas = []
+ chromas = []
+
+ with its.device.ItsSession() as cam:
+ props = cam.get_camera_properties()
+ cam.do_3a()
+
+ # do captures over jpeg quality range
+ req = its.objects.auto_capture_request()
+ for q in QUALITIES:
+ print '\njpeg.quality: %.d' % q
+ req['android.jpeg.quality'] = q
+ cap = cam.do_capture(req, cam.CAP_JPEG)
+ jpeg = cap['data']
+
+ # strip off start of image
+ jpeg = strip_soi_marker(jpeg)
+
+ # strip off application specific data
+ jpeg = strip_appn_data(jpeg)
+ print 'remaining JPEG header:', jpeg[0:4]
+
+ # find and extract DQTs
+ lumas_i, chromas_i = extract_dqts(jpeg, debug)
+ lumas.append(lumas_i)
+ chromas.append(chromas_i)
+
+ # save JPEG image
+ img = its.image.convert_capture_to_rgb_image(cap, props=props)
+ its.image.write_image(img, '%s_%d.jpg' % (NAME, q))
+
+ # turn lumas/chromas into np array to ease multi-dimensional plots/asserts
+ lumas = np.array(lumas)
+ chromas = np.array(chromas)
+
+ # create plot of luma & chroma averages vs quality
+ plot_data(QUALITIES, lumas, chromas)
+
+ # assert decreasing luma/chroma with improved jpeg quality
+ for i in range(lumas.shape[1]):
+ l = lumas[:, i]
+ c = chromas[:, i]
+ emsg = 'luma DQT avgs: %s, TOL: %.1f' % (str(l), JPEG_DQT_TOL)
+ assert all(y < x * JPEG_DQT_TOL for x, y in zip(l, l[1:])), emsg
+ emsg = 'chroma DQT avgs: %s, TOL: %.1f' % (str(c), JPEG_DQT_TOL)
+ assert all(y < x * JPEG_DQT_TOL for x, y in zip(c, c[1:])), emsg
+
+
+if __name__ == '__main__':
+ main()
diff --git a/apps/CameraITS/tools/run_all_tests.py b/apps/CameraITS/tools/run_all_tests.py
index 021a324..e47795e 100644
--- a/apps/CameraITS/tools/run_all_tests.py
+++ b/apps/CameraITS/tools/run_all_tests.py
@@ -104,7 +104,9 @@
['test_channel_saturation', 29]
],
'scene1_2': [],
- 'scene2_a': [],
+ 'scene2_a': [
+ ['test_jpeg_quality', 30]
+ ],
'scene2_b': [
['test_auto_per_frame_control', NOT_YET_MANDATED_ALL]
],
diff --git a/apps/CtsVerifier/jni/audio_loopback/Android.bp b/apps/CtsVerifier/jni/audio_loopback/Android.bp
index 9227c75..29b7e13 100644
--- a/apps/CtsVerifier/jni/audio_loopback/Android.bp
+++ b/apps/CtsVerifier/jni/audio_loopback/Android.bp
@@ -1,21 +1,22 @@
cc_test_library {
name: "libaudioloopback_jni",
srcs: [
- "sles.cpp",
- "jni_sles.c",
- "audio_utils/atomic.c",
- "audio_utils/fifo.c",
- "audio_utils/roundup.c",
+ "jni-bridge.cpp",
+ "NativeAudioAnalyzer.cpp",
+ ],
+ include_dirs: [
+ "frameworks/av/media/ndk/include",
+ "system/core/include/cutils",
],
shared_libs: [
- "libOpenSLES",
+ "libaaudio",
"liblog",
],
+ stl: "libc++_static",
ldflags: ["-Wl,--hash-style=sysv"],
cflags: [
- "-DSTDC_HEADERS",
"-Werror",
"-Wall",
],
- sdk_version: "23",
+ sdk_version: "current",
}
diff --git a/apps/CtsVerifier/jni/audio_loopback/NativeAudioAnalyzer.cpp b/apps/CtsVerifier/jni/audio_loopback/NativeAudioAnalyzer.cpp
new file mode 100644
index 0000000..d8d6946
--- /dev/null
+++ b/apps/CtsVerifier/jni/audio_loopback/NativeAudioAnalyzer.cpp
@@ -0,0 +1,322 @@
+/*
+ * Copyright 2020 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.
+ */
+
+#include "NativeAudioAnalyzer.h"
+
+static void convertPcm16ToFloat(const int16_t *source,
+ float *destination,
+ int32_t numSamples) {
+ constexpr float scaler = 1.0f / 32768.0f;
+ for (int i = 0; i < numSamples; i++) {
+ destination[i] = source[i] * scaler;
+ }
+}
+
+// Fill the audio output buffer.
+int32_t NativeAudioAnalyzer::readFormattedData(int32_t numFrames) {
+ int32_t framesRead = AAUDIO_ERROR_INVALID_FORMAT;
+ if (mActualInputFormat == AAUDIO_FORMAT_PCM_I16) {
+ framesRead = AAudioStream_read(mInputStream, mInputShortData,
+ numFrames,
+ 0 /* timeoutNanoseconds */);
+ } else if (mActualInputFormat == AAUDIO_FORMAT_PCM_FLOAT) {
+ framesRead = AAudioStream_read(mInputStream, mInputFloatData,
+ numFrames,
+ 0 /* timeoutNanoseconds */);
+ } else {
+ ALOGE("ERROR actualInputFormat = %d\n", mActualInputFormat);
+ assert(false);
+ }
+ if (framesRead < 0) {
+ // Expect INVALID_STATE if STATE_STARTING
+ if (mFramesReadTotal > 0) {
+ mInputError = framesRead;
+ ALOGE("ERROR in read = %d = %s\n", framesRead,
+ AAudio_convertResultToText(framesRead));
+ } else {
+ framesRead = 0;
+ }
+ } else {
+ mFramesReadTotal += framesRead;
+ }
+ return framesRead;
+}
+
+aaudio_data_callback_result_t NativeAudioAnalyzer::dataCallbackProc(
+ void *audioData,
+ int32_t numFrames
+) {
+ aaudio_data_callback_result_t callbackResult = AAUDIO_CALLBACK_RESULT_CONTINUE;
+ float *outputData = (float *) audioData;
+
+ // Read audio data from the input stream.
+ int32_t actualFramesRead;
+
+ if (numFrames > mInputFramesMaximum) {
+ ALOGE("%s() numFrames:%d > mInputFramesMaximum:%d", __func__, numFrames, mInputFramesMaximum);
+ mInputError = AAUDIO_ERROR_OUT_OF_RANGE;
+ return AAUDIO_CALLBACK_RESULT_STOP;
+ }
+
+ if (numFrames > mMaxNumFrames) {
+ mMaxNumFrames = numFrames;
+ }
+ if (numFrames < mMinNumFrames) {
+ mMinNumFrames = numFrames;
+ }
+
+ // Silence the output.
+ int32_t numBytes = numFrames * mActualOutputChannelCount * sizeof(float);
+ memset(audioData, 0 /* value */, numBytes);
+
+ if (mNumCallbacksToDrain > 0) {
+ // Drain the input FIFOs.
+ int32_t totalFramesRead = 0;
+ do {
+ actualFramesRead = readFormattedData(numFrames);
+ if (actualFramesRead > 0) {
+ totalFramesRead += actualFramesRead;
+ } else if (actualFramesRead < 0) {
+ callbackResult = AAUDIO_CALLBACK_RESULT_STOP;
+ }
+ // Ignore errors because input stream may not be started yet.
+ } while (actualFramesRead > 0);
+ // Only counts if we actually got some data.
+ if (totalFramesRead > 0) {
+ mNumCallbacksToDrain--;
+ }
+
+ } else if (mNumCallbacksToNotRead > 0) {
+ // Let the input fill up a bit so we are not so close to the write pointer.
+ mNumCallbacksToNotRead--;
+ } else if (mNumCallbacksToDiscard > 0) {
+ // Ignore. Allow the input to fill back up to equilibrium with the output.
+ actualFramesRead = readFormattedData(numFrames);
+ if (actualFramesRead < 0) {
+ callbackResult = AAUDIO_CALLBACK_RESULT_STOP;
+ }
+ mNumCallbacksToDiscard--;
+
+ } else {
+ // The full duplex stream is now stable so process the audio.
+ int32_t numInputBytes = numFrames * mActualInputChannelCount * sizeof(float);
+ memset(mInputFloatData, 0 /* value */, numInputBytes);
+
+ int64_t inputFramesWritten = AAudioStream_getFramesWritten(mInputStream);
+ int64_t inputFramesRead = AAudioStream_getFramesRead(mInputStream);
+ int64_t framesAvailable = inputFramesWritten - inputFramesRead;
+
+ // Read the INPUT data.
+ actualFramesRead = readFormattedData(numFrames); // READ
+ if (actualFramesRead < 0) {
+ callbackResult = AAUDIO_CALLBACK_RESULT_STOP;
+ } else {
+ if (actualFramesRead < numFrames) {
+ if(actualFramesRead < (int32_t) framesAvailable) {
+ ALOGE("insufficient for no reason, numFrames = %d"
+ ", actualFramesRead = %d"
+ ", inputFramesWritten = %d"
+ ", inputFramesRead = %d"
+ ", available = %d\n",
+ numFrames,
+ actualFramesRead,
+ (int) inputFramesWritten,
+ (int) inputFramesRead,
+ (int) framesAvailable);
+ }
+ mInsufficientReadCount++;
+ mInsufficientReadFrames += numFrames - actualFramesRead; // deficit
+ // ALOGE("Error insufficientReadCount = %d\n",(int)mInsufficientReadCount);
+ }
+
+ int32_t numSamples = actualFramesRead * mActualInputChannelCount;
+
+ if (mActualInputFormat == AAUDIO_FORMAT_PCM_I16) {
+ convertPcm16ToFloat(mInputShortData, mInputFloatData, numSamples);
+ }
+
+ // Process the INPUT and generate the OUTPUT.
+ mLoopbackProcessor->process(mInputFloatData,
+ mActualInputChannelCount,
+ numFrames,
+ outputData,
+ mActualOutputChannelCount,
+ numFrames);
+
+ mIsDone = mLoopbackProcessor->isDone();
+ if (mIsDone) {
+ callbackResult = AAUDIO_CALLBACK_RESULT_STOP;
+ }
+ }
+ }
+ mFramesWrittenTotal += numFrames;
+
+ return callbackResult;
+}
+
+static aaudio_data_callback_result_t s_MyDataCallbackProc(
+ AAudioStream * /* outputStream */,
+ void *userData,
+ void *audioData,
+ int32_t numFrames) {
+ NativeAudioAnalyzer *myData = (NativeAudioAnalyzer *) userData;
+ return myData->dataCallbackProc(audioData, numFrames);
+}
+
+static void s_MyErrorCallbackProc(
+ AAudioStream * /* stream */,
+ void * userData,
+ aaudio_result_t error) {
+ ALOGE("Error Callback, error: %d\n",(int)error);
+ NativeAudioAnalyzer *myData = (NativeAudioAnalyzer *) userData;
+ myData->mOutputError = error;
+}
+
+bool NativeAudioAnalyzer::isRecordingComplete() {
+ return mPulseLatencyAnalyzer.isRecordingComplete();
+}
+
+int NativeAudioAnalyzer::analyze() {
+ mPulseLatencyAnalyzer.analyze();
+ return getError(); // TODO review
+}
+
+double NativeAudioAnalyzer::getLatencyMillis() {
+ return mPulseLatencyAnalyzer.getMeasuredLatency() * 1000.0 / 48000;
+}
+
+double NativeAudioAnalyzer::getConfidence() {
+ return mPulseLatencyAnalyzer.getMeasuredConfidence();
+}
+
+aaudio_result_t NativeAudioAnalyzer::openAudio() {
+ AAudioStreamBuilder *builder = nullptr;
+
+ mLoopbackProcessor = &mPulseLatencyAnalyzer; // for latency test
+
+ // Use an AAudioStreamBuilder to contain requested parameters.
+ aaudio_result_t result = AAudio_createStreamBuilder(&builder);
+ if (result != AAUDIO_OK) {
+ ALOGE("AAudio_createStreamBuilder() returned %s",
+ AAudio_convertResultToText(result));
+ return result;
+ }
+
+ // Create the OUTPUT stream -----------------------
+ AAudioStreamBuilder_setDirection(builder, AAUDIO_DIRECTION_OUTPUT);
+ AAudioStreamBuilder_setPerformanceMode(builder, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);
+ AAudioStreamBuilder_setSharingMode(builder, AAUDIO_SHARING_MODE_EXCLUSIVE);
+ AAudioStreamBuilder_setFormat(builder, AAUDIO_FORMAT_PCM_FLOAT);
+ AAudioStreamBuilder_setChannelCount(builder, 2); // stereo
+ AAudioStreamBuilder_setDataCallback(builder, s_MyDataCallbackProc, this);
+ AAudioStreamBuilder_setErrorCallback(builder, s_MyErrorCallbackProc, this);
+
+ result = AAudioStreamBuilder_openStream(builder, &mOutputStream);
+ if (result != AAUDIO_OK) {
+ ALOGE("NativeAudioAnalyzer::openAudio() OUTPUT error %s",
+ AAudio_convertResultToText(result));
+ return result;
+ }
+
+ int32_t outputFramesPerBurst = AAudioStream_getFramesPerBurst(mOutputStream);
+ (void) AAudioStream_setBufferSizeInFrames(mOutputStream, outputFramesPerBurst * kDefaultOutputSizeBursts);
+
+ int32_t outputSampleRate = AAudioStream_getSampleRate(mOutputStream);
+ mActualOutputChannelCount = AAudioStream_getChannelCount(mOutputStream);
+
+ // Create the INPUT stream -----------------------
+ AAudioStreamBuilder_setDirection(builder, AAUDIO_DIRECTION_INPUT);
+ AAudioStreamBuilder_setFormat(builder, AAUDIO_FORMAT_UNSPECIFIED);
+ AAudioStreamBuilder_setSampleRate(builder, outputSampleRate); // must match
+ AAudioStreamBuilder_setChannelCount(builder, 1); // mono
+ AAudioStreamBuilder_setDataCallback(builder, nullptr, nullptr);
+ AAudioStreamBuilder_setErrorCallback(builder, nullptr, nullptr);
+ result = AAudioStreamBuilder_openStream(builder, &mInputStream);
+ if (result != AAUDIO_OK) {
+ ALOGE("NativeAudioAnalyzer::openAudio() INPUT error %s",
+ AAudio_convertResultToText(result));
+ return result;
+ }
+
+ int32_t actualCapacity = AAudioStream_getBufferCapacityInFrames(mInputStream);
+ (void) AAudioStream_setBufferSizeInFrames(mInputStream, actualCapacity);
+
+ // ------- Setup loopbackData -----------------------------
+ mActualInputFormat = AAudioStream_getFormat(mInputStream);
+ mActualInputChannelCount = AAudioStream_getChannelCount(mInputStream);
+
+ // Allocate a buffer for the audio data.
+ mInputFramesMaximum = 32 * AAudioStream_getFramesPerBurst(mInputStream);
+
+ if (mActualInputFormat == AAUDIO_FORMAT_PCM_I16) {
+ mInputShortData = new int16_t[mInputFramesMaximum * mActualInputChannelCount]{};
+ }
+ mInputFloatData = new float[mInputFramesMaximum * mActualInputChannelCount]{};
+
+ return result;
+}
+
+aaudio_result_t NativeAudioAnalyzer::startAudio() {
+ mLoopbackProcessor->prepareToTest();
+
+ // Start OUTPUT first so INPUT does not overflow.
+ aaudio_result_t result = AAudioStream_requestStart(mOutputStream);
+ if (result != AAUDIO_OK) {
+ stopAudio();
+ return result;
+ }
+
+ result = AAudioStream_requestStart(mInputStream);
+ if (result != AAUDIO_OK) {
+ stopAudio();
+ return result;
+ }
+
+ return result;
+}
+
+aaudio_result_t NativeAudioAnalyzer::stopAudio() {
+ aaudio_result_t result1 = AAUDIO_OK;
+ aaudio_result_t result2 = AAUDIO_OK;
+ ALOGD("stopAudio() , minNumFrames = %d, maxNumFrames = %d\n", mMinNumFrames, mMaxNumFrames);
+ // Stop OUTPUT first because it uses INPUT.
+ if (mOutputStream != nullptr) {
+ result1 = AAudioStream_requestStop(mOutputStream);
+ }
+
+ // Stop INPUT.
+ if (mInputStream != nullptr) {
+ result2 = AAudioStream_requestStop(mInputStream);
+ }
+ return result1 != AAUDIO_OK ? result1 : result2;
+}
+
+aaudio_result_t NativeAudioAnalyzer::closeAudio() {
+ aaudio_result_t result1 = AAUDIO_OK;
+ aaudio_result_t result2 = AAUDIO_OK;
+ // Stop and close OUTPUT first because it uses INPUT.
+ if (mOutputStream != nullptr) {
+ result1 = AAudioStream_close(mOutputStream);
+ mOutputStream = nullptr;
+ }
+
+ // Stop and close INPUT.
+ if (mInputStream != nullptr) {
+ result2 = AAudioStream_close(mInputStream);
+ mInputStream = nullptr;
+ }
+ return result1 != AAUDIO_OK ? result1 : result2;
+}
diff --git a/apps/CtsVerifier/jni/audio_loopback/NativeAudioAnalyzer.h b/apps/CtsVerifier/jni/audio_loopback/NativeAudioAnalyzer.h
new file mode 100644
index 0000000..0d9c64b
--- /dev/null
+++ b/apps/CtsVerifier/jni/audio_loopback/NativeAudioAnalyzer.h
@@ -0,0 +1,139 @@
+/*
+ * Copyright 2020 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.
+ */
+
+#ifndef CTS_NATIVE_AUDIO_ANALYZER_H
+#define CTS_NATIVE_AUDIO_ANALYZER_H
+
+#define LOG_TAG "NativeAudioAnalyzer"
+#include <android/log.h>
+
+#ifndef MODULE_NAME
+#define MODULE_NAME "NativeAudioAnalyzer"
+#endif
+
+#define ALOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, MODULE_NAME, __VA_ARGS__)
+#define ALOGD(...) __android_log_print(ANDROID_LOG_DEBUG, MODULE_NAME, __VA_ARGS__)
+#define ALOGI(...) __android_log_print(ANDROID_LOG_INFO, MODULE_NAME, __VA_ARGS__)
+#define ALOGW(...) __android_log_print(ANDROID_LOG_WARN, MODULE_NAME, __VA_ARGS__)
+#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, MODULE_NAME, __VA_ARGS__)
+#define ALOGF(...) __android_log_print(ANDROID_LOG_FATAL, MODULE_NAME, __VA_ARGS__)
+
+#include <aaudio/AAudio.h>
+
+#include "analyzer/GlitchAnalyzer.h"
+#include "analyzer/LatencyAnalyzer.h"
+
+class NativeAudioAnalyzer {
+public:
+
+ /**
+ * Open the audio input and output streams.
+ * @return AAUDIO_OK or negative error
+ */
+ aaudio_result_t openAudio();
+
+ /**
+ * Start the audio input and output streams.
+ * @return AAUDIO_OK or negative error
+ */
+ aaudio_result_t startAudio();
+
+ /**
+ * Stop the audio input and output streams.
+ * @return AAUDIO_OK or negative error
+ */
+ aaudio_result_t stopAudio();
+
+ /**
+ * Close the audio input and output streams.
+ * @return AAUDIO_OK or negative error
+ */
+ aaudio_result_t closeAudio();
+
+ /**
+ * @return true if enough audio input has been recorded
+ */
+ bool isRecordingComplete();
+
+ /**
+ * Analyze the input and measure the latency between output and input.
+ * @return AAUDIO_OK or negative error
+ */
+ int analyze();
+
+ /**
+ * @return the measured latency in milliseconds
+ */
+ double getLatencyMillis();
+
+ /**
+ * The confidence is based on a normalized correlation.
+ * It ranges from 0.0 to 1.0. Higher is better.
+ *
+ * @return the confidence in the latency result
+ */
+ double getConfidence();
+
+ aaudio_result_t getError() {
+ return mInputError ? mInputError : mOutputError;
+ }
+
+ AAudioStream *mInputStream = nullptr;
+ AAudioStream *mOutputStream = nullptr;
+ aaudio_format_t mActualInputFormat = AAUDIO_FORMAT_INVALID;
+ int16_t *mInputShortData = nullptr;
+ float *mInputFloatData = nullptr;
+
+ aaudio_result_t mInputError = AAUDIO_OK;
+ aaudio_result_t mOutputError = AAUDIO_OK;
+
+aaudio_data_callback_result_t dataCallbackProc(
+ void *audioData,
+ int32_t numFrames);
+
+private:
+
+ int32_t readFormattedData(int32_t numFrames);
+
+ GlitchAnalyzer mSineAnalyzer;
+ PulseLatencyAnalyzer mPulseLatencyAnalyzer;
+ LoopbackProcessor *mLoopbackProcessor;
+
+ int32_t mInputFramesMaximum = 0;
+ int32_t mActualInputChannelCount = 0;
+ int32_t mActualOutputChannelCount = 0;
+ int32_t mNumCallbacksToDrain = kNumCallbacksToDrain;
+ int32_t mNumCallbacksToNotRead = kNumCallbacksToNotRead;
+ int32_t mNumCallbacksToDiscard = kNumCallbacksToDiscard;
+ int32_t mMinNumFrames = INT32_MAX;
+ int32_t mMaxNumFrames = 0;
+ int32_t mInsufficientReadCount = 0;
+ int32_t mInsufficientReadFrames = 0;
+ int32_t mFramesReadTotal = 0;
+ int32_t mFramesWrittenTotal = 0;
+ bool mIsDone = false;
+
+ static constexpr int kLogPeriodMillis = 1000;
+ static constexpr int kNumInputChannels = 1;
+ static constexpr int kNumCallbacksToDrain = 20;
+ static constexpr int kNumCallbacksToNotRead = 0; // let input fill back up
+ static constexpr int kNumCallbacksToDiscard = 20;
+ static constexpr int kDefaultHangTimeMillis = 50;
+ static constexpr int kMaxGlitchEventsToSave = 32;
+ static constexpr int kDefaultOutputSizeBursts = 2;
+};
+
+#endif // CTS_NATIVE_AUDIO_ANALYZER_H
diff --git a/apps/CtsVerifier/jni/audio_loopback/analyzer/GlitchAnalyzer.h b/apps/CtsVerifier/jni/audio_loopback/analyzer/GlitchAnalyzer.h
new file mode 100644
index 0000000..0adcd6e
--- /dev/null
+++ b/apps/CtsVerifier/jni/audio_loopback/analyzer/GlitchAnalyzer.h
@@ -0,0 +1,445 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+#ifndef ANALYZER_GLITCH_ANALYZER_H
+#define ANALYZER_GLITCH_ANALYZER_H
+
+#include <algorithm>
+#include <cctype>
+#include <iomanip>
+#include <iostream>
+
+#include "LatencyAnalyzer.h"
+#include "PseudoRandom.h"
+
+/**
+ * Output a steady sine wave and analyze the return signal.
+ *
+ * Use a cosine transform to measure the predicted magnitude and relative phase of the
+ * looped back sine wave. Then generate a predicted signal and compare with the actual signal.
+ */
+class GlitchAnalyzer : public LoopbackProcessor {
+public:
+
+ int32_t getState() const {
+ return mState;
+ }
+
+ double getPeakAmplitude() const {
+ return mPeakFollower.getLevel();
+ }
+
+ double getTolerance() {
+ return mTolerance;
+ }
+
+ void setTolerance(double tolerance) {
+ mTolerance = tolerance;
+ mScaledTolerance = mMagnitude * mTolerance;
+ }
+
+ void setMagnitude(double magnitude) {
+ mMagnitude = magnitude;
+ mScaledTolerance = mMagnitude * mTolerance;
+ }
+
+ int32_t getGlitchCount() const {
+ return mGlitchCount;
+ }
+
+ int32_t getStateFrameCount(int state) const {
+ return mStateFrameCounters[state];
+ }
+
+ double getSignalToNoiseDB() {
+ static const double threshold = 1.0e-14;
+ if (mMeanSquareSignal < threshold || mMeanSquareNoise < threshold) {
+ return 0.0;
+ } else {
+ double signalToNoise = mMeanSquareSignal / mMeanSquareNoise; // power ratio
+ double signalToNoiseDB = 10.0 * log(signalToNoise);
+ if (signalToNoiseDB < MIN_SNR_DB) {
+ ALOGD("ERROR - signal to noise ratio is too low! < %d dB. Adjust volume.",
+ MIN_SNR_DB);
+ setResult(ERROR_VOLUME_TOO_LOW);
+ }
+ return signalToNoiseDB;
+ }
+ }
+
+ std::string analyze() override {
+ std::stringstream report;
+ report << "GlitchAnalyzer ------------------\n";
+ report << LOOPBACK_RESULT_TAG "peak.amplitude = " << std::setw(8)
+ << getPeakAmplitude() << "\n";
+ report << LOOPBACK_RESULT_TAG "sine.magnitude = " << std::setw(8)
+ << mMagnitude << "\n";
+ report << LOOPBACK_RESULT_TAG "rms.noise = " << std::setw(8)
+ << mMeanSquareNoise << "\n";
+ report << LOOPBACK_RESULT_TAG "signal.to.noise.db = " << std::setw(8)
+ << getSignalToNoiseDB() << "\n";
+ report << LOOPBACK_RESULT_TAG "frames.accumulated = " << std::setw(8)
+ << mFramesAccumulated << "\n";
+ report << LOOPBACK_RESULT_TAG "sine.period = " << std::setw(8)
+ << mSinePeriod << "\n";
+ report << LOOPBACK_RESULT_TAG "test.state = " << std::setw(8)
+ << mState << "\n";
+ report << LOOPBACK_RESULT_TAG "frame.count = " << std::setw(8)
+ << mFrameCounter << "\n";
+ // Did we ever get a lock?
+ bool gotLock = (mState == STATE_LOCKED) || (mGlitchCount > 0);
+ if (!gotLock) {
+ report << "ERROR - failed to lock on reference sine tone.\n";
+ setResult(ERROR_NO_LOCK);
+ } else {
+ // Only print if meaningful.
+ report << LOOPBACK_RESULT_TAG "glitch.count = " << std::setw(8)
+ << mGlitchCount << "\n";
+ report << LOOPBACK_RESULT_TAG "max.glitch = " << std::setw(8)
+ << mMaxGlitchDelta << "\n";
+ if (mGlitchCount > 0) {
+ report << "ERROR - number of glitches > 0\n";
+ setResult(ERROR_GLITCHES);
+ }
+ }
+ return report.str();
+ }
+
+ void printStatus() override {
+ ALOGD("st = %d, #gl = %3d,", mState, mGlitchCount);
+ }
+ /**
+ * Calculate the magnitude of the component of the input signal
+ * that matches the analysis frequency.
+ * Also calculate the phase that we can use to create a
+ * signal that matches that component.
+ * The phase will be between -PI and +PI.
+ */
+ double calculateMagnitude(double *phasePtr = nullptr) {
+ if (mFramesAccumulated == 0) {
+ return 0.0;
+ }
+ double sinMean = mSinAccumulator / mFramesAccumulated;
+ double cosMean = mCosAccumulator / mFramesAccumulated;
+ double magnitude = 2.0 * sqrt((sinMean * sinMean) + (cosMean * cosMean));
+ if (phasePtr != nullptr) {
+ double phase = M_PI_2 - atan2(sinMean, cosMean);
+ *phasePtr = phase;
+ }
+ return magnitude;
+ }
+
+ /**
+ * @param frameData contains microphone data with sine signal feedback
+ * @param channelCount
+ */
+ result_code processInputFrame(float *frameData, int /* channelCount */) override {
+ result_code result = RESULT_OK;
+
+ float sample = frameData[0];
+ float peak = mPeakFollower.process(sample);
+
+ // Force a periodic glitch to test the detector!
+ if (mForceGlitchDuration > 0) {
+ if (mForceGlitchCounter == 0) {
+ ALOGE("%s: force a glitch!!", __func__);
+ mForceGlitchCounter = getSampleRate();
+ } else if (mForceGlitchCounter <= mForceGlitchDuration) {
+ // Force an abrupt offset.
+ sample += (sample > 0.0) ? -0.5f : 0.5f;
+ }
+ --mForceGlitchCounter;
+ }
+
+ mStateFrameCounters[mState]++; // count how many frames we are in each state
+
+ switch (mState) {
+ case STATE_IDLE:
+ mDownCounter--;
+ if (mDownCounter <= 0) {
+ mState = STATE_IMMUNE;
+ mDownCounter = IMMUNE_FRAME_COUNT;
+ mInputPhase = 0.0; // prevent spike at start
+ mOutputPhase = 0.0;
+ }
+ break;
+
+ case STATE_IMMUNE:
+ mDownCounter--;
+ if (mDownCounter <= 0) {
+ mState = STATE_WAITING_FOR_SIGNAL;
+ }
+ break;
+
+ case STATE_WAITING_FOR_SIGNAL:
+ if (peak > mThreshold) {
+ mState = STATE_WAITING_FOR_LOCK;
+ //ALOGD("%5d: switch to STATE_WAITING_FOR_LOCK", mFrameCounter);
+ resetAccumulator();
+ }
+ break;
+
+ case STATE_WAITING_FOR_LOCK:
+ mSinAccumulator += sample * sinf(mInputPhase);
+ mCosAccumulator += sample * cosf(mInputPhase);
+ mFramesAccumulated++;
+ // Must be a multiple of the period or the calculation will not be accurate.
+ if (mFramesAccumulated == mSinePeriod * PERIODS_NEEDED_FOR_LOCK) {
+ double phaseOffset = 0.0;
+ setMagnitude(calculateMagnitude(&phaseOffset));
+// ALOGD("%s() mag = %f, offset = %f, prev = %f",
+// __func__, mMagnitude, mPhaseOffset, mPreviousPhaseOffset);
+ if (mMagnitude > mThreshold) {
+ if (abs(phaseOffset) < kMaxPhaseError) {
+ mState = STATE_LOCKED;
+// ALOGD("%5d: switch to STATE_LOCKED", mFrameCounter);
+ }
+ // Adjust mInputPhase to match measured phase
+ mInputPhase += phaseOffset;
+ }
+ resetAccumulator();
+ }
+ incrementInputPhase();
+ break;
+
+ case STATE_LOCKED: {
+ // Predict next sine value
+ double predicted = sinf(mInputPhase) * mMagnitude;
+ double diff = predicted - sample;
+ double absDiff = fabs(diff);
+ mMaxGlitchDelta = std::max(mMaxGlitchDelta, absDiff);
+ if (absDiff > mScaledTolerance) {
+ result = ERROR_GLITCHES;
+ onGlitchStart();
+// LOGI("diff glitch detected, absDiff = %g", absDiff);
+ } else {
+ mSumSquareSignal += predicted * predicted;
+ mSumSquareNoise += diff * diff;
+ // Track incoming signal and slowly adjust magnitude to account
+ // for drift in the DRC or AGC.
+ mSinAccumulator += sample * sinf(mInputPhase);
+ mCosAccumulator += sample * cosf(mInputPhase);
+ mFramesAccumulated++;
+ // Must be a multiple of the period or the calculation will not be accurate.
+ if (mFramesAccumulated == mSinePeriod) {
+ const double coefficient = 0.1;
+ double phaseOffset = 0.0;
+ double magnitude = calculateMagnitude(&phaseOffset);
+ // One pole averaging filter.
+ setMagnitude((mMagnitude * (1.0 - coefficient)) + (magnitude * coefficient));
+
+ mMeanSquareNoise = mSumSquareNoise * mInverseSinePeriod;
+ mMeanSquareSignal = mSumSquareSignal * mInverseSinePeriod;
+ resetAccumulator();
+
+ if (abs(phaseOffset) > kMaxPhaseError) {
+ result = ERROR_GLITCHES;
+ onGlitchStart();
+ ALOGD("phase glitch detected, phaseOffset = %g", phaseOffset);
+ } else if (mMagnitude < mThreshold) {
+ result = ERROR_GLITCHES;
+ onGlitchStart();
+ ALOGD("magnitude glitch detected, mMagnitude = %g", mMagnitude);
+ }
+ }
+ }
+ incrementInputPhase();
+ } break;
+
+ case STATE_GLITCHING: {
+ // Predict next sine value
+ mGlitchLength++;
+ double predicted = sinf(mInputPhase) * mMagnitude;
+ double diff = predicted - sample;
+ double absDiff = fabs(diff);
+ mMaxGlitchDelta = std::max(mMaxGlitchDelta, absDiff);
+ if (absDiff < mScaledTolerance) { // close enough?
+ // If we get a full sine period of non-glitch samples in a row then consider the glitch over.
+ // We don't want to just consider a zero crossing the end of a glitch.
+ if (mNonGlitchCount++ > mSinePeriod) {
+ onGlitchEnd();
+ }
+ } else {
+ mNonGlitchCount = 0;
+ if (mGlitchLength > (4 * mSinePeriod)) {
+ relock();
+ }
+ }
+ incrementInputPhase();
+ } break;
+
+ case NUM_STATES: // not a real state
+ break;
+ }
+
+ mFrameCounter++;
+
+ return result;
+ }
+
+ // advance and wrap phase
+ void incrementInputPhase() {
+ mInputPhase += mPhaseIncrement;
+ if (mInputPhase > M_PI) {
+ mInputPhase -= (2.0 * M_PI);
+ }
+ }
+
+ // advance and wrap phase
+ void incrementOutputPhase() {
+ mOutputPhase += mPhaseIncrement;
+ if (mOutputPhase > M_PI) {
+ mOutputPhase -= (2.0 * M_PI);
+ }
+ }
+
+ /**
+ * @param frameData upon return, contains the reference sine wave
+ * @param channelCount
+ */
+ result_code processOutputFrame(float *frameData, int channelCount) override {
+ float output = 0.0f;
+ // Output sine wave so we can measure it.
+ if (mState != STATE_IDLE) {
+ float sinOut = sinf(mOutputPhase);
+ incrementOutputPhase();
+ output = (sinOut * mOutputAmplitude)
+ + (mWhiteNoise.nextRandomDouble() * kNoiseAmplitude);
+ // ALOGD("sin(%f) = %f, %f\n", mOutputPhase, sinOut, mPhaseIncrement);
+ }
+ frameData[0] = output;
+ for (int i = 1; i < channelCount; i++) {
+ frameData[i] = 0.0f;
+ }
+ return RESULT_OK;
+ }
+
+ void onGlitchStart() {
+ mGlitchCount++;
+// ALOGD("%5d: STARTED a glitch # %d", mFrameCounter, mGlitchCount);
+ mState = STATE_GLITCHING;
+ mGlitchLength = 1;
+ mNonGlitchCount = 0;
+ }
+
+ void onGlitchEnd() {
+// ALOGD("%5d: ENDED a glitch # %d, length = %d", mFrameCounter, mGlitchCount, mGlitchLength);
+ mState = STATE_LOCKED;
+ resetAccumulator();
+ }
+
+ // reset the sine wave detector
+ void resetAccumulator() {
+ mFramesAccumulated = 0;
+ mSinAccumulator = 0.0;
+ mCosAccumulator = 0.0;
+ mSumSquareSignal = 0.0;
+ mSumSquareNoise = 0.0;
+ }
+
+ void relock() {
+// ALOGD("relock: %d because of a very long %d glitch", mFrameCounter, mGlitchLength);
+ mState = STATE_WAITING_FOR_LOCK;
+ resetAccumulator();
+ }
+
+ void reset() override {
+ LoopbackProcessor::reset();
+ mState = STATE_IDLE;
+ mDownCounter = IDLE_FRAME_COUNT;
+ resetAccumulator();
+ }
+
+ void prepareToTest() override {
+ LoopbackProcessor::prepareToTest();
+ mSinePeriod = getSampleRate() / kTargetGlitchFrequency;
+ mOutputPhase = 0.0f;
+ mInverseSinePeriod = 1.0 / mSinePeriod;
+ mPhaseIncrement = 2.0 * M_PI * mInverseSinePeriod;
+ mGlitchCount = 0;
+ mMaxGlitchDelta = 0.0;
+ for (int i = 0; i < NUM_STATES; i++) {
+ mStateFrameCounters[i] = 0;
+ }
+ }
+
+private:
+
+ // These must match the values in GlitchActivity.java
+ enum sine_state_t {
+ STATE_IDLE, // beginning
+ STATE_IMMUNE, // ignoring input, waiting fo HW to settle
+ STATE_WAITING_FOR_SIGNAL, // looking for a loud signal
+ STATE_WAITING_FOR_LOCK, // trying to lock onto the phase of the sine
+ STATE_LOCKED, // locked on the sine wave, looking for glitches
+ STATE_GLITCHING, // locked on the sine wave but glitching
+ NUM_STATES
+ };
+
+ enum constants {
+ // Arbitrary durations, assuming 48000 Hz
+ IDLE_FRAME_COUNT = 48 * 100,
+ IMMUNE_FRAME_COUNT = 48 * 100,
+ PERIODS_NEEDED_FOR_LOCK = 8,
+ MIN_SNR_DB = 65
+ };
+
+ static constexpr float kNoiseAmplitude = 0.00; // Used to experiment with warbling caused by DRC.
+ static constexpr int kTargetGlitchFrequency = 607;
+ static constexpr double kMaxPhaseError = M_PI * 0.05;
+
+ float mTolerance = 0.10; // scaled from 0.0 to 1.0
+ double mThreshold = 0.005;
+ int mSinePeriod = 1; // this will be set before use
+ double mInverseSinePeriod = 1.0;
+
+ int32_t mStateFrameCounters[NUM_STATES];
+
+ double mPhaseIncrement = 0.0;
+ double mInputPhase = 0.0;
+ double mOutputPhase = 0.0;
+ double mMagnitude = 0.0;
+ int32_t mFramesAccumulated = 0;
+ double mSinAccumulator = 0.0;
+ double mCosAccumulator = 0.0;
+ double mMaxGlitchDelta = 0.0;
+ int32_t mGlitchCount = 0;
+ int32_t mNonGlitchCount = 0;
+ int32_t mGlitchLength = 0;
+ // This is used for processing every frame so we cache it here.
+ double mScaledTolerance = 0.0;
+ int mDownCounter = IDLE_FRAME_COUNT;
+ int32_t mFrameCounter = 0;
+ double mOutputAmplitude = 0.75;
+
+ int32_t mForceGlitchDuration = 0; // if > 0 then force a glitch for debugging
+ int32_t mForceGlitchCounter = 4 * 48000; // count down and trigger at zero
+
+ // measure background noise continuously as a deviation from the expected signal
+ double mSumSquareSignal = 0.0;
+ double mSumSquareNoise = 0.0;
+ double mMeanSquareSignal = 0.0;
+ double mMeanSquareNoise = 0.0;
+
+ PeakDetector mPeakFollower;
+
+ PseudoRandom mWhiteNoise;
+
+ sine_state_t mState = STATE_IDLE;
+};
+
+
+#endif //ANALYZER_GLITCH_ANALYZER_H
diff --git a/apps/CtsVerifier/jni/audio_loopback/analyzer/LatencyAnalyzer.h b/apps/CtsVerifier/jni/audio_loopback/analyzer/LatencyAnalyzer.h
new file mode 100644
index 0000000..59106cb
--- /dev/null
+++ b/apps/CtsVerifier/jni/audio_loopback/analyzer/LatencyAnalyzer.h
@@ -0,0 +1,604 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+/**
+ * Tools for measuring latency and for detecting glitches.
+ * These classes are pure math and can be used with any audio system.
+ */
+
+#ifndef ANALYZER_LATENCY_ANALYZER_H
+#define ANALYZER_LATENCY_ANALYZER_H
+
+#include <algorithm>
+#include <assert.h>
+#include <cctype>
+#include <iomanip>
+#include <iostream>
+#include <math.h>
+#include <memory>
+#include <sstream>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <vector>
+
+#include "PeakDetector.h"
+#include "PseudoRandom.h"
+#include "RandomPulseGenerator.h"
+
+
+#define LOOPBACK_RESULT_TAG "RESULT: "
+
+static constexpr int32_t kDefaultSampleRate = 48000;
+static constexpr int32_t kMillisPerSecond = 1000;
+static constexpr int32_t kMaxLatencyMillis = 700; // arbitrary and generous
+static constexpr double kMinimumConfidence = 0.2;
+
+struct LatencyReport {
+ int32_t latencyInFrames = 0.0;
+ double confidence = 0.0;
+
+ void reset() {
+ latencyInFrames = 0;
+ confidence = 0.0;
+ }
+};
+
+// Calculate a normalized cross correlation.
+static double calculateNormalizedCorrelation(const float *a,
+ const float *b,
+ int windowSize) {
+ double correlation = 0.0;
+ double sumProducts = 0.0;
+ double sumSquares = 0.0;
+
+ // Correlate a against b.
+ for (int i = 0; i < windowSize; i++) {
+ float s1 = a[i];
+ float s2 = b[i];
+ // Use a normalized cross-correlation.
+ sumProducts += s1 * s2;
+ sumSquares += ((s1 * s1) + (s2 * s2));
+ }
+
+ if (sumSquares >= 1.0e-9) {
+ correlation = 2.0 * sumProducts / sumSquares;
+ }
+ return correlation;
+}
+
+static double calculateRootMeanSquare(float *data, int32_t numSamples) {
+ double sum = 0.0;
+ for (int32_t i = 0; i < numSamples; i++) {
+ float sample = data[i];
+ sum += sample * sample;
+ }
+ return sqrt(sum / numSamples);
+}
+
+/**
+ * Monophonic recording with processing.
+ */
+class AudioRecording
+{
+public:
+
+ void allocate(int maxFrames) {
+ mData = std::make_unique<float[]>(maxFrames);
+ mMaxFrames = maxFrames;
+ }
+
+ // Write SHORT data from the first channel.
+ int32_t write(int16_t *inputData, int32_t inputChannelCount, int32_t numFrames) {
+ // stop at end of buffer
+ if ((mFrameCounter + numFrames) > mMaxFrames) {
+ numFrames = mMaxFrames - mFrameCounter;
+ }
+ for (int i = 0; i < numFrames; i++) {
+ mData[mFrameCounter++] = inputData[i * inputChannelCount] * (1.0f / 32768);
+ }
+ return numFrames;
+ }
+
+ // Write FLOAT data from the first channel.
+ int32_t write(float *inputData, int32_t inputChannelCount, int32_t numFrames) {
+ // stop at end of buffer
+ if ((mFrameCounter + numFrames) > mMaxFrames) {
+ numFrames = mMaxFrames - mFrameCounter;
+ }
+ for (int i = 0; i < numFrames; i++) {
+ mData[mFrameCounter++] = inputData[i * inputChannelCount];
+ }
+ return numFrames;
+ }
+
+ // Write FLOAT data from the first channel.
+ int32_t write(float sample) {
+ // stop at end of buffer
+ if (mFrameCounter < mMaxFrames) {
+ mData[mFrameCounter++] = sample;
+ return 1;
+ }
+ return 0;
+ }
+
+ void clear() {
+ mFrameCounter = 0;
+ }
+ int32_t size() const {
+ return mFrameCounter;
+ }
+
+ bool isFull() const {
+ return mFrameCounter >= mMaxFrames;
+ }
+
+ float *getData() const {
+ return mData.get();
+ }
+
+ void setSampleRate(int32_t sampleRate) {
+ mSampleRate = sampleRate;
+ }
+
+ int32_t getSampleRate() const {
+ return mSampleRate;
+ }
+
+ /**
+ * Square the samples so they are all positive and so the peaks are emphasized.
+ */
+ void square() {
+ float *x = mData.get();
+ for (int i = 0; i < mFrameCounter; i++) {
+ x[i] *= x[i];
+ }
+ }
+
+ /**
+ * Amplify a signal so that the peak matches the specified target.
+ *
+ * @param target final max value
+ * @return gain applied to signal
+ */
+ float normalize(float target) {
+ float maxValue = 1.0e-9f;
+ for (int i = 0; i < mFrameCounter; i++) {
+ maxValue = std::max(maxValue, abs(mData[i]));
+ }
+ float gain = target / maxValue;
+ for (int i = 0; i < mFrameCounter; i++) {
+ mData[i] *= gain;
+ }
+ return gain;
+ }
+
+private:
+ std::unique_ptr<float[]> mData;
+ int32_t mFrameCounter = 0;
+ int32_t mMaxFrames = 0;
+ int32_t mSampleRate = kDefaultSampleRate; // common default
+};
+
+static int measureLatencyFromPulse(AudioRecording &recorded,
+ AudioRecording &pulse,
+ LatencyReport *report) {
+
+ report->latencyInFrames = 0;
+ report->confidence = 0.0;
+
+ int numCorrelations = recorded.size() - pulse.size();
+ if (numCorrelations < 10) {
+ ALOGE("%s() recording too small = %d frames\n", __func__, recorded.size());
+ return -1;
+ }
+ std::unique_ptr<float[]> correlations= std::make_unique<float[]>(numCorrelations);
+
+ // Correlate pulse against the recorded data.
+ for (int i = 0; i < numCorrelations; i++) {
+ float correlation = (float) calculateNormalizedCorrelation(&recorded.getData()[i],
+ &pulse.getData()[0],
+ pulse.size());
+ correlations[i] = correlation;
+ }
+
+ // Find highest peak in correlation array.
+ float peakCorrelation = 0.0;
+ int peakIndex = -1;
+ for (int i = 0; i < numCorrelations; i++) {
+ float value = abs(correlations[i]);
+ if (value > peakCorrelation) {
+ peakCorrelation = value;
+ peakIndex = i;
+ }
+ }
+ if (peakIndex < 0) {
+ ALOGE("%s() no signal for correlation\n", __func__);
+ return -2;
+ }
+
+ report->latencyInFrames = peakIndex;
+ report->confidence = peakCorrelation;
+
+ return 0;
+}
+
+// ====================================================================================
+class LoopbackProcessor {
+public:
+ virtual ~LoopbackProcessor() = default;
+
+ enum result_code {
+ RESULT_OK = 0,
+ ERROR_NOISY = -99,
+ ERROR_VOLUME_TOO_LOW,
+ ERROR_VOLUME_TOO_HIGH,
+ ERROR_CONFIDENCE,
+ ERROR_INVALID_STATE,
+ ERROR_GLITCHES,
+ ERROR_NO_LOCK
+ };
+
+ virtual void prepareToTest() {
+ reset();
+ }
+
+ virtual void reset() {
+ mResult = 0;
+ mResetCount++;
+ }
+
+ virtual result_code processInputFrame(float *frameData, int channelCount) = 0;
+ virtual result_code processOutputFrame(float *frameData, int channelCount) = 0;
+
+ void process(float *inputData, int inputChannelCount, int numInputFrames,
+ float *outputData, int outputChannelCount, int numOutputFrames) {
+ int numBoth = std::min(numInputFrames, numOutputFrames);
+ // Process one frame at a time.
+ for (int i = 0; i < numBoth; i++) {
+ processInputFrame(inputData, inputChannelCount);
+ inputData += inputChannelCount;
+ processOutputFrame(outputData, outputChannelCount);
+ outputData += outputChannelCount;
+ }
+ // If there is more input than output.
+ for (int i = numBoth; i < numInputFrames; i++) {
+ processInputFrame(inputData, inputChannelCount);
+ inputData += inputChannelCount;
+ }
+ // If there is more output than input.
+ for (int i = numBoth; i < numOutputFrames; i++) {
+ processOutputFrame(outputData, outputChannelCount);
+ outputData += outputChannelCount;
+ }
+ }
+
+ virtual std::string analyze() = 0;
+
+ virtual void printStatus() {};
+
+ int32_t getResult() {
+ return mResult;
+ }
+
+ void setResult(int32_t result) {
+ mResult = result;
+ }
+
+ virtual bool isDone() {
+ return false;
+ }
+
+ virtual int save(const char *fileName) {
+ (void) fileName;
+ return -1;
+ }
+
+ virtual int load(const char *fileName) {
+ (void) fileName;
+ return -1;
+ }
+
+ virtual void setSampleRate(int32_t sampleRate) {
+ mSampleRate = sampleRate;
+ }
+
+ int32_t getSampleRate() const {
+ return mSampleRate;
+ }
+
+ int32_t getResetCount() const {
+ return mResetCount;
+ }
+
+ /** Called when not enough input frames could be read after synchronization.
+ */
+ virtual void onInsufficientRead() {
+ reset();
+ }
+
+protected:
+ int32_t mResetCount = 0;
+
+private:
+ int32_t mSampleRate = kDefaultSampleRate;
+ int32_t mResult = 0;
+};
+
+class LatencyAnalyzer : public LoopbackProcessor {
+public:
+
+ LatencyAnalyzer() : LoopbackProcessor() {}
+ virtual ~LatencyAnalyzer() = default;
+
+ virtual int32_t getProgress() const = 0;
+
+ virtual int getState() = 0;
+
+ // @return latency in frames
+ virtual int32_t getMeasuredLatency() = 0;
+
+ virtual double getMeasuredConfidence() = 0;
+
+ virtual double getBackgroundRMS() = 0;
+
+ virtual double getSignalRMS() = 0;
+
+};
+
+// ====================================================================================
+/**
+ * Measure latency given a loopback stream data.
+ * Use an encoded bit train as the sound source because it
+ * has an unambiguous correlation value.
+ * Uses a state machine to cycle through various stages.
+ *
+ */
+class PulseLatencyAnalyzer : public LatencyAnalyzer {
+public:
+
+ PulseLatencyAnalyzer() : LatencyAnalyzer() {
+ int32_t maxLatencyFrames = getSampleRate() * kMaxLatencyMillis / kMillisPerSecond;
+ int32_t numPulseBits = getSampleRate() * kPulseLengthMillis
+ / (kFramesPerEncodedBit * kMillisPerSecond);
+ int32_t pulseLength = numPulseBits * kFramesPerEncodedBit;
+ mFramesToRecord = pulseLength + maxLatencyFrames;
+ mAudioRecording.allocate(mFramesToRecord);
+ mAudioRecording.setSampleRate(getSampleRate());
+ generateRandomPulse(pulseLength);
+ }
+
+ void generateRandomPulse(int32_t pulseLength) {
+ mPulse.allocate(pulseLength);
+ RandomPulseGenerator pulser(kFramesPerEncodedBit);
+ for (int i = 0; i < pulseLength; i++) {
+ mPulse.write(pulser.nextFloat());
+ }
+ }
+
+ int getState() override {
+ return mState;
+ }
+
+ void setSampleRate(int32_t sampleRate) override {
+ LoopbackProcessor::setSampleRate(sampleRate);
+ mAudioRecording.setSampleRate(sampleRate);
+ }
+
+ void reset() override {
+ LoopbackProcessor::reset();
+ mDownCounter = getSampleRate() / 2;
+ mLoopCounter = 0;
+
+ mPulseCursor = 0;
+ mBackgroundSumSquare = 0.0f;
+ mBackgroundSumCount = 0;
+ mBackgroundRMS = 0.0f;
+ mSignalRMS = 0.0f;
+
+ mState = STATE_MEASURE_BACKGROUND;
+ mAudioRecording.clear();
+ mLatencyReport.reset();
+ }
+
+ bool hasEnoughData() {
+ return mAudioRecording.isFull();
+ }
+
+ bool isDone() override {
+ return mState == STATE_DONE;
+ }
+
+ int32_t getProgress() const override {
+ return mAudioRecording.size();
+ }
+
+ std::string analyze() override {
+ std::stringstream report;
+ report << "PulseLatencyAnalyzer ---------------\n";
+ report << LOOPBACK_RESULT_TAG "test.state = "
+ << std::setw(8) << mState << "\n";
+ report << LOOPBACK_RESULT_TAG "test.state.name = "
+ << convertStateToText(mState) << "\n";
+ report << LOOPBACK_RESULT_TAG "background.rms = "
+ << std::setw(8) << mBackgroundRMS << "\n";
+
+ int32_t newResult = RESULT_OK;
+ if (mState != STATE_GOT_DATA) {
+ report << "WARNING - Bad state. Check volume on device.\n";
+ // setResult(ERROR_INVALID_STATE);
+ } else {
+ float gain = mAudioRecording.normalize(1.0f);
+ measureLatencyFromPulse(mAudioRecording,
+ mPulse,
+ &mLatencyReport);
+
+ if (mLatencyReport.confidence < kMinimumConfidence) {
+ report << " ERROR - confidence too low!";
+ newResult = ERROR_CONFIDENCE;
+ } else {
+ mSignalRMS = calculateRootMeanSquare(
+ &mAudioRecording.getData()[mLatencyReport.latencyInFrames], mPulse.size())
+ / gain;
+ }
+ double latencyMillis = kMillisPerSecond * (double) mLatencyReport.latencyInFrames
+ / getSampleRate();
+ report << LOOPBACK_RESULT_TAG "latency.frames = " << std::setw(8)
+ << mLatencyReport.latencyInFrames << "\n";
+ report << LOOPBACK_RESULT_TAG "latency.msec = " << std::setw(8)
+ << latencyMillis << "\n";
+ report << LOOPBACK_RESULT_TAG "latency.confidence = " << std::setw(8)
+ << mLatencyReport.confidence << "\n";
+ }
+ mState = STATE_DONE;
+ if (getResult() == RESULT_OK) {
+ setResult(newResult);
+ }
+
+ return report.str();
+ }
+
+ int32_t getMeasuredLatency() override {
+ return mLatencyReport.latencyInFrames;
+ }
+
+ double getMeasuredConfidence() override {
+ return mLatencyReport.confidence;
+ }
+
+ double getBackgroundRMS() override {
+ return mBackgroundRMS;
+ }
+
+ double getSignalRMS() override {
+ return mSignalRMS;
+ }
+
+ bool isRecordingComplete() {
+ return mState == STATE_GOT_DATA;
+ }
+
+ void printStatus() override {
+ ALOGD("latency: st = %d = %s", mState, convertStateToText(mState));
+ }
+
+ result_code processInputFrame(float *frameData, int channelCount) override {
+ echo_state nextState = mState;
+ mLoopCounter++;
+
+ switch (mState) {
+ case STATE_MEASURE_BACKGROUND:
+ // Measure background RMS on channel 0
+ mBackgroundSumSquare += frameData[0] * frameData[0];
+ mBackgroundSumCount++;
+ mDownCounter--;
+ if (mDownCounter <= 0) {
+ mBackgroundRMS = sqrtf(mBackgroundSumSquare / mBackgroundSumCount);
+ nextState = STATE_IN_PULSE;
+ mPulseCursor = 0;
+ }
+ break;
+
+ case STATE_IN_PULSE:
+ // Record input until the mAudioRecording is full.
+ mAudioRecording.write(frameData, channelCount, 1);
+ if (hasEnoughData()) {
+ nextState = STATE_GOT_DATA;
+ }
+ break;
+
+ case STATE_GOT_DATA:
+ case STATE_DONE:
+ default:
+ break;
+ }
+
+ mState = nextState;
+ return RESULT_OK;
+ }
+
+ result_code processOutputFrame(float *frameData, int channelCount) override {
+ switch (mState) {
+ case STATE_IN_PULSE:
+ if (mPulseCursor < mPulse.size()) {
+ float pulseSample = mPulse.getData()[mPulseCursor++];
+ for (int i = 0; i < channelCount; i++) {
+ frameData[i] = pulseSample;
+ }
+ } else {
+ for (int i = 0; i < channelCount; i++) {
+ frameData[i] = 0;
+ }
+ }
+ break;
+
+ case STATE_MEASURE_BACKGROUND:
+ case STATE_GOT_DATA:
+ case STATE_DONE:
+ default:
+ for (int i = 0; i < channelCount; i++) {
+ frameData[i] = 0.0f; // silence
+ }
+ break;
+ }
+
+ return RESULT_OK;
+ }
+
+private:
+
+ enum echo_state {
+ STATE_MEASURE_BACKGROUND,
+ STATE_IN_PULSE,
+ STATE_GOT_DATA, // must match RoundTripLatencyActivity.java
+ STATE_DONE,
+ };
+
+ const char *convertStateToText(echo_state state) {
+ switch (state) {
+ case STATE_MEASURE_BACKGROUND:
+ return "INIT";
+ case STATE_IN_PULSE:
+ return "PULSE";
+ case STATE_GOT_DATA:
+ return "GOT_DATA";
+ case STATE_DONE:
+ return "DONE";
+ }
+ return "UNKNOWN";
+ }
+
+ int32_t mDownCounter = 500;
+ int32_t mLoopCounter = 0;
+ echo_state mState = STATE_MEASURE_BACKGROUND;
+
+ static constexpr int32_t kFramesPerEncodedBit = 8; // multiple of 2
+ static constexpr int32_t kPulseLengthMillis = 500;
+
+ AudioRecording mPulse;
+ int32_t mPulseCursor = 0;
+
+ double mBackgroundSumSquare = 0.0;
+ int32_t mBackgroundSumCount = 0;
+ double mBackgroundRMS = 0.0;
+ double mSignalRMS = 0.0;
+ int32_t mFramesToRecord = 0;
+
+ AudioRecording mAudioRecording; // contains only the input after starting the pulse
+ LatencyReport mLatencyReport;
+};
+
+#endif // ANALYZER_LATENCY_ANALYZER_H
diff --git a/apps/CtsVerifier/jni/audio_loopback/analyzer/ManchesterEncoder.h b/apps/CtsVerifier/jni/audio_loopback/analyzer/ManchesterEncoder.h
new file mode 100644
index 0000000..3f7eebb
--- /dev/null
+++ b/apps/CtsVerifier/jni/audio_loopback/analyzer/ManchesterEncoder.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2020 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.
+ */
+
+#ifndef ANALYZER_MANCHESTER_ENCODER_H
+#define ANALYZER_MANCHESTER_ENCODER_H
+
+#include <cstdint>
+
+/**
+ * Encode bytes using Manchester Coding scheme.
+ *
+ * Manchester Code is self clocking.
+ * There is a transition in the middle of every bit.
+ * Zero is high then low.
+ * One is low then high.
+ *
+ * This avoids having long DC sections that would droop when
+ * passed though analog circuits with AC coupling.
+ *
+ * IEEE 802.3 compatible.
+ */
+
+class ManchesterEncoder {
+public:
+ ManchesterEncoder(int samplesPerPulse)
+ : mSamplesPerPulse(samplesPerPulse)
+ , mSamplesPerPulseHalf(samplesPerPulse / 2)
+ , mCursor(samplesPerPulse) {
+ }
+
+ virtual ~ManchesterEncoder() = default;
+
+ /**
+ * This will be called when the next byte is needed.
+ * @return
+ */
+ virtual uint8_t onNextByte() = 0;
+
+ /**
+ * Generate the next floating point sample.
+ * @return
+ */
+ virtual float nextFloat() {
+ advanceSample();
+ if (mCurrentBit) {
+ return (mCursor < mSamplesPerPulseHalf) ? -1.0f : 1.0f; // one
+ } else {
+ return (mCursor < mSamplesPerPulseHalf) ? 1.0f : -1.0f; // zero
+ }
+ }
+
+protected:
+ /**
+ * This will be called when a new bit is ready to be encoded.
+ * It can be used to prepare the encoded samples.
+ * @param current
+ */
+ virtual void onNextBit(bool /* current */) {};
+
+ void advanceSample() {
+ // Are we ready for a new bit?
+ if (++mCursor >= mSamplesPerPulse) {
+ mCursor = 0;
+ if (mBitsLeft == 0) {
+ mCurrentByte = onNextByte();
+ mBitsLeft = 8;
+ }
+ --mBitsLeft;
+ mCurrentBit = (mCurrentByte >> mBitsLeft) & 1;
+ onNextBit(mCurrentBit);
+ }
+ }
+
+ bool getCurrentBit() {
+ return mCurrentBit;
+ }
+
+ const int mSamplesPerPulse;
+ const int mSamplesPerPulseHalf;
+ int mCursor;
+ int mBitsLeft = 0;
+ uint8_t mCurrentByte = 0;
+ bool mCurrentBit = false;
+};
+#endif //ANALYZER_MANCHESTER_ENCODER_H
diff --git a/apps/CtsVerifier/jni/audio_loopback/analyzer/PeakDetector.h b/apps/CtsVerifier/jni/audio_loopback/analyzer/PeakDetector.h
new file mode 100644
index 0000000..e407eac
--- /dev/null
+++ b/apps/CtsVerifier/jni/audio_loopback/analyzer/PeakDetector.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2020 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.
+ */
+
+#ifndef ANALYZER_PEAK_DETECTOR_H
+#define ANALYZER_PEAK_DETECTOR_H
+
+#include <math.h>
+
+/**
+ * Measure a peak envelope by rising with the peaks,
+ * and decaying exponentially after each peak.
+ * The absolute value of the input signal is used.
+ */
+class PeakDetector {
+public:
+
+ void reset() {
+ mLevel = 0.0;
+ }
+
+ double process(double input) {
+ mLevel *= mDecay; // exponential decay
+ input = fabs(input);
+ // never fall below the input signal
+ if (input > mLevel) {
+ mLevel = input;
+ }
+ return mLevel;
+ }
+
+ double getLevel() const {
+ return mLevel;
+ }
+
+ double getDecay() const {
+ return mDecay;
+ }
+
+ /**
+ * Multiply the level by this amount on every iteration.
+ * This provides an exponential decay curve.
+ * A value just under 1.0 is best, for example, 0.99;
+ * @param decay scale level for each input
+ */
+ void setDecay(double decay) {
+ mDecay = decay;
+ }
+
+private:
+ static constexpr double kDefaultDecay = 0.99f;
+
+ double mLevel = 0.0;
+ double mDecay = kDefaultDecay;
+};
+#endif //ANALYZER_PEAK_DETECTOR_H
diff --git a/apps/CtsVerifier/jni/audio_loopback/analyzer/PseudoRandom.h b/apps/CtsVerifier/jni/audio_loopback/analyzer/PseudoRandom.h
new file mode 100644
index 0000000..d8f5894
--- /dev/null
+++ b/apps/CtsVerifier/jni/audio_loopback/analyzer/PseudoRandom.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+
+#ifndef ANALYZER_PSEUDORANDOM_H
+#define ANALYZER_PSEUDORANDOM_H
+
+#include <cctype>
+
+class PseudoRandom {
+public:
+ PseudoRandom(int64_t seed = 99887766)
+ : mSeed(seed)
+ {}
+
+ /**
+ * Returns the next random double from -1.0 to 1.0
+ *
+ * @return value from -1.0 to 1.0
+ */
+ double nextRandomDouble() {
+ return nextRandomInteger() * (0.5 / (((int32_t)1) << 30));
+ }
+
+ /** Calculate random 32 bit number using linear-congruential method
+ * with known real-time performance.
+ */
+ int32_t nextRandomInteger() {
+#if __has_builtin(__builtin_mul_overflow) && __has_builtin(__builtin_add_overflow)
+ int64_t prod;
+ // Use values for 64-bit sequence from MMIX by Donald Knuth.
+ __builtin_mul_overflow(mSeed, (int64_t)6364136223846793005, &prod);
+ __builtin_add_overflow(prod, (int64_t)1442695040888963407, &mSeed);
+#else
+ mSeed = (mSeed * (int64_t)6364136223846793005) + (int64_t)1442695040888963407;
+#endif
+ return (int32_t) (mSeed >> 32); // The higher bits have a longer sequence.
+ }
+
+private:
+ int64_t mSeed;
+};
+
+#endif //ANALYZER_PSEUDORANDOM_H
diff --git a/apps/CtsVerifier/jni/audio_loopback/analyzer/RandomPulseGenerator.h b/apps/CtsVerifier/jni/audio_loopback/analyzer/RandomPulseGenerator.h
new file mode 100644
index 0000000..b057d09
--- /dev/null
+++ b/apps/CtsVerifier/jni/audio_loopback/analyzer/RandomPulseGenerator.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2020 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.
+ */
+
+#ifndef ANALYZER_RANDOM_PULSE_GENERATOR_H
+#define ANALYZER_RANDOM_PULSE_GENERATOR_H
+
+#include <stdlib.h>
+#include "RoundedManchesterEncoder.h"
+
+/**
+ * Encode random ones and zeros using Manchester Code per IEEE 802.3.
+ */
+class RandomPulseGenerator : public RoundedManchesterEncoder {
+public:
+ RandomPulseGenerator(int samplesPerPulse)
+ : RoundedManchesterEncoder(samplesPerPulse) {
+ }
+
+ virtual ~RandomPulseGenerator() = default;
+
+ /**
+ * This will be called when the next byte is needed.
+ * @return random byte
+ */
+ uint8_t onNextByte() override {
+ return static_cast<uint8_t>(rand());
+ }
+};
+
+#endif //ANALYZER_RANDOM_PULSE_GENERATOR_H
diff --git a/apps/CtsVerifier/jni/audio_loopback/analyzer/RoundedManchesterEncoder.h b/apps/CtsVerifier/jni/audio_loopback/analyzer/RoundedManchesterEncoder.h
new file mode 100644
index 0000000..76f57e7
--- /dev/null
+++ b/apps/CtsVerifier/jni/audio_loopback/analyzer/RoundedManchesterEncoder.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2020 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.
+ */
+
+#ifndef ANALYZER_ROUNDED_MANCHESTER_ENCODER_H
+#define ANALYZER_ROUNDED_MANCHESTER_ENCODER_H
+
+#include <math.h>
+#include <memory.h>
+#include <stdlib.h>
+#include "ManchesterEncoder.h"
+
+/**
+ * Encode bytes using Manchester Code.
+ * Round the edges using a half cosine to reduce ringing caused by a hard edge.
+ */
+
+class RoundedManchesterEncoder : public ManchesterEncoder {
+public:
+ RoundedManchesterEncoder(int samplesPerPulse)
+ : ManchesterEncoder(samplesPerPulse) {
+ int rampSize = samplesPerPulse / 4;
+ mZeroAfterZero = std::make_unique<float[]>(samplesPerPulse);
+ mZeroAfterOne = std::make_unique<float[]>(samplesPerPulse);
+
+ int sampleIndex = 0;
+ for (int rampIndex = 0; rampIndex < rampSize; rampIndex++) {
+ float phase = (rampIndex + 1) * M_PI / rampSize;
+ float sample = -cosf(phase);
+ mZeroAfterZero[sampleIndex] = sample;
+ mZeroAfterOne[sampleIndex] = 1.0f;
+ sampleIndex++;
+ }
+ for (int rampIndex = 0; rampIndex < rampSize; rampIndex++) {
+ mZeroAfterZero[sampleIndex] = 1.0f;
+ mZeroAfterOne[sampleIndex] = 1.0f;
+ sampleIndex++;
+ }
+ for (int rampIndex = 0; rampIndex < rampSize; rampIndex++) {
+ float phase = (rampIndex + 1) * M_PI / rampSize;
+ float sample = cosf(phase);
+ mZeroAfterZero[sampleIndex] = sample;
+ mZeroAfterOne[sampleIndex] = sample;
+ sampleIndex++;
+ }
+ for (int rampIndex = 0; rampIndex < rampSize; rampIndex++) {
+ mZeroAfterZero[sampleIndex] = -1.0f;
+ mZeroAfterOne[sampleIndex] = -1.0f;
+ sampleIndex++;
+ }
+ }
+
+ void onNextBit(bool current) override {
+ // Do we need to use the rounded edge?
+ mCurrentSamples = (current ^ mPreviousBit)
+ ? mZeroAfterOne.get()
+ : mZeroAfterZero.get();
+ mPreviousBit = current;
+ }
+
+ float nextFloat() override {
+ advanceSample();
+ float output = mCurrentSamples[mCursor];
+ if (getCurrentBit()) output = -output;
+ return output;
+ }
+
+private:
+
+ bool mPreviousBit = false;
+ float *mCurrentSamples = nullptr;
+ std::unique_ptr<float[]> mZeroAfterZero;
+ std::unique_ptr<float[]> mZeroAfterOne;
+};
+
+#endif //ANALYZER_ROUNDED_MANCHESTER_ENCODER_H
diff --git a/apps/CtsVerifier/jni/audio_loopback/audio_utils/atomic.c b/apps/CtsVerifier/jni/audio_loopback/audio_utils/atomic.c
deleted file mode 100644
index db2b3fc..0000000
--- a/apps/CtsVerifier/jni/audio_loopback/audio_utils/atomic.c
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "atomic.h"
-
-#include <stdatomic.h>
-
-int32_t android_atomic_acquire_load(volatile const int32_t* addr)
-{
- volatile atomic_int_least32_t* a = (volatile atomic_int_least32_t*)addr;
- return atomic_load_explicit(a, memory_order_acquire);
-}
-
-void android_atomic_release_store(int32_t value, volatile int32_t* addr)
-{
- volatile atomic_int_least32_t* a = (volatile atomic_int_least32_t*)addr;
- atomic_store_explicit(a, value, memory_order_release);
-}
diff --git a/apps/CtsVerifier/jni/audio_loopback/audio_utils/atomic.h b/apps/CtsVerifier/jni/audio_loopback/audio_utils/atomic.h
deleted file mode 100644
index 535c926..0000000
--- a/apps/CtsVerifier/jni/audio_loopback/audio_utils/atomic.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_AUDIO_ATOMIC_H
-#define ANDROID_AUDIO_ATOMIC_H
-
-#include <stdlib.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-int32_t android_atomic_acquire_load(volatile const int32_t* addr);
-void android_atomic_release_store(int32_t value, volatile int32_t* addr);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif // ANDROID_AUDIO_ATOMIC_H
diff --git a/apps/CtsVerifier/jni/audio_loopback/audio_utils/fifo.c b/apps/CtsVerifier/jni/audio_loopback/audio_utils/fifo.c
deleted file mode 100644
index ea9a8d1..0000000
--- a/apps/CtsVerifier/jni/audio_loopback/audio_utils/fifo.c
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "audio_utils_fifo"
-
-#include <stdlib.h>
-#include <string.h>
-#include "fifo.h"
-#include "roundup.h"
-#include "atomic.h"
-//#include <cutils/log.h>
-#define ALOG_ASSERT(exp)
-
-void audio_utils_fifo_init(struct audio_utils_fifo *fifo, size_t frameCount, size_t frameSize,
- void *buffer)
-{
- // We would need a 64-bit roundup to support larger frameCount.
- ALOG_ASSERT(fifo != NULL && frameCount > 0 && frameSize > 0 && buffer != NULL);
- fifo->mFrameCount = frameCount;
- fifo->mFrameCountP2 = roundup(frameCount);
- fifo->mFudgeFactor = fifo->mFrameCountP2 - fifo->mFrameCount;
- fifo->mFrameSize = frameSize;
- fifo->mBuffer = buffer;
- fifo->mFront = 0;
- fifo->mRear = 0;
-}
-
-void audio_utils_fifo_deinit(struct audio_utils_fifo *fifo __unused)
-{
-}
-
-// Return a new index as the sum of an old index (either mFront or mRear) and a specified increment.
-static inline int32_t audio_utils_fifo_sum(struct audio_utils_fifo *fifo, int32_t index,
- uint32_t increment)
-{
- if (fifo->mFudgeFactor) {
- uint32_t mask = fifo->mFrameCountP2 - 1;
- ALOG_ASSERT((index & mask) < fifo->mFrameCount);
- ALOG_ASSERT(/*0 <= increment &&*/ increment <= fifo->mFrameCountP2);
- if ((index & mask) + increment >= fifo->mFrameCount) {
- increment += fifo->mFudgeFactor;
- }
- index += increment;
- ALOG_ASSERT((index & mask) < fifo->mFrameCount);
- return index;
- } else {
- return index + increment;
- }
-}
-
-// Return the difference between two indices: rear - front, where 0 <= difference <= mFrameCount.
-static inline size_t audio_utils_fifo_diff(struct audio_utils_fifo *fifo, int32_t rear,
- int32_t front)
-{
- int32_t diff = rear - front;
- if (fifo->mFudgeFactor) {
- uint32_t mask = ~(fifo->mFrameCountP2 - 1);
- int32_t genDiff = (rear & mask) - (front & mask);
- if (genDiff != 0) {
- ALOG_ASSERT(genDiff == (int32_t) fifo->mFrameCountP2);
- diff -= fifo->mFudgeFactor;
- }
- }
- // FIFO should not be overfull
- ALOG_ASSERT(0 <= diff && diff <= (int32_t) fifo->mFrameCount);
- return (size_t) diff;
-}
-
-ssize_t audio_utils_fifo_write(struct audio_utils_fifo *fifo, const void *buffer, size_t count)
-{
- int32_t front = android_atomic_acquire_load(&fifo->mFront);
- int32_t rear = fifo->mRear;
- size_t availToWrite = fifo->mFrameCount - audio_utils_fifo_diff(fifo, rear, front);
- if (availToWrite > count) {
- availToWrite = count;
- }
- rear &= fifo->mFrameCountP2 - 1;
- size_t part1 = fifo->mFrameCount - rear;
- if (part1 > availToWrite) {
- part1 = availToWrite;
- }
- if (part1 > 0) {
- memcpy((char *) fifo->mBuffer + (rear * fifo->mFrameSize), buffer,
- part1 * fifo->mFrameSize);
- size_t part2 = availToWrite - part1;
- if (part2 > 0) {
- memcpy(fifo->mBuffer, (char *) buffer + (part1 * fifo->mFrameSize),
- part2 * fifo->mFrameSize);
- }
- android_atomic_release_store(audio_utils_fifo_sum(fifo, fifo->mRear, availToWrite),
- &fifo->mRear);
- }
- return availToWrite;
-}
-
-ssize_t audio_utils_fifo_read(struct audio_utils_fifo *fifo, void *buffer, size_t count)
-{
- int32_t rear = android_atomic_acquire_load(&fifo->mRear);
- int32_t front = fifo->mFront;
- size_t availToRead = audio_utils_fifo_diff(fifo, rear, front);
- if (availToRead > count) {
- availToRead = count;
- }
- front &= fifo->mFrameCountP2 - 1;
- size_t part1 = fifo->mFrameCount - front;
- if (part1 > availToRead) {
- part1 = availToRead;
- }
- if (part1 > 0) {
- memcpy(buffer, (char *) fifo->mBuffer + (front * fifo->mFrameSize),
- part1 * fifo->mFrameSize);
- size_t part2 = availToRead - part1;
- if (part2 > 0) {
- memcpy((char *) buffer + (part1 * fifo->mFrameSize), fifo->mBuffer,
- part2 * fifo->mFrameSize);
- }
- android_atomic_release_store(audio_utils_fifo_sum(fifo, fifo->mFront, availToRead),
- &fifo->mFront);
- }
- return availToRead;
-}
diff --git a/apps/CtsVerifier/jni/audio_loopback/audio_utils/fifo.h b/apps/CtsVerifier/jni/audio_loopback/audio_utils/fifo.h
deleted file mode 100644
index ba4c5c6..0000000
--- a/apps/CtsVerifier/jni/audio_loopback/audio_utils/fifo.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_AUDIO_FIFO_H
-#define ANDROID_AUDIO_FIFO_H
-
-#include <stdlib.h>
-
-// FIXME use atomic_int_least32_t and new atomic operations instead of legacy Android ones
-// #include <stdatomic.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// Single writer, single reader non-blocking FIFO.
-// Writer and reader must be in same process.
-
-// No user-serviceable parts within.
-struct audio_utils_fifo {
- // These fields are const after initialization
- size_t mFrameCount; // max number of significant frames to be stored in the FIFO > 0
- size_t mFrameCountP2; // roundup(mFrameCount)
- size_t mFudgeFactor; // mFrameCountP2 - mFrameCount, the number of "wasted" frames after
- // the end of mBuffer. Only the indices are wasted, not any memory.
- size_t mFrameSize; // size of each frame in bytes
- void *mBuffer; // pointer to caller-allocated buffer of size mFrameCount frames
-
- volatile int32_t mFront; // frame index of first frame slot available to read, or read index
- volatile int32_t mRear; // frame index of next frame slot available to write, or write index
-};
-
-// Initialize a FIFO object.
-// Input parameters:
-// fifo Pointer to the FIFO object.
-// frameCount Max number of significant frames to be stored in the FIFO > 0.
-// If writes and reads always use the same count, and that count is a divisor of
-// frameCount, then the writes and reads will never do a partial transfer.
-// frameSize Size of each frame in bytes.
-// buffer Pointer to a caller-allocated buffer of frameCount frames.
-void audio_utils_fifo_init(struct audio_utils_fifo *fifo, size_t frameCount, size_t frameSize,
- void *buffer);
-
-// De-initialize a FIFO object.
-// Input parameters:
-// fifo Pointer to the FIFO object.
-void audio_utils_fifo_deinit(struct audio_utils_fifo *fifo);
-
-// Write to FIFO.
-// Input parameters:
-// fifo Pointer to the FIFO object.
-// buffer Pointer to source buffer containing 'count' frames of data.
-// Returns actual number of frames written <= count.
-// The actual transfer count may be zero if the FIFO is full,
-// or partial if the FIFO was almost full.
-// A negative return value indicates an error. Currently there are no errors defined.
-ssize_t audio_utils_fifo_write(struct audio_utils_fifo *fifo, const void *buffer, size_t count);
-
-// Read from FIFO.
-// Input parameters:
-// fifo Pointer to the FIFO object.
-// buffer Pointer to destination buffer to be filled with up to 'count' frames of data.
-// Returns actual number of frames read <= count.
-// The actual transfer count may be zero if the FIFO is empty,
-// or partial if the FIFO was almost empty.
-// A negative return value indicates an error. Currently there are no errors defined.
-ssize_t audio_utils_fifo_read(struct audio_utils_fifo *fifo, void *buffer, size_t count);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif // !ANDROID_AUDIO_FIFO_H
diff --git a/apps/CtsVerifier/jni/audio_loopback/audio_utils/roundup.c b/apps/CtsVerifier/jni/audio_loopback/audio_utils/roundup.c
deleted file mode 100644
index 4f9af6a..0000000
--- a/apps/CtsVerifier/jni/audio_loopback/audio_utils/roundup.c
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2012 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.
- */
-
-#include "roundup.h"
-
-unsigned roundup(unsigned v)
-{
- // __builtin_clz is undefined for zero input
- if (v == 0) {
- v = 1;
- }
- int lz = __builtin_clz((int) v);
- unsigned rounded = ((unsigned) 0x80000000) >> lz;
- // 0x800000001 and higher are actually rounded _down_ to prevent overflow
- if (v > rounded && lz > 0) {
- rounded <<= 1;
- }
- return rounded;
-}
diff --git a/apps/CtsVerifier/jni/audio_loopback/jni-bridge.cpp b/apps/CtsVerifier/jni/audio_loopback/jni-bridge.cpp
new file mode 100644
index 0000000..a851cbe
--- /dev/null
+++ b/apps/CtsVerifier/jni/audio_loopback/jni-bridge.cpp
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2020 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.
+ */
+
+#include <cassert>
+#include <cstring>
+#include <jni.h>
+#include <stdint.h>
+
+#include "NativeAudioAnalyzer.h"
+
+extern "C" {
+
+JNIEXPORT jlong JNICALL Java_com_android_cts_verifier_audio_NativeAnalyzerThread_openAudio
+ (JNIEnv * /*env */, jobject /* obj */,
+ jint /* micSource */) {
+ // It is OK to use a raw pointer here because the pointer will be passed back
+ // to Java and only used from one thread.
+ // Java then deletes it from that same thread by calling _closeAudio() below.
+ NativeAudioAnalyzer * analyzer = new NativeAudioAnalyzer();
+ aaudio_result_t result = analyzer->openAudio();
+ if (result != AAUDIO_OK) {
+ delete analyzer;
+ analyzer = nullptr;
+ }
+ return (jlong) analyzer;
+}
+
+JNIEXPORT jint JNICALL Java_com_android_cts_verifier_audio_NativeAnalyzerThread_startAudio
+ (JNIEnv *env __unused, jobject obj __unused, jlong pAnalyzer) {
+ NativeAudioAnalyzer * analyzer = (NativeAudioAnalyzer *) pAnalyzer;
+ int result = AAUDIO_ERROR_NULL;
+ if (analyzer != nullptr) {
+ result = analyzer->startAudio();
+ }
+ return result;
+}
+
+JNIEXPORT jint JNICALL Java_com_android_cts_verifier_audio_NativeAnalyzerThread_stopAudio
+ (JNIEnv *env __unused, jobject obj __unused, jlong pAnalyzer) {
+ NativeAudioAnalyzer * analyzer = (NativeAudioAnalyzer *) pAnalyzer;
+ if (analyzer != nullptr) {
+ return analyzer->stopAudio();
+ }
+ return AAUDIO_ERROR_NULL;
+}
+
+JNIEXPORT jint JNICALL Java_com_android_cts_verifier_audio_NativeAnalyzerThread_closeAudio
+ (JNIEnv *env __unused, jobject obj __unused, jlong pAnalyzer) {
+ NativeAudioAnalyzer * analyzer = (NativeAudioAnalyzer *) pAnalyzer;
+ int result = AAUDIO_ERROR_NULL;
+ if (analyzer != nullptr) {
+ result = analyzer->closeAudio();
+ delete analyzer;
+ }
+ return result;
+}
+
+JNIEXPORT jboolean JNICALL Java_com_android_cts_verifier_audio_NativeAnalyzerThread_isRecordingComplete
+ (JNIEnv *env __unused, jobject obj __unused, jlong pAnalyzer) {
+ NativeAudioAnalyzer * analyzer = (NativeAudioAnalyzer *) pAnalyzer;
+ if (analyzer != nullptr) {
+ return analyzer->isRecordingComplete();
+ }
+ return false;
+}
+
+JNIEXPORT jint JNICALL Java_com_android_cts_verifier_audio_NativeAnalyzerThread_getError
+ (JNIEnv *env __unused, jobject obj __unused, jlong pAnalyzer) {
+ NativeAudioAnalyzer * analyzer = (NativeAudioAnalyzer *) pAnalyzer;
+ if (analyzer != nullptr) {
+ return (jint) analyzer->getError();
+ }
+ return (jint) AAUDIO_ERROR_NULL;
+}
+
+JNIEXPORT jint JNICALL Java_com_android_cts_verifier_audio_NativeAnalyzerThread_analyze
+ (JNIEnv *env __unused, jobject obj __unused, jlong pAnalyzer) {
+ NativeAudioAnalyzer * analyzer = (NativeAudioAnalyzer *) pAnalyzer;
+ if (analyzer != nullptr) {
+ return analyzer->analyze();
+ }
+ return AAUDIO_ERROR_NULL;
+}
+
+JNIEXPORT jdouble JNICALL Java_com_android_cts_verifier_audio_NativeAnalyzerThread_getLatencyMillis
+ (JNIEnv *env __unused, jobject obj __unused, jlong pAnalyzer) {
+ NativeAudioAnalyzer * analyzer = (NativeAudioAnalyzer *) pAnalyzer;
+ if (analyzer != nullptr) {
+ return analyzer->getLatencyMillis();
+ }
+ return -1.0;
+}
+
+JNIEXPORT jdouble JNICALL Java_com_android_cts_verifier_audio_NativeAnalyzerThread_getConfidence
+ (JNIEnv *env __unused, jobject obj __unused, jlong pAnalyzer) {
+ NativeAudioAnalyzer * analyzer = (NativeAudioAnalyzer *) pAnalyzer;
+ if (analyzer != nullptr) {
+ return analyzer->getConfidence();
+ }
+ return 0.0;
+}
+
+}
diff --git a/apps/CtsVerifier/jni/audio_loopback/jni_sles.c b/apps/CtsVerifier/jni/audio_loopback/jni_sles.c
deleted file mode 100644
index e8a837e..0000000
--- a/apps/CtsVerifier/jni/audio_loopback/jni_sles.c
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <android/log.h>
-#include "sles.h"
-#include "jni_sles.h"
-#include <stdio.h>
-#include <stddef.h>
-
-/////
-JNIEXPORT jlong JNICALL Java_com_android_cts_verifier_audio_NativeAudioThread_slesInit
- (JNIEnv *env __unused, jobject obj __unused, jint samplingRate, jint frameCount,
- jint micSource, jint numFramesToIgnore) {
-
- sles_data * pSles = NULL;
-
- if (slesInit(&pSles, samplingRate, frameCount, micSource, numFramesToIgnore) != SLES_FAIL) {
-
- return (long)pSles;
- }
- // FIXME This should be stored as a (long) field in the object,
- // so that incorrect Java code could not synthesize a bad sles pointer.
- return 0;
-}
-
-JNIEXPORT jint JNICALL Java_com_android_cts_verifier_audio_NativeAudioThread_slesProcessNext
- (JNIEnv *env __unused, jobject obj __unused, jlong sles, jdoubleArray samplesArray,
- jlong offset) {
- sles_data * pSles= (sles_data*) ((long)sles);
-
- long maxSamples = (*env)->GetArrayLength(env, samplesArray);
- double *pSamples = (*env)->GetDoubleArrayElements(env, samplesArray,0);
-
- long availableSamples = maxSamples-offset;
- double *pCurrentSample = pSamples+offset;
-
- SLES_PRINTF("jni slesProcessNext pSles:%p, currentSample %p, availableSamples %ld ", pSles,
- pCurrentSample, availableSamples);
-
- int samplesRead = slesProcessNext(pSles, pCurrentSample, availableSamples);
-
- return samplesRead;
-}
-
-JNIEXPORT jint JNICALL Java_com_android_cts_verifier_audio_NativeAudioThread_slesDestroy
- (JNIEnv *env __unused, jobject obj __unused, jlong sles) {
- sles_data * pSles= (sles_data*) ((long) sles);
-
- int status = slesDestroy(&pSles);
-
- return status;
-}
diff --git a/apps/CtsVerifier/jni/audio_loopback/jni_sles.h b/apps/CtsVerifier/jni/audio_loopback/jni_sles.h
deleted file mode 100644
index d7aa625..0000000
--- a/apps/CtsVerifier/jni/audio_loopback/jni_sles.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <jni.h>
-
-#ifndef _Included_org_drrickorang_loopback_jni
-#define _Included_org_drrickorang_loopback_jni
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-////////////////////////
-JNIEXPORT jlong JNICALL Java_com_android_cts_verifier_audio_NativeAudioThread_slesInit
- (JNIEnv *, jobject, jint, jint, jint, jint );
-
-JNIEXPORT jint JNICALL Java_com_android_cts_verifier_audio_NativeAudioThread_slesProcessNext
- (JNIEnv *, jobject , jlong, jdoubleArray, jlong );
-
-JNIEXPORT jint JNICALL Java_com_android_cts_verifier_audio_NativeAudioThread_slesDestroy
- (JNIEnv *, jobject , jlong );
-
-
-#ifdef __cplusplus
-}
-#endif
-#endif //_Included_org_drrickorang_loopback_jni
diff --git a/apps/CtsVerifier/jni/audio_loopback/sles.cpp b/apps/CtsVerifier/jni/audio_loopback/sles.cpp
deleted file mode 100644
index 586c60f..0000000
--- a/apps/CtsVerifier/jni/audio_loopback/sles.cpp
+++ /dev/null
@@ -1,673 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-////////////////////////////////////////////
-/// Actual sles functions.
-
-
-// Test program to record from default audio input and playback to default audio output.
-// It will generate feedback (Larsen effect) if played through on-device speakers,
-// or acts as a delay if played through headset.
-
-#include "sles.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <stddef.h>
-
-#include <assert.h>
-#include <pthread.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-int slesInit(sles_data ** ppSles, int samplingRate, int frameCount, int micSource,
- int numFramesToIgnore) {
- int status = SLES_FAIL;
- if (ppSles != NULL) {
- sles_data * pSles = (sles_data*) calloc(1, sizeof (sles_data));
-
- SLES_PRINTF("malloc %zu bytes at %p", sizeof(sles_data), pSles);
- *ppSles = pSles;
- if (pSles != NULL)
- {
- SLES_PRINTF("creating server. Sampling rate =%d, frame count = %d",samplingRate,
- frameCount);
- status = slesCreateServer(pSles, samplingRate, frameCount, micSource,
- numFramesToIgnore);
- SLES_PRINTF("slesCreateServer =%d", status);
- }
- }
- return status;
-}
-int slesDestroy(sles_data ** ppSles) {
- int status = SLES_FAIL;
- if (ppSles != NULL) {
- slesDestroyServer(*ppSles);
-
- if (*ppSles != NULL)
- {
- free(*ppSles);
- *ppSles = 0;
- }
- status = SLES_SUCCESS;
- }
- return status;
-}
-
-#define ASSERT_EQ(x, y) do { if ((x) == (y)) ; else { fprintf(stderr, "0x%x != 0x%x\n", \
- (unsigned) (x), (unsigned) (y)); assert((x) == (y)); } } while (0)
-
-
-// Called after audio recorder fills a buffer with data
-static void recorderCallback(SLAndroidSimpleBufferQueueItf caller __unused, void *context) {
- sles_data *pSles = (sles_data*) context;
- if (pSles != NULL) {
-
-
-
- SLresult result;
-
- pthread_mutex_lock(&(pSles->mutex));
- //ee SLES_PRINTF("<R");
-
- // We should only be called when a recording buffer is done
- assert(pSles->rxFront <= pSles->rxBufCount);
- assert(pSles->rxRear <= pSles->rxBufCount);
- assert(pSles->rxFront != pSles->rxRear);
- char *buffer = pSles->rxBuffers[pSles->rxFront];
-
- // Remove buffer from record queue
- if (++pSles->rxFront > pSles->rxBufCount) {
- pSles->rxFront = 0;
- }
-
- // Throw out first frames
- if (pSles->numFramesToIgnore) {
- SLuint32 framesToErase = pSles->numFramesToIgnore;
- if (framesToErase > pSles->bufSizeInFrames) {
- framesToErase = pSles->bufSizeInFrames;
- }
- pSles->numFramesToIgnore -= framesToErase;
- // FIXME: this assumes each sample is a short
- memset(buffer, 0, framesToErase * pSles->channels * sizeof(short));
- }
-
- ssize_t actual = audio_utils_fifo_write(&(pSles->fifo), buffer,
- (size_t) pSles->bufSizeInFrames);
- if (actual != (ssize_t) pSles->bufSizeInFrames) {
- write(1, "?", 1);
- }
-
- // This is called by a realtime (SCHED_FIFO) thread,
- // and it is unsafe to do I/O as it could block for unbounded time.
- // Flash filesystem is especially notorious for blocking.
- if (pSles->fifo2Buffer != NULL) {
- actual = audio_utils_fifo_write(&(pSles->fifo2), buffer,
- (size_t) pSles->bufSizeInFrames);
- if (actual != (ssize_t) pSles->bufSizeInFrames) {
- write(1, "?", 1);
- }
- }
-
- // Enqueue this same buffer for the recorder to fill again.
- result = (*(pSles->recorderBufferQueue))->Enqueue(pSles->recorderBufferQueue, buffer,
- pSles->bufSizeInBytes);
- ASSERT_EQ(SL_RESULT_SUCCESS, result);
-
- // Update our model of the record queue
- SLuint32 rxRearNext = pSles->rxRear+1;
- if (rxRearNext > pSles->rxBufCount) {
- rxRearNext = 0;
- }
- assert(rxRearNext != pSles->rxFront);
- pSles->rxBuffers[pSles->rxRear] = buffer;
- pSles->rxRear = rxRearNext;
-
-
-
- //ee SLES_PRINTF("r>");
- pthread_mutex_unlock(&(pSles->mutex));
-
- } //pSles not null
-}
-
-
-// Called after audio player empties a buffer of data
-static void playerCallback(SLBufferQueueItf caller __unused, void *context) {
- sles_data *pSles = (sles_data*) context;
- if (pSles != NULL) {
-
- SLresult result;
-
- pthread_mutex_lock(&(pSles->mutex));
- //ee SLES_PRINTF("<P");
-
- // Get the buffer that just finished playing
- assert(pSles->txFront <= pSles->txBufCount);
- assert(pSles->txRear <= pSles->txBufCount);
- assert(pSles->txFront != pSles->txRear);
- char *buffer = pSles->txBuffers[pSles->txFront];
- if (++pSles->txFront > pSles->txBufCount) {
- pSles->txFront = 0;
- }
-
-
- ssize_t actual = audio_utils_fifo_read(&(pSles->fifo), buffer, pSles->bufSizeInFrames);
- if (actual != (ssize_t) pSles->bufSizeInFrames) {
- write(1, "/", 1);
- // on underrun from pipe, substitute silence
- memset(buffer, 0, pSles->bufSizeInFrames * pSles->channels * sizeof(short));
- }
-
- if (pSles->injectImpulse == -1) {
- // Experimentally, a single frame impulse was insufficient to trigger feedback.
- // Also a Nyquist frequency signal was also insufficient, probably because
- // the response of output and/or input path was not adequate at high frequencies.
- // This short burst of a few cycles of square wave at Nyquist/4 was found to work well.
- for (unsigned i = 0; i < pSles->bufSizeInFrames / 8; i += 8) {
- for (int j = 0; j < 8; j++) {
- for (unsigned k = 0; k < pSles->channels; k++) {
- ((short *)buffer)[(i+j)*pSles->channels+k] = j < 4 ? 0x7FFF : 0x8000;
- }
- }
- }
- pSles->injectImpulse = 0;
- }
-
- // Enqueue the filled buffer for playing
- result = (*(pSles->playerBufferQueue))->Enqueue(pSles->playerBufferQueue, buffer,
- pSles->bufSizeInBytes);
- ASSERT_EQ(SL_RESULT_SUCCESS, result);
-
- // Update our model of the player queue
- assert(pSles->txFront <= pSles->txBufCount);
- assert(pSles->txRear <= pSles->txBufCount);
- SLuint32 txRearNext = pSles->txRear+1;
- if (txRearNext > pSles->txBufCount) {
- txRearNext = 0;
- }
- assert(txRearNext != pSles->txFront);
- pSles->txBuffers[pSles->txRear] = buffer;
- pSles->txRear = txRearNext;
-
-
- //ee SLES_PRINTF("p>");
- pthread_mutex_unlock(&(pSles->mutex));
-
- } //pSles not null
-}
-
-int slesCreateServer(sles_data *pSles, int samplingRate, int frameCount,
- int micSource, int numFramesToIgnore) {
- int status = SLES_FAIL;
-
- if (pSles == NULL) {
- return status;
- }
-
- // adb shell slesTest_feedback -r1 -t1 -s48000 -f240 -i300 -e3 -o/sdcard/log.wav
- // r1 and t1 are the receive and transmit buffer counts, typically 1
- // s is the sample rate, typically 48000 or 44100
- // f is the frame count per buffer, typically 240 or 256
- // i is the number of milliseconds before impulse. You may need to adjust this.
- // e is number of seconds to record
- // o is output .wav file name
-
-
- // // default values
- // SLuint32 rxBufCount = 1; // -r#
- // SLuint32 txBufCount = 1; // -t#
- // SLuint32 bufSizeInFrames = 240; // -f#
- // SLuint32 channels = 1; // -c#
- // SLuint32 sampleRate = 48000; // -s#
- // SLuint32 exitAfterSeconds = 3; // -e#
- // SLuint32 freeBufCount = 0; // calculated
- // SLuint32 bufSizeInBytes = 0; // calculated
- // int injectImpulse = 300; // -i#i
- //
- // // Storage area for the buffer queues
- // char **rxBuffers;
- // char **txBuffers;
- // char **freeBuffers;
- //
- // // Buffer indices
- // SLuint32 rxFront; // oldest recording
- // SLuint32 rxRear; // next to be recorded
- // SLuint32 txFront; // oldest playing
- // SLuint32 txRear; // next to be played
- // SLuint32 freeFront; // oldest free
- // SLuint32 freeRear; // next to be freed
- //
- // audio_utils_fifo fifo; //(*)
- // SLAndroidSimpleBufferQueueItf recorderBufferQueue;
- // SLBufferQueueItf playerBufferQueue;
-
- // default values
- pSles->rxBufCount = 1; // -r#
- pSles->txBufCount = 1; // -t#
- pSles->bufSizeInFrames = frameCount;//240; // -f#
- pSles->channels = 1; // -c#
- pSles->sampleRate = samplingRate;//48000; // -s#
- pSles->exitAfterSeconds = 3; // -e#
- pSles->freeBufCount = 0; // calculated
- pSles->bufSizeInBytes = 0; // calculated
- pSles->injectImpulse = 300; // -i#i
-
- if (numFramesToIgnore > 0) {
- pSles->numFramesToIgnore = numFramesToIgnore;
- } else {
- pSles->numFramesToIgnore = 0;
- }
-
- // Storage area for the buffer queues
- // char **rxBuffers;
- // char **txBuffers;
- // char **freeBuffers;
-
- // Buffer indices
-/*
- pSles->rxFront; // oldest recording
- pSles->rxRear; // next to be recorded
- pSles->txFront; // oldest playing
- pSles->txRear; // next to be played
- pSles->freeFront; // oldest free
- pSles->freeRear; // next to be freed
-
- pSles->fifo; //(*)
-*/
- pSles->fifo2Buffer = NULL;
-
- // compute total free buffers as -r plus -t
- pSles->freeBufCount = pSles->rxBufCount + pSles->txBufCount;
- // compute buffer size
- pSles->bufSizeInBytes = pSles->channels * pSles->bufSizeInFrames * sizeof(short);
-
- // Initialize free buffers
- pSles->freeBuffers = (char **) calloc(pSles->freeBufCount+1, sizeof(char *));
- unsigned j;
- for (j = 0; j < pSles->freeBufCount; ++j) {
- pSles->freeBuffers[j] = (char *) malloc(pSles->bufSizeInBytes);
- }
- pSles->freeFront = 0;
- pSles->freeRear = pSles->freeBufCount;
- pSles->freeBuffers[j] = NULL;
-
- // Initialize record queue
- pSles->rxBuffers = (char **) calloc(pSles->rxBufCount+1, sizeof(char *));
- pSles->rxFront = 0;
- pSles->rxRear = 0;
-
- // Initialize play queue
- pSles->txBuffers = (char **) calloc(pSles->txBufCount+1, sizeof(char *));
- pSles->txFront = 0;
- pSles->txRear = 0;
-
- size_t frameSize = pSles->channels * sizeof(short);
-#define FIFO_FRAMES 1024
- pSles->fifoBuffer = new short[FIFO_FRAMES * pSles->channels];
- audio_utils_fifo_init(&(pSles->fifo), FIFO_FRAMES, frameSize, pSles->fifoBuffer);
-
- // SNDFILE *sndfile;
- // if (outFileName != NULL) {
- // create .wav writer
- // SF_INFO info;
- // info.frames = 0;
- // info.samplerate = sampleRate;
- // info.channels = channels;
- // info.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16;
- // sndfile = sf_open(outFileName, SFM_WRITE, &info);
- // if (sndfile != NULL) {
-#define FIFO2_FRAMES 65536
- pSles->fifo2Buffer = new short[FIFO2_FRAMES * pSles->channels];
- audio_utils_fifo_init(&(pSles->fifo2), FIFO2_FRAMES, frameSize, pSles->fifo2Buffer);
- // } else {
- // fprintf(stderr, "sf_open failed\n");
- // }
- // } else {
- // sndfile = NULL;
- // }
-
- SLresult result;
-
- // create engine
- result = slCreateEngine(&(pSles->engineObject), 0, NULL, 0, NULL, NULL);
- ASSERT_EQ(SL_RESULT_SUCCESS, result);
- result = (*(pSles->engineObject))->Realize(pSles->engineObject, SL_BOOLEAN_FALSE);
- ASSERT_EQ(SL_RESULT_SUCCESS, result);
- SLEngineItf engineEngine;
- result = (*(pSles->engineObject))->GetInterface(pSles->engineObject, SL_IID_ENGINE,
- &engineEngine);
- ASSERT_EQ(SL_RESULT_SUCCESS, result);
-
- // create output mix
- result = (*engineEngine)->CreateOutputMix(engineEngine, &(pSles->outputmixObject), 0, NULL,
- NULL);
- ASSERT_EQ(SL_RESULT_SUCCESS, result);
- result = (*(pSles->outputmixObject))->Realize(pSles->outputmixObject, SL_BOOLEAN_FALSE);
- ASSERT_EQ(SL_RESULT_SUCCESS, result);
-
- // create an audio player with buffer queue source and output mix sink
- SLDataSource audiosrc;
- SLDataSink audiosnk;
- SLDataFormat_PCM pcm;
- SLDataLocator_OutputMix locator_outputmix;
- SLDataLocator_BufferQueue locator_bufferqueue_tx;
- locator_bufferqueue_tx.locatorType = SL_DATALOCATOR_BUFFERQUEUE;
- locator_bufferqueue_tx.numBuffers = pSles->txBufCount;
- locator_outputmix.locatorType = SL_DATALOCATOR_OUTPUTMIX;
- locator_outputmix.outputMix = pSles->outputmixObject;
- pcm.formatType = SL_DATAFORMAT_PCM;
- pcm.numChannels = pSles->channels;
- pcm.samplesPerSec = pSles->sampleRate * 1000;
- pcm.bitsPerSample = SL_PCMSAMPLEFORMAT_FIXED_16;
- pcm.containerSize = 16;
- pcm.channelMask = pSles->channels == 1 ? SL_SPEAKER_FRONT_CENTER :
- (SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT);
- pcm.endianness = SL_BYTEORDER_LITTLEENDIAN;
- audiosrc.pLocator = &locator_bufferqueue_tx;
- audiosrc.pFormat = &pcm;
- audiosnk.pLocator = &locator_outputmix;
- audiosnk.pFormat = NULL;
- pSles->playerObject = NULL;
- pSles->recorderObject = NULL;
- SLInterfaceID ids_tx[1] = {SL_IID_BUFFERQUEUE};
- SLboolean flags_tx[1] = {SL_BOOLEAN_TRUE};
- result = (*engineEngine)->CreateAudioPlayer(engineEngine, &(pSles->playerObject),
- &audiosrc, &audiosnk, 1, ids_tx, flags_tx);
- if (SL_RESULT_CONTENT_UNSUPPORTED == result) {
- fprintf(stderr, "Could not create audio player (result %x), check sample rate\n",
- result);
- SLES_PRINTF("ERROR: Could not create audio player (result %x), check sample rate\n",
- result);
- goto cleanup;
- }
- ASSERT_EQ(SL_RESULT_SUCCESS, result);
- result = (*(pSles->playerObject))->Realize(pSles->playerObject, SL_BOOLEAN_FALSE);
- ASSERT_EQ(SL_RESULT_SUCCESS, result);
- SLPlayItf playerPlay;
- result = (*(pSles->playerObject))->GetInterface(pSles->playerObject, SL_IID_PLAY,
- &playerPlay);
- ASSERT_EQ(SL_RESULT_SUCCESS, result);
- result = (*(pSles->playerObject))->GetInterface(pSles->playerObject, SL_IID_BUFFERQUEUE,
- &(pSles->playerBufferQueue));
- ASSERT_EQ(SL_RESULT_SUCCESS, result);
- result = (*(pSles->playerBufferQueue))->RegisterCallback(pSles->playerBufferQueue,
- playerCallback, pSles);
- ASSERT_EQ(SL_RESULT_SUCCESS, result);
-
- // Enqueue some zero buffers for the player
- for (j = 0; j < pSles->txBufCount; ++j) {
-
- // allocate a free buffer
- assert(pSles->freeFront != pSles->freeRear);
- char *buffer = pSles->freeBuffers[pSles->freeFront];
- if (++pSles->freeFront > pSles->freeBufCount) {
- pSles->freeFront = 0;
- }
-
- // put on play queue
- SLuint32 txRearNext = pSles->txRear + 1;
- if (txRearNext > pSles->txBufCount) {
- txRearNext = 0;
- }
- assert(txRearNext != pSles->txFront);
- pSles->txBuffers[pSles->txRear] = buffer;
- pSles->txRear = txRearNext;
- result = (*(pSles->playerBufferQueue))->Enqueue(pSles->playerBufferQueue,
- buffer, pSles->bufSizeInBytes);
- ASSERT_EQ(SL_RESULT_SUCCESS, result);
- }
-
- result = (*playerPlay)->SetPlayState(playerPlay, SL_PLAYSTATE_PLAYING);
- ASSERT_EQ(SL_RESULT_SUCCESS, result);
-
- // Create an audio recorder with microphone device source and buffer queue sink.
- // The buffer queue as sink is an Android-specific extension.
-
- SLDataLocator_IODevice locator_iodevice;
- SLDataLocator_AndroidSimpleBufferQueue locator_bufferqueue_rx;
- locator_iodevice.locatorType = SL_DATALOCATOR_IODEVICE;
- locator_iodevice.deviceType = SL_IODEVICE_AUDIOINPUT;
- locator_iodevice.deviceID = SL_DEFAULTDEVICEID_AUDIOINPUT;
- locator_iodevice.device = NULL;
- audiosrc.pLocator = &locator_iodevice;
- audiosrc.pFormat = NULL;
- locator_bufferqueue_rx.locatorType = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE;
- locator_bufferqueue_rx.numBuffers = pSles->rxBufCount;
- audiosnk.pLocator = &locator_bufferqueue_rx;
- audiosnk.pFormat = &pcm;
- {
- SLInterfaceID ids_rx[2] = {SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
- SL_IID_ANDROIDCONFIGURATION};
- SLboolean flags_rx[2] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
- result = (*engineEngine)->CreateAudioRecorder(engineEngine, &(pSles->recorderObject),
- &audiosrc, &audiosnk, 2, ids_rx, flags_rx);
- if (SL_RESULT_SUCCESS != result) {
- fprintf(stderr, "Could not create audio recorder (result %x), "
- "check sample rate and channel count\n", result);
- status = SLES_FAIL;
-
- SLES_PRINTF("ERROR: Could not create audio recorder (result %x), "
- "check sample rate and channel count\n", result);
- goto cleanup;
- }
- }
- ASSERT_EQ(SL_RESULT_SUCCESS, result);
-
- {
- /* Get the Android configuration interface which is explicit */
- SLAndroidConfigurationItf configItf;
- result = (*(pSles->recorderObject))->GetInterface(pSles->recorderObject,
- SL_IID_ANDROIDCONFIGURATION, (void*)&configItf);
- ASSERT_EQ(SL_RESULT_SUCCESS, result);
- SLuint32 presetValue = micSource;
- /* Use the configuration interface to configure the recorder before it's realized */
- if (presetValue != SL_ANDROID_RECORDING_PRESET_NONE) {
- result = (*configItf)->SetConfiguration(configItf, SL_ANDROID_KEY_RECORDING_PRESET,
- &presetValue, sizeof(SLuint32));
- ASSERT_EQ(SL_RESULT_SUCCESS, result);
- }
-
- }
-
- result = (*(pSles->recorderObject))->Realize(pSles->recorderObject, SL_BOOLEAN_FALSE);
- ASSERT_EQ(SL_RESULT_SUCCESS, result);
- SLRecordItf recorderRecord;
- result = (*(pSles->recorderObject))->GetInterface(pSles->recorderObject, SL_IID_RECORD,
- &recorderRecord);
- ASSERT_EQ(SL_RESULT_SUCCESS, result);
- result = (*(pSles->recorderObject))->GetInterface(pSles->recorderObject,
- SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &(pSles->recorderBufferQueue));
- ASSERT_EQ(SL_RESULT_SUCCESS, result);
- result = (*(pSles->recorderBufferQueue))->RegisterCallback(pSles->recorderBufferQueue,
- recorderCallback, pSles);
- ASSERT_EQ(SL_RESULT_SUCCESS, result);
-
- // Enqueue some empty buffers for the recorder
- for (j = 0; j < pSles->rxBufCount; ++j) {
-
- // allocate a free buffer
- assert(pSles->freeFront != pSles->freeRear);
- char *buffer = pSles->freeBuffers[pSles->freeFront];
- if (++pSles->freeFront > pSles->freeBufCount) {
- pSles->freeFront = 0;
- }
-
- // put on record queue
- SLuint32 rxRearNext = pSles->rxRear + 1;
- if (rxRearNext > pSles->rxBufCount) {
- rxRearNext = 0;
- }
- assert(rxRearNext != pSles->rxFront);
- pSles->rxBuffers[pSles->rxRear] = buffer;
- pSles->rxRear = rxRearNext;
- result = (*(pSles->recorderBufferQueue))->Enqueue(pSles->recorderBufferQueue,
- buffer, pSles->bufSizeInBytes);
- ASSERT_EQ(SL_RESULT_SUCCESS, result);
- }
-
- // Kick off the recorder
- result = (*recorderRecord)->SetRecordState(recorderRecord, SL_RECORDSTATE_RECORDING);
- ASSERT_EQ(SL_RESULT_SUCCESS, result);
-
- // Tear down the objects and exit
- status = SLES_SUCCESS;
- cleanup:
- SLES_PRINTF("Finished initialization with status: %d", status);
-
- return status;
-}
-
-int slesProcessNext(sles_data *pSles, double *pSamples, long maxSamples) {
- //int status = SLES_FAIL;
-
- SLES_PRINTF("slesProcessNext: pSles = %p, currentSample: %p, maxSamples = %ld", pSles,
- pSamples, maxSamples);
-
- int samplesRead = 0;
-
- int currentSample = 0;
- double *pCurrentSample = pSamples;
- int maxValue = 32768;
-
- if (pSles == NULL) {
- return samplesRead;
- }
-
- SLresult result;
- for (int i = 0; i < 10; i++) {
- usleep(100000);
- if (pSles->fifo2Buffer != NULL) {
- for (;;) {
- short buffer[pSles->bufSizeInFrames * pSles->channels];
- ssize_t actual = audio_utils_fifo_read(&(pSles->fifo2), buffer,
- pSles->bufSizeInFrames);
- if (actual <= 0)
- break;
- {
- for (int jj =0; jj<actual && currentSample < maxSamples; jj++) {
- *(pCurrentSample++) = ((double)buffer[jj])/maxValue;
- currentSample++;
- }
- }
- samplesRead +=actual;
- }
- }
- if (pSles->injectImpulse > 0) {
- if (pSles->injectImpulse <= 100) {
- pSles->injectImpulse = -1;
- write(1, "I", 1);
- } else {
- if ((pSles->injectImpulse % 1000) < 100) {
- write(1, "i", 1);
- }
- pSles->injectImpulse -= 100;
- }
- } else if (i == 9) {
- write(1, ".", 1);
- }
- }
- SLBufferQueueState playerBQState;
- result = (*(pSles->playerBufferQueue))->GetState(pSles->playerBufferQueue,
- &playerBQState);
- ASSERT_EQ(SL_RESULT_SUCCESS, result);
- SLAndroidSimpleBufferQueueState recorderBQState;
- result = (*(pSles->recorderBufferQueue))->GetState(pSles->recorderBufferQueue,
- &recorderBQState);
- ASSERT_EQ(SL_RESULT_SUCCESS, result);
-
- SLES_PRINTF("End of slesProcessNext: pSles = %p, samplesRead = %d, maxSamples= %ld", pSles,
- samplesRead, maxSamples);
-
- return samplesRead;
-}
-
-int slesDestroyServer(sles_data *pSles) {
- int status = SLES_FAIL;
-
- SLES_PRINTF("Start slesDestroyServer: pSles = %p", pSles);
- if (pSles == NULL) {
- return status;
- }
-
- if (NULL != pSles->playerObject) {
-
- SLES_PRINTF("stopping player...");
- SLPlayItf playerPlay;
- SLresult result = (*(pSles->playerObject))->GetInterface(pSles->playerObject,
- SL_IID_PLAY, &playerPlay);
-
- ASSERT_EQ(SL_RESULT_SUCCESS, result);
-
- //stop player and recorder if they exist
- result = (*playerPlay)->SetPlayState(playerPlay, SL_PLAYSTATE_STOPPED);
- ASSERT_EQ(SL_RESULT_SUCCESS, result);
- }
-
- if (NULL != pSles->recorderObject) {
- SLES_PRINTF("stopping recorder...");
- SLRecordItf recorderRecord;
- SLresult result = (*(pSles->recorderObject))->GetInterface(pSles->recorderObject,
- SL_IID_RECORD, &recorderRecord);
- ASSERT_EQ(SL_RESULT_SUCCESS, result);
-
- result = (*recorderRecord)->SetRecordState(recorderRecord, SL_RECORDSTATE_STOPPED);
- ASSERT_EQ(SL_RESULT_SUCCESS, result);
- }
-
- usleep(1000);
-
- audio_utils_fifo_deinit(&(pSles->fifo));
- delete[] pSles->fifoBuffer;
-
- SLES_PRINTF("slesDestroyServer 2");
-
- // if (sndfile != NULL) {
- audio_utils_fifo_deinit(&(pSles->fifo2));
- delete[] pSles->fifo2Buffer;
-
- SLES_PRINTF("slesDestroyServer 3");
-
- // sf_close(sndfile);
- // }
- if (NULL != pSles->playerObject) {
- (*(pSles->playerObject))->Destroy(pSles->playerObject);
- }
-
- SLES_PRINTF("slesDestroyServer 4");
-
- if (NULL != pSles->recorderObject) {
- (*(pSles->recorderObject))->Destroy(pSles->recorderObject);
- }
-
- SLES_PRINTF("slesDestroyServer 5");
-
- (*(pSles->outputmixObject))->Destroy(pSles->outputmixObject);
- SLES_PRINTF("slesDestroyServer 6");
- (*(pSles->engineObject))->Destroy(pSles->engineObject);
- SLES_PRINTF("slesDestroyServer 7");
-
- // free(pSles);
- // pSles=NULL;
-
- status = SLES_SUCCESS;
-
- SLES_PRINTF("End slesDestroyServer: status = %d", status);
- return status;
-}
-
diff --git a/apps/CtsVerifier/jni/audio_loopback/sles.h b/apps/CtsVerifier/jni/audio_loopback/sles.h
deleted file mode 100644
index 607f724..0000000
--- a/apps/CtsVerifier/jni/audio_loopback/sles.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <SLES/OpenSLES.h>
-#include <SLES/OpenSLES_Android.h>
-#include <pthread.h>
-#include <android/log.h>
-
-#ifndef _Included_org_drrickorang_loopback_sles
-#define _Included_org_drrickorang_loopback_sles
-
-//struct audio_utils_fifo;
-#define SLES_PRINTF(...) __android_log_print(ANDROID_LOG_INFO, "sles_jni", __VA_ARGS__);
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-#include <audio_utils/fifo.h>
-
-typedef struct {
- SLuint32 rxBufCount; // -r#
- SLuint32 txBufCount; // -t#
- SLuint32 bufSizeInFrames; // -f#
- SLuint32 channels; // -c#
- SLuint32 sampleRate; // -s#
- SLuint32 exitAfterSeconds; // -e#
- SLuint32 freeBufCount; // calculated
- SLuint32 bufSizeInBytes; // calculated
- int injectImpulse; // -i#i
- SLuint32 numFramesToIgnore;
-
- // Storage area for the buffer queues
- char **rxBuffers;
- char **txBuffers;
- char **freeBuffers;
-
- // Buffer indices
- SLuint32 rxFront; // oldest recording
- SLuint32 rxRear; // next to be recorded
- SLuint32 txFront; // oldest playing
- SLuint32 txRear; // next to be played
- SLuint32 freeFront; // oldest free
- SLuint32 freeRear; // next to be freed
-
- struct audio_utils_fifo fifo; //(*)
- struct audio_utils_fifo fifo2;
- short *fifo2Buffer;
- short *fifoBuffer;
- SLAndroidSimpleBufferQueueItf recorderBufferQueue;
- SLBufferQueueItf playerBufferQueue;
-
- pthread_mutex_t mutex;// = PTHREAD_MUTEX_INITIALIZER;
-
- //other things that belong here
- SLObjectItf playerObject;
- SLObjectItf recorderObject;
- SLObjectItf outputmixObject;
- SLObjectItf engineObject;
-} sles_data;
-
-enum {
- SLES_SUCCESS = 0,
- SLES_FAIL = 1,
-} SLES_STATUS_ENUM;
-
-int slesInit(sles_data ** ppSles, int samplingRate, int frameCount,
- int micSource, int numFramesToIgnore);
-
-//note the double pointer to properly free the memory of the structure
-int slesDestroy(sles_data ** ppSles);
-
-///full
-int slesFull(sles_data *pSles);
-
-int slesCreateServer(sles_data *pSles, int samplingRate, int frameCount, int micSource, int numFramesToIgnore);
-int slesProcessNext(sles_data *pSles, double *pSamples, long maxSamples);
-int slesDestroyServer(sles_data *pSles);
-
-#ifdef __cplusplus
-}
-#endif
-#endif //_Included_org_drrickorang_loopback_sles
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioLoopbackActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioLoopbackActivity.java
index f5cf4e1..5c3fa9f 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioLoopbackActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioLoopbackActivity.java
@@ -27,6 +27,7 @@
import android.media.AudioDeviceInfo;
import android.media.AudioManager;
import android.media.AudioTrack;
+import android.media.MediaRecorder;
import android.os.Bundle;
import android.os.Handler;
@@ -51,15 +52,14 @@
public static final int BYTES_PER_FRAME = 2;
- NativeAudioThread nativeAudioThread = null;
+ NativeAnalyzerThread mNativeAnalyzerThread = null;
private int mSamplingRate = 44100;
private int mMinBufferSizeInFrames = 0;
private static final double CONFIDENCE_THRESHOLD = 0.6;
- private Correlation mCorrelation = new Correlation();
- // TODO: remove this variable
- private int mNumFramesToIgnore = 0;
+ private double mLatencyMillis;
+ private double mConfidence;
OnBtnClickListener mBtnClickListener = new OnBtnClickListener();
Context mContext;
@@ -92,13 +92,13 @@
case R.id.audio_general_headset_yes:
Log.i(TAG, "User confirms Headset Port existence");
mLoopbackPlugReady.setEnabled(true);
- recordHeasetPortFound(true);
+ recordHeadsetPortFound(true);
mHeadsetPortYes.setEnabled(false);
mHeadsetPortNo.setEnabled(false);
break;
case R.id.audio_general_headset_no:
Log.i(TAG, "User denies Headset Port existence");
- recordHeasetPortFound(false);
+ recordHeadsetPortFound(false);
getPassButton().setEnabled(true);
mHeadsetPortYes.setEnabled(false);
mHeadsetPortNo.setEnabled(false);
@@ -161,6 +161,7 @@
setPassFailButtonClickListeners();
getPassButton().setEnabled(false);
setInfoResources(R.string.audio_loopback_test, R.string.audio_loopback_info, -1);
+
}
/**
@@ -204,41 +205,43 @@
*/
private void startAudioTest() {
getPassButton().setEnabled(false);
+ mTestButton.setEnabled(false);
+ mLatencyMillis = 0.0;
+ mConfidence = 0.0;
- //get system defaults for sampling rate, buffers.
- AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
- String value = am.getProperty(AudioManager.PROPERTY_OUTPUT_FRAMES_PER_BUFFER);
- mMinBufferSizeInFrames = Integer.parseInt(value);
-
- int minBufferSizeInBytes = BYTES_PER_FRAME * mMinBufferSizeInFrames;
-
- mSamplingRate = AudioTrack.getNativeOutputSampleRate(AudioManager.STREAM_MUSIC);
-
- Log.i(TAG, String.format("startAudioTest sr:%d , buffer:%d frames",
- mSamplingRate, mMinBufferSizeInFrames));
-
- nativeAudioThread = new NativeAudioThread();
- if (nativeAudioThread != null) {
- nativeAudioThread.setMessageHandler(mMessageHandler);
- nativeAudioThread.mSessionId = 0;
- nativeAudioThread.setParams(mSamplingRate,
- minBufferSizeInBytes,
- minBufferSizeInBytes,
- 0x03 /*voice recognition*/,
- mNumFramesToIgnore);
- nativeAudioThread.start();
+ mNativeAnalyzerThread = new NativeAnalyzerThread();
+ if (mNativeAnalyzerThread != null) {
+ mNativeAnalyzerThread.setMessageHandler(mMessageHandler);
+ // This value matches AAUDIO_INPUT_PRESET_VOICE_RECOGNITION
+ mNativeAnalyzerThread.setInputPreset(MediaRecorder.AudioSource.VOICE_RECOGNITION);
+ mNativeAnalyzerThread.startTest();
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
-
- nativeAudioThread.runTest();
-
}
}
+ private void handleTestCompletion() {
+ recordTestResults();
+ boolean resultValid = mConfidence >= CONFIDENCE_THRESHOLD
+ && mLatencyMillis > 1.0;
+ getPassButton().setEnabled(resultValid);
+
+ // Make sure the test thread is finished. It should already be done.
+ if (mNativeAnalyzerThread != null) {
+ try {
+ mNativeAnalyzerThread.stopTest(2 * 1000);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ showWait(false);
+ mTestButton.setEnabled(true);
+ }
+
/**
* handler for messages from audio thread
*/
@@ -246,45 +249,35 @@
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch(msg.what) {
- case NativeAudioThread.NATIVE_AUDIO_THREAD_MESSAGE_REC_STARTED:
+ case NativeAnalyzerThread.NATIVE_AUDIO_THREAD_MESSAGE_REC_STARTED:
Log.v(TAG,"got message native rec started!!");
showWait(true);
mResultText.setText("Test Running...");
break;
- case NativeAudioThread.NATIVE_AUDIO_THREAD_MESSAGE_REC_ERROR:
+ case NativeAnalyzerThread.NATIVE_AUDIO_THREAD_MESSAGE_OPEN_ERROR:
Log.v(TAG,"got message native rec can't start!!");
- showWait(false);
- mResultText.setText("Test Error.");
+ mResultText.setText("Test Error opening streams.");
+ handleTestCompletion();
break;
- case NativeAudioThread.NATIVE_AUDIO_THREAD_MESSAGE_REC_COMPLETE:
- case NativeAudioThread.NATIVE_AUDIO_THREAD_MESSAGE_REC_COMPLETE_ERRORS:
- if (nativeAudioThread != null) {
- Log.v(TAG,"Finished recording.");
- double [] waveData = nativeAudioThread.getWaveData();
- mCorrelation.computeCorrelation(waveData, mSamplingRate);
- mResultText.setText(String.format(
- "Test Finished\nLatency:%.2f ms\nConfidence: %.2f",
- mCorrelation.mEstimatedLatencyMs,
- mCorrelation.mEstimatedLatencyConfidence));
-
- recordTestResults();
- if (mCorrelation.mEstimatedLatencyConfidence >= CONFIDENCE_THRESHOLD) {
- getPassButton().setEnabled(true);
- }
-
- //close
- if (nativeAudioThread != null) {
- nativeAudioThread.isRunning = false;
- try {
- nativeAudioThread.finish();
- nativeAudioThread.join();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- nativeAudioThread = null;
- }
- showWait(false);
+ case NativeAnalyzerThread.NATIVE_AUDIO_THREAD_MESSAGE_REC_ERROR:
+ Log.v(TAG,"got message native rec can't start!!");
+ mResultText.setText("Test Error while recording.");
+ handleTestCompletion();
+ break;
+ case NativeAnalyzerThread.NATIVE_AUDIO_THREAD_MESSAGE_REC_COMPLETE_ERRORS:
+ mResultText.setText("Test FAILED due to errors.");
+ handleTestCompletion();
+ break;
+ case NativeAnalyzerThread.NATIVE_AUDIO_THREAD_MESSAGE_REC_COMPLETE:
+ if (mNativeAnalyzerThread != null) {
+ mLatencyMillis = mNativeAnalyzerThread.getLatencyMillis();
+ mConfidence = mNativeAnalyzerThread.getConfidence();
}
+ mResultText.setText(String.format(
+ "Test Finished\nLatency:%.2f ms\nConfidence: %.2f",
+ mLatencyMillis,
+ mConfidence));
+ handleTestCompletion();
break;
default:
break;
@@ -299,13 +292,13 @@
getReportLog().addValue(
"Estimated Latency",
- mCorrelation.mEstimatedLatencyMs,
+ mLatencyMillis,
ResultType.LOWER_BETTER,
ResultUnit.MS);
getReportLog().addValue(
"Confidence",
- mCorrelation.mEstimatedLatencyConfidence,
+ mConfidence,
ResultType.HIGHER_BETTER,
ResultUnit.NONE);
@@ -331,7 +324,7 @@
Log.v(TAG,"Results Recorded");
}
- private void recordHeasetPortFound(boolean found) {
+ private void recordHeadsetPortFound(boolean found) {
getReportLog().addValue(
"User Reported Headset Port",
found ? 1.0 : 0,
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/Correlation.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/Correlation.java
deleted file mode 100644
index c653d1d..0000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/Correlation.java
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.cts.verifier.audio;
-
-import android.util.Log;
-
-
-public class Correlation {
-
- private int mBlockSize = 4096;
- private int mSamplingRate = 44100;
- private double [] mDataDownsampled = new double [mBlockSize];
- private double [] mDataAutocorrelated = new double[mBlockSize];
-
- public double mEstimatedLatencySamples = 0;
- public double mEstimatedLatencyMs = 0;
- public double mEstimatedLatencyConfidence = 0.0;
-
- private double mAmplitudeThreshold = 0.001; // 0.001 = -60 dB noise
-
- public void init(int blockSize, int samplingRate) {
- mBlockSize = blockSize;
- mSamplingRate = samplingRate;
- }
-
- public boolean computeCorrelation(double [] data, int samplingRate) {
- boolean status = false;
- log("Started Auto Correlation for data with " + data.length + " points");
- mSamplingRate = samplingRate;
-
- downsampleData(data, mDataDownsampled, mAmplitudeThreshold);
-
- //correlation vector
- autocorrelation(mDataDownsampled, mDataAutocorrelated);
-
- int N = data.length; //all samples available
- double groupSize = (double) N / mBlockSize; //samples per downsample point.
-
- double maxValue = 0;
- int maxIndex = -1;
-
- double minLatencyMs = 8; //min latency expected. This algorithm should be improved.
- int minIndex = (int)(0.5 + minLatencyMs * mSamplingRate / (groupSize*1000));
-
- double average = 0;
- double rms = 0;
- //find max
- for (int i=minIndex; i<mDataAutocorrelated.length; i++) {
- average += mDataAutocorrelated[i];
- rms += mDataAutocorrelated[i]*mDataAutocorrelated[i];
- if (mDataAutocorrelated[i] > maxValue) {
- maxValue = mDataAutocorrelated[i];
- maxIndex = i;
- }
- }
-
- rms = Math.sqrt(rms/mDataAutocorrelated.length);
- average = average/mDataAutocorrelated.length;
- log(String.format(" Maxvalue %f, max Index : %d/%d (%d) minIndex=%d",maxValue, maxIndex,
- mDataAutocorrelated.length, data.length, minIndex));
-
- log(String.format(" average : %.3f rms: %.3f", average, rms));
-
- mEstimatedLatencyConfidence = 0.0;
- if (average>0) {
- double factor = 3.0;
-
- double raw = (rms-average) /(factor*average);
- log(String.format("Raw: %.3f",raw));
- mEstimatedLatencyConfidence = Math.max(Math.min(raw, 1.0),0.0);
- }
-
- log(String.format(" ****Confidence: %.2f",mEstimatedLatencyConfidence));
-
- mEstimatedLatencySamples = maxIndex*groupSize;
-
- mEstimatedLatencyMs = mEstimatedLatencySamples *1000/mSamplingRate;
-
- log(String.format(" latencySamples: %.2f %.2f ms", mEstimatedLatencySamples,
- mEstimatedLatencyMs));
-
- status = true;
- return status;
- }
-
- private boolean downsampleData(double [] data, double [] dataDownsampled, double threshold) {
-
- boolean status = false;
- // mDataDownsampled = new double[mBlockSize];
- for (int i=0; i<mBlockSize; i++) {
- dataDownsampled[i] = 0;
- }
-
- int N = data.length; //all samples available
- double groupSize = (double) N / mBlockSize;
-
- int ignored = 0;
-
- int currentIndex = 0;
- double nextGroup = groupSize;
- for (int i = 0; i<N && currentIndex<mBlockSize; i++) {
-
- if (i> nextGroup) { //advanced to next group.
- currentIndex++;
- nextGroup += groupSize;
- }
-
- if (currentIndex>=mBlockSize) {
- break;
- }
-
- double value = Math.abs(data[i]);
- if (value >= threshold) {
- dataDownsampled[currentIndex] += value;
- } else {
- ignored++;
- }
- }
-
- log(String.format(" Threshold: %.3f, ignored:%d/%d (%.2f)", threshold, ignored, N,
- (double) ignored/(double)N));
-
- status = true;
- return status;
- }
-
- private boolean autocorrelation(double [] data, double [] dataOut) {
- boolean status = false;
-
- double sumsquared = 0;
- int N = data.length;
- for (int i=0; i<N; i++) {
- double value = data[i];
- sumsquared += value*value;
- }
-
- if (sumsquared>0) {
- for (int i = 0; i < N; i++) {
- dataOut[i] = 0;
- for (int j = 0; j < N - i; j++) {
-
- dataOut[i] += data[j] * data[i + j];
- }
- dataOut[i] = dataOut[i] / sumsquared;
- }
- status = true;
- }
-
- return status;
- }
-
- private static void log(String msg) {
- Log.v("Recorder", msg);
- }
-}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/NativeAnalyzerThread.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/NativeAnalyzerThread.java
new file mode 100644
index 0000000..42f22aa
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/NativeAnalyzerThread.java
@@ -0,0 +1,187 @@
+/*
+ * 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.
+ */
+
+
+package com.android.cts.verifier.audio;
+
+import android.media.AudioFormat;
+import android.media.AudioManager;
+import android.media.AudioTrack;
+import android.media.MediaRecorder;
+import android.media.AudioRecord;
+import android.media.MediaRecorder;
+import android.util.Log;
+
+import android.os.Handler;
+import android.os.Message;
+
+/**
+ * A thread that runs a native audio loopback analyzer.
+ */
+public class NativeAnalyzerThread {
+ private final int mSecondsToRun = 5;
+ private Handler mMessageHandler;
+ private Thread mThread;
+ private volatile boolean mEnabled = false;
+ private volatile double mLatencyMillis = 0.0;
+ private volatile double mConfidence = 0.0;
+ private int mInputPreset = 0;
+
+ static final int NATIVE_AUDIO_THREAD_MESSAGE_REC_STARTED = 892;
+ static final int NATIVE_AUDIO_THREAD_MESSAGE_OPEN_ERROR = 893;
+ static final int NATIVE_AUDIO_THREAD_MESSAGE_REC_ERROR = 894;
+ static final int NATIVE_AUDIO_THREAD_MESSAGE_REC_COMPLETE = 895;
+ static final int NATIVE_AUDIO_THREAD_MESSAGE_REC_COMPLETE_ERRORS = 896;
+
+ public void setInputPreset(int inputPreset) {
+ mInputPreset = inputPreset;
+ }
+
+ //JNI load
+ static {
+ try {
+ System.loadLibrary("audioloopback_jni");
+ } catch (UnsatisfiedLinkError e) {
+ log("Error loading loopback JNI library");
+ e.printStackTrace();
+ }
+
+ /* TODO: gracefully fail/notify if the library can't be loaded */
+ }
+
+ /**
+ * @return native audio context
+ */
+ private native long openAudio(int micSource);
+ private native int startAudio(long audio_context);
+ private native int stopAudio(long audio_context);
+ private native int closeAudio(long audio_context);
+ private native int getError(long audio_context);
+ private native boolean isRecordingComplete(long audio_context);
+ private native int analyze(long audio_context);
+ private native double getLatencyMillis(long audio_context);
+ private native double getConfidence(long audio_context);
+
+ public double getLatencyMillis() {
+ return mLatencyMillis;
+ }
+
+ public double getConfidence() {
+ return mConfidence;
+ }
+
+ public synchronized void startTest() {
+ if (mThread == null) {
+ mEnabled = true;
+ mThread = new Thread(mBackGroundTask);
+ mThread.start();
+ }
+ }
+
+ public synchronized void stopTest(int millis) throws InterruptedException {
+ mEnabled = false;
+ if (mThread != null) {
+ mThread.interrupt();
+ mThread.join(millis);
+ mThread = null;
+ }
+ }
+
+ private void sendMessage(int what) {
+ if (mMessageHandler != null) {
+ Message msg = Message.obtain();
+ msg.what = what;
+ mMessageHandler.sendMessage(msg);
+ }
+ }
+
+ private Runnable mBackGroundTask = () -> {
+ mLatencyMillis = 0.0;
+ mConfidence = 0.0;
+ boolean analysisComplete = false;
+
+ log(" Started capture test");
+ sendMessage(NATIVE_AUDIO_THREAD_MESSAGE_REC_STARTED);
+
+ long audioContext = openAudio(mInputPreset);
+ log(String.format("audioContext = 0x%X",audioContext));
+
+ if (audioContext == 0 ) {
+ log(" ERROR at JNI initialization");
+ sendMessage(NATIVE_AUDIO_THREAD_MESSAGE_OPEN_ERROR);
+ } else if (mEnabled) {
+ int result = startAudio(audioContext);
+ if (result < 0) {
+ sendMessage(NATIVE_AUDIO_THREAD_MESSAGE_REC_ERROR);
+ mEnabled = false;
+ }
+
+ final long timeoutMillis = mSecondsToRun * 1000;
+ final long startedAtMillis = System.currentTimeMillis();
+ boolean timedOut = false;
+ int loopCounter = 0;
+ while (mEnabled && !timedOut) {
+ result = getError(audioContext);
+ if (result < 0) {
+ sendMessage(NATIVE_AUDIO_THREAD_MESSAGE_REC_ERROR);
+ break;
+ } else if (isRecordingComplete(audioContext)) {
+ result = stopAudio(audioContext);
+ if (result < 0) {
+ sendMessage(NATIVE_AUDIO_THREAD_MESSAGE_REC_ERROR);
+ break;
+ }
+
+ // Analyze the recording and measure latency.
+ mThread.setPriority(Thread.MAX_PRIORITY);
+ result = analyze(audioContext);
+ if (result < 0) {
+ break;
+ } else {
+ analysisComplete = true;
+ }
+ mLatencyMillis = getLatencyMillis(audioContext);
+ mConfidence = getConfidence(audioContext);
+ break;
+ } else {
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ long now = System.currentTimeMillis();
+ timedOut = (now - startedAtMillis) > timeoutMillis;
+ }
+ log("latency: analyze returns " + result);
+ closeAudio(audioContext);
+
+ int what = (analysisComplete && result == 0)
+ ? NATIVE_AUDIO_THREAD_MESSAGE_REC_COMPLETE
+ : NATIVE_AUDIO_THREAD_MESSAGE_REC_COMPLETE_ERRORS;
+ sendMessage(what);
+ }
+ };
+
+ public void setMessageHandler(Handler messageHandler) {
+ mMessageHandler = messageHandler;
+ }
+
+ private static void log(String msg) {
+ Log.v("Loopback", msg);
+ }
+
+} //end thread.
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/NativeAudioThread.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/NativeAudioThread.java
deleted file mode 100644
index 0bb1298..0000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/NativeAudioThread.java
+++ /dev/null
@@ -1,278 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-//package org.drrickorang.loopback;
-
-package com.android.cts.verifier.audio;
-
-import android.media.AudioFormat;
-import android.media.AudioManager;
-import android.media.AudioTrack;
-//import android.media.MediaPlayer;
-import android.media.AudioRecord;
-import android.media.MediaRecorder;
-import android.util.Log;
-
-import android.os.Handler;
-import android.os.Message;
-
-/**
- * A thread/audio track based audio synth.
- */
-public class NativeAudioThread extends Thread {
-
- public boolean isRunning = false;
- double twoPi = 6.28318530718;
-
- public int mSessionId;
-
- public double[] mvSamples; //captured samples
- int mSamplesIndex;
-
- private final int mSecondsToRun = 2;
- public int mSamplingRate = 48000;
- private int mChannelConfigIn = AudioFormat.CHANNEL_IN_MONO;
- private int mAudioFormat = AudioFormat.ENCODING_PCM_16BIT;
-
- int mMinPlayBufferSizeInBytes = 0;
- int mMinRecordBuffSizeInBytes = 0;
- private int mChannelConfigOut = AudioFormat.CHANNEL_OUT_MONO;
-
- int mMicSource = 0;
-
- int mNumFramesToIgnore;
-
-// private double [] samples = new double[50000];
-
- boolean isPlaying = false;
- private Handler mMessageHandler;
- boolean isDestroying = false;
- boolean hasDestroyingErrors = false;
-
- static final int NATIVE_AUDIO_THREAD_MESSAGE_REC_STARTED = 892;
- static final int NATIVE_AUDIO_THREAD_MESSAGE_REC_ERROR = 893;
- static final int NATIVE_AUDIO_THREAD_MESSAGE_REC_COMPLETE = 894;
- static final int NATIVE_AUDIO_THREAD_MESSAGE_REC_COMPLETE_ERRORS = 895;
-
- public void setParams(int samplingRate, int playBufferInBytes, int recBufferInBytes,
- int micSource, int numFramesToIgnore) {
- mSamplingRate = samplingRate;
- mMinPlayBufferSizeInBytes = playBufferInBytes;
- mMinRecordBuffSizeInBytes = recBufferInBytes;
- mMicSource = micSource;
- mNumFramesToIgnore = numFramesToIgnore;
- }
-
- //JNI load
- static {
- try {
- System.loadLibrary("audioloopback_jni");
- } catch (UnsatisfiedLinkError e) {
- log("Error loading loopback JNI library");
- e.printStackTrace();
- }
-
- /* TODO: gracefully fail/notify if the library can't be loaded */
- }
-
- //jni calls
- public native long slesInit(int samplingRate, int frameCount, int micSource,
- int numFramesToIgnore);
- public native int slesProcessNext(long sles_data, double[] samples, long offset);
- public native int slesDestroy(long sles_data);
-
- public void run() {
-
- setPriority(Thread.MAX_PRIORITY);
- isRunning = true;
-
- //erase output buffer
- if (mvSamples != null)
- mvSamples = null;
-
- //resize
- int nNewSize = (int)(1.1* mSamplingRate * mSecondsToRun ); //10% more just in case
- mvSamples = new double[nNewSize];
- mSamplesIndex = 0; //reset index
-
- //clear samples
- for (int i=0; i<nNewSize; i++) {
- mvSamples[i] = 0;
- }
-
- //start playing
- isPlaying = true;
-
-
- log(" Started capture test");
- if (mMessageHandler != null) {
- Message msg = Message.obtain();
- msg.what = NATIVE_AUDIO_THREAD_MESSAGE_REC_STARTED;
- mMessageHandler.sendMessage(msg);
- }
-
-
-
- log(String.format("about to init, sampling rate: %d, buffer:%d", mSamplingRate,
- mMinPlayBufferSizeInBytes/2 ));
- long sles_data = slesInit(mSamplingRate, mMinPlayBufferSizeInBytes/2, mMicSource,
- mNumFramesToIgnore);
- log(String.format("sles_data = 0x%X",sles_data));
-
- if (sles_data == 0 ) {
- log(" ERROR at JNI initialization");
- if (mMessageHandler != null) {
- Message msg = Message.obtain();
- msg.what = NATIVE_AUDIO_THREAD_MESSAGE_REC_ERROR;
- mMessageHandler.sendMessage(msg);
- }
- } else {
-
- //wait a little bit...
- try {
- sleep(10); //just to let it start properly?
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
-
-
-
- mSamplesIndex = 0;
- int totalSamplesRead = 0;
- long offset = 0;
- for (int ii = 0; ii < mSecondsToRun; ii++) {
- log(String.format("block %d...", ii));
- int samplesRead = slesProcessNext(sles_data, mvSamples,offset);
- totalSamplesRead += samplesRead;
-
- offset += samplesRead;
- log(" [" + ii + "] jni samples read:" + samplesRead + " currentOffset:" + offset);
- }
-
- log(String.format(" samplesRead: %d, sampleOffset:%d", totalSamplesRead, offset));
- log(String.format("about to destroy..."));
-
- runDestroy(sles_data);
-
- int maxTry = 20;
- int tryCount = 0;
- //isDestroying = true;
- while (isDestroying) {
-
- try {
- sleep(40);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
-
- tryCount++;
-
- log("destroy try: " + tryCount);
-
- if (tryCount >= maxTry) {
- hasDestroyingErrors = true;
- log("WARNING: waited for max time to properly destroy JNI.");
- break;
- }
- }
- log(String.format("after destroying. TotalSamplesRead = %d", totalSamplesRead));
-
- if (totalSamplesRead==0)
- {
- hasDestroyingErrors = true;
- }
-
- endTest();
- }
- }
-
- public void setMessageHandler(Handler messageHandler) {
- mMessageHandler = messageHandler;
- }
-
- private void runDestroy(final long sles_data ) {
- isDestroying = true;
-
- //start thread
-
- final long local_sles_data = sles_data;
- ////
- Thread thread = new Thread(new Runnable() {
- public void run() {
- isDestroying = true;
- log("**Start runnable destroy");
-
- int status = slesDestroy(local_sles_data);
- log(String.format("**End runnable destroy sles delete status: %d", status));
- isDestroying = false;
- }
- });
-
- thread.start();
-
-
-
- log("end of runDestroy()");
-
-
- }
-
- public void togglePlay() {
-
- }
-
- public void runTest() {
-
-
- }
-
- public void endTest() {
- log("--Ending capture test--");
- isPlaying = false;
-
-
- if (mMessageHandler != null) {
- Message msg = Message.obtain();
- if (hasDestroyingErrors)
- msg.what = NATIVE_AUDIO_THREAD_MESSAGE_REC_COMPLETE_ERRORS;
- else
- msg.what = NATIVE_AUDIO_THREAD_MESSAGE_REC_COMPLETE;
- mMessageHandler.sendMessage(msg);
- }
-
- }
-
- public void finish() {
-
- if (isRunning) {
- isRunning = false;
- try {
- sleep(20);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
-
- private static void log(String msg) {
- Log.v("Loopback", msg);
- }
-
- double [] getWaveData () {
- return mvSamples;
- }
-
-} //end thread.
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/p2p/testcase/P2pBroadcastReceiverTest.java b/apps/CtsVerifier/src/com/android/cts/verifier/p2p/testcase/P2pBroadcastReceiverTest.java
index 5cc23f1..0e5f356 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/p2p/testcase/P2pBroadcastReceiverTest.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/p2p/testcase/P2pBroadcastReceiverTest.java
@@ -42,7 +42,7 @@
private WifiP2pManager mP2pMgr;
private Channel mChannel;
- private WifiP2pDeviceList mPeers;
+ private WifiP2pDeviceList mPeers = new WifiP2pDeviceList();
private WifiP2pInfo mP2pInfo;
private WifiP2pGroup mP2pGroup;
@@ -79,12 +79,9 @@
Timeout t = new Timeout(msec);
while (!t.isTimeout()) {
- if (mPeers != null) {
- for (WifiP2pDevice dev: mPeers.getDeviceList()) {
- if (dev.deviceAddress.equals(targetAddr)) {
- return dev;
- }
- }
+ WifiP2pDevice dev = mPeers.get(targetAddr);
+ if (dev != null) {
+ return dev;
}
wait(t.getRemainTime());
}
@@ -125,14 +122,9 @@
Timeout t = new Timeout(msec);
while (!t.isTimeout()) {
- if (mPeers != null) {
- for (WifiP2pDevice dev: mPeers.getDeviceList()) {
- if (dev.deviceAddress.equals(targetAddr)) {
- if (dev.status == WifiP2pDevice.CONNECTED) {
- return true;
- }
- }
- }
+ WifiP2pDevice dev = mPeers.get(targetAddr);
+ if (dev != null && dev.status == WifiP2pDevice.CONNECTED) {
+ return true;
}
wait(t.getRemainTime());
}
@@ -152,21 +144,14 @@
Timeout t = new Timeout(msec);
- boolean devicePresent;
-
while (!t.isTimeout()) {
- devicePresent = false;
- if (mPeers != null) {
- for (WifiP2pDevice dev: mPeers.getDeviceList()) {
- if (dev.deviceAddress.equals(targetAddr)) {
- if (dev.status != WifiP2pDevice.CONNECTED) {
- return true;
- }
- devicePresent = true;
- }
- }
+ WifiP2pDevice dev = mPeers.get(targetAddr);
+
+ if (dev == null ) return true;
+
+ if (dev.status != WifiP2pDevice.CONNECTED) {
+ return true;
}
- if (!devicePresent) return true;
wait(t.getRemainTime());
}
Log.e(TAG, "Appropriate WIFI_P2P_PEERS_CHANGED_ACTION didn't occur");
@@ -217,7 +202,7 @@
@Override
public synchronized void onPeersAvailable(WifiP2pDeviceList peers) {
Log.d(TAG, "onPeersAvailable()");
- mPeers = peers;
+ mPeers = new WifiP2pDeviceList(peers);
notifyAll();
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/wifi/testcase/NetworkSuggestionTestCase.java b/apps/CtsVerifier/src/com/android/cts/verifier/wifi/testcase/NetworkSuggestionTestCase.java
index 395142d..68d3bb5 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/wifi/testcase/NetworkSuggestionTestCase.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/wifi/testcase/NetworkSuggestionTestCase.java
@@ -29,10 +29,8 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
-import android.net.LinkProperties;
import android.net.MacAddress;
import android.net.Network;
-import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiManager;
@@ -76,6 +74,7 @@
private ConnectivityManager mConnectivityManager;
private NetworkRequest mNetworkRequest;
private CallbackUtils.NetworkCallback mNetworkCallback;
+ private ConnectionStatusListener mConnectionStatusListener;
private BroadcastReceiver mBroadcastReceiver;
private String mFailureReason;
@@ -202,10 +201,10 @@
// Register the receiver for post connection broadcast.
mContext.registerReceiver(mBroadcastReceiver, intentFilter);
final CountDownLatch countDownLatchForConnectionStatusListener = new CountDownLatch(1);
- ConnectionStatusListener connectionStatusListener =
+ mConnectionStatusListener =
new ConnectionStatusListener(countDownLatchForConnectionStatusListener);
mWifiManager.addSuggestionConnectionStatusListener(
- Executors.newSingleThreadExecutor(), connectionStatusListener);
+ Executors.newSingleThreadExecutor(), mConnectionStatusListener);
// Step: Register network callback to wait for connection state.
mNetworkRequest = new NetworkRequest.Builder()
@@ -312,12 +311,12 @@
return false;
}
if (DBG) Log.v(TAG, "Received connection status");
- if (!Objects.equals(connectionStatusListener.wifiNetworkSuggestion, networkSuggestion)
- || connectionStatusListener.failureReason
+ if (!Objects.equals(mConnectionStatusListener.wifiNetworkSuggestion, networkSuggestion)
+ || mConnectionStatusListener.failureReason
!= WifiManager.STATUS_SUGGESTION_CONNECTION_FAILURE_AUTHENTICATION) {
Log.e(TAG, "Received wrong connection status for "
- + connectionStatusListener.wifiNetworkSuggestion
- + " with reason: " + connectionStatusListener.failureReason);
+ + mConnectionStatusListener.wifiNetworkSuggestion
+ + " with reason: " + mConnectionStatusListener.failureReason);
setFailureReason(mContext.getString(
R.string.wifi_status_suggestion_connection_status_failure));
return false;
@@ -404,6 +403,9 @@
if (mBroadcastReceiver != null) {
mContext.unregisterReceiver(mBroadcastReceiver);
}
+ if (mConnectionStatusListener != null) {
+ mWifiManager.removeSuggestionConnectionStatusListener(mConnectionStatusListener);
+ }
mWifiManager.removeNetworkSuggestions(new ArrayList<>());
super.tearDown();
}
diff --git a/hostsidetests/appsecurity/Android.mk b/hostsidetests/appsecurity/Android.mk
index ee149f0..55d7720 100644
--- a/hostsidetests/appsecurity/Android.mk
+++ b/hostsidetests/appsecurity/Android.mk
@@ -28,6 +28,9 @@
truth-prebuilt \
hamcrest-library
+LOCAL_STATIC_JAVA_LIBRARIES := \
+ CompatChangeGatingTestBase
+
LOCAL_JAVA_RESOURCE_DIRS := res
LOCAL_CTS_TEST_PACKAGE := android.appsecurity
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/DocumentsTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/DocumentsTest.java
index 1465bc3..00ddbb0 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/DocumentsTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/DocumentsTest.java
@@ -18,6 +18,8 @@
import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
+import com.google.common.collect.ImmutableSet;
+
/**
* Set of tests that verify behavior of
* {@link android.provider.DocumentsContract} and related intents.
@@ -27,6 +29,8 @@
private static final String PROVIDER_APK = "CtsDocumentProvider.apk";
private static final String DUMMYIME_APK = "CtsDummyIme.apk";
+ private static final long RESTRICT_STORAGE_ACCESS_FRAMEWORK = 141600225L;
+
@Override
protected void setUp() throws Exception {
super.setUp();
@@ -65,10 +69,6 @@
runDeviceTests(CLIENT_PKG, ".DocumentsClientTest", "testTree");
}
- public void testTree_blockFromTree() throws Exception {
- runDeviceTests(CLIENT_PKG, ".DocumentsClientTest", "testTree_blockFromTree");
- }
-
public void testGetContent_rootsShowing() throws Exception {
runDeviceTests(CLIENT_PKG, ".DocumentsClientTest", "testGetContent_rootsShowing");
}
@@ -119,4 +119,18 @@
public void testEject() throws Exception {
runDeviceTests(CLIENT_PKG, ".DocumentsClientTest", "testEject");
}
+
+ public void testRestrictStorageAccessFrameworkEnabled_blockFromTree() throws Exception {
+ runDeviceCompatTest(CLIENT_PKG, ".DocumentsClientTest",
+ "testRestrictStorageAccessFrameworkEnabled_blockFromTree",
+ /* enabledChanges */ ImmutableSet.of(RESTRICT_STORAGE_ACCESS_FRAMEWORK),
+ /* disabledChanges */ ImmutableSet.of());
+ }
+
+ public void testRestrictStorageAccessFrameworkDisabled_notBlockFromTree() throws Exception {
+ runDeviceCompatTest(CLIENT_PKG, ".DocumentsClientTest",
+ "testRestrictStorageAccessFrameworkDisabled_notBlockFromTree",
+ /* enabledChanges */ ImmutableSet.of(),
+ /* disabledChanges */ ImmutableSet.of(RESTRICT_STORAGE_ACCESS_FRAMEWORK));
+ }
}
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/DocumentsTestCase.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/DocumentsTestCase.java
index 1af0650..d7a9ffc 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/DocumentsTestCase.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/DocumentsTestCase.java
@@ -16,23 +16,21 @@
package android.appsecurity.cts;
+import android.compat.cts.CompatChangeGatingTestCase;
+
import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
-import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.testtype.DeviceTestCase;
import com.android.tradefed.testtype.IAbi;
import com.android.tradefed.testtype.IAbiReceiver;
-import com.android.tradefed.testtype.IBuildReceiver;
/**
* Base class for {@link android.provider.DocumentsContract} and related test cases.
*/
-abstract class DocumentsTestCase extends DeviceTestCase implements IAbiReceiver, IBuildReceiver {
+abstract class DocumentsTestCase extends CompatChangeGatingTestCase implements IAbiReceiver {
protected static final String CLIENT_PKG = "com.android.cts.documentclient";
protected static final String CLIENT_APK = "CtsDocumentClient.apk";
protected IAbi mAbi;
- protected IBuildInfo mCtsBuild;
@Override
public void setAbi(IAbi abi) {
@@ -40,17 +38,11 @@
}
@Override
- public void setBuild(IBuildInfo buildInfo) {
- mCtsBuild = buildInfo;
- }
-
- @Override
protected void setUp() throws Exception {
super.setUp();
Utils.prepareSingleUser(getDevice());
assertNotNull(mAbi);
- assertNotNull(mCtsBuild);
reinstallClientPackage();
}
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/ExternalStorageHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/ExternalStorageHostTest.java
index 38a76d9..ab6e0bd 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/ExternalStorageHostTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/ExternalStorageHostTest.java
@@ -655,9 +655,6 @@
runDeviceTests(WRITE_PKG_2, WRITE_PKG + ".WriteGiftTest",
"testNotIsExternalStorageLegacy", user);
- updateAppOp(WRITE_PKG_2, user, "android:request_install_packages", true);
- runDeviceTests(WRITE_PKG_2, WRITE_PKG + ".WriteGiftTest",
- "testIsExternalStorageLegacy", user);
}
} finally {
getDevice().uninstallPackage(WRITE_PKG);
diff --git a/hostsidetests/appsecurity/test-apps/DocumentClient/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/DocumentClient/AndroidManifest.xml
index 79eb44d..e87cd6f 100644
--- a/hostsidetests/appsecurity/test-apps/DocumentClient/AndroidManifest.xml
+++ b/hostsidetests/appsecurity/test-apps/DocumentClient/AndroidManifest.xml
@@ -16,7 +16,9 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.cts.documentclient">
- <application android:forceQueryable="true">
+ <uses-sdk android:minSdkVersion="29" android:targetSdkVersion="29"/>
+
+ <application android:debuggable="true" android:forceQueryable="true">
<uses-library android:name="android.test.runner" />
<activity android:name=".MyActivity" />
</application>
diff --git a/hostsidetests/appsecurity/test-apps/DocumentClient/src/com/android/cts/documentclient/DocumentsClientTest.java b/hostsidetests/appsecurity/test-apps/DocumentClient/src/com/android/cts/documentclient/DocumentsClientTest.java
index 1f302dd..40d8ff4 100644
--- a/hostsidetests/appsecurity/test-apps/DocumentClient/src/com/android/cts/documentclient/DocumentsClientTest.java
+++ b/hostsidetests/appsecurity/test-apps/DocumentClient/src/com/android/cts/documentclient/DocumentsClientTest.java
@@ -357,19 +357,58 @@
}
}
- public void testTree_blockFromTree() throws Exception {
+ public void testRestrictStorageAccessFrameworkEnabled_blockFromTree() throws Exception {
if (!supportedHardware()) return;
final Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
mActivity.startActivityForResult(intent, REQUEST_CODE);
mDevice.waitForIdle();
+
+ // save button is disabled for the storage root
+ assertFalse(findSaveButton().isEnabled());
+
+ findDocument("Download").click();
+ mDevice.waitForIdle();
+
+ // save button is disabled for Download folder
+ assertFalse(findSaveButton().isEnabled());
+
findRoot("CtsCreate").click();
+ mDevice.waitForIdle();
+
+ // save button is disabled for CtsCreate root
+ assertFalse(findSaveButton().isEnabled());
+
+ findDocument("DIR2").click();
+
+ mDevice.waitForIdle();
+ // save button is enabled for dir2
+ assertTrue(findSaveButton().isEnabled());
+ }
+
+ public void testRestrictStorageAccessFrameworkDisabled_notBlockFromTree() throws Exception {
+ if (!supportedHardware()) return;
+
+ final Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
+ mActivity.startActivityForResult(intent, REQUEST_CODE);
mDevice.waitForIdle();
- // save button is disabled for root
- assertFalse(findSaveButton().isEnabled());
+ // save button is enabled for for the storage root
+ assertTrue(findSaveButton().isEnabled());
+
+ findDocument("Download").click();
+ mDevice.waitForIdle();
+
+ // save button is enabled for Download folder
+ assertTrue(findSaveButton().isEnabled());
+
+ findRoot("CtsCreate").click();
+ mDevice.waitForIdle();
+
+ // save button is enabled for CtsCreate root
+ assertTrue(findSaveButton().isEnabled());
findDocument("DIR2").click();
@@ -661,14 +700,6 @@
// assert the default root is internal storage root
assertToolbarTitleEquals(title);
- // save button is disabled for the root
- assertFalse(findSaveButton().isEnabled());
-
- findDocument("Download").click();
- mDevice.waitForIdle();
- // save button is disabled for Download folder
- assertFalse(findSaveButton().isEnabled());
-
// no Downloads root
assertFalse(findRoot("Downloads").exists());
}
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 61f342c..0886269 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
@@ -473,8 +473,7 @@
// 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)");
+ final UiSelector grant = new UiSelector().textMatches("Allow");
if (new UiObject(grant).waitForExists(2_000)) {
device.findObject(grant).click();
}
diff --git a/hostsidetests/appsecurity/test-apps/V3SigningSchemeRotation/Android.bp b/hostsidetests/appsecurity/test-apps/V3SigningSchemeRotation/Android.bp
index 4481d9e..9de8251 100644
--- a/hostsidetests/appsecurity/test-apps/V3SigningSchemeRotation/Android.bp
+++ b/hostsidetests/appsecurity/test-apps/V3SigningSchemeRotation/Android.bp
@@ -20,6 +20,7 @@
"cts",
"vts",
"general-tests",
+ "sts",
],
srcs: ["src/**/*.java"],
sdk_version: "current",
diff --git a/hostsidetests/backup/OtherSoundsSettingsApp/Android.bp b/hostsidetests/backup/OtherSoundsSettingsApp/Android.bp
index fac14e6..e34b256 100644
--- a/hostsidetests/backup/OtherSoundsSettingsApp/Android.bp
+++ b/hostsidetests/backup/OtherSoundsSettingsApp/Android.bp
@@ -27,5 +27,8 @@
"vts",
"general-tests",
],
- sdk_version: "test_current",
+ // Uncomment when b/78787392 is fixed
+ // sdk_version: "system_test_current",
+ platform_apis: true,
+
}
diff --git a/hostsidetests/backup/OtherSoundsSettingsApp/src/android/cts/backup/othersoundssettingsapp/OtherSoundsSettingsTest.java b/hostsidetests/backup/OtherSoundsSettingsApp/src/android/cts/backup/othersoundssettingsapp/OtherSoundsSettingsTest.java
index 792cd1d..868dc40 100644
--- a/hostsidetests/backup/OtherSoundsSettingsApp/src/android/cts/backup/othersoundssettingsapp/OtherSoundsSettingsTest.java
+++ b/hostsidetests/backup/OtherSoundsSettingsApp/src/android/cts/backup/othersoundssettingsapp/OtherSoundsSettingsTest.java
@@ -23,6 +23,7 @@
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;
+import android.app.UiAutomation;
import android.content.ContentResolver;
import android.content.Context;
import android.os.ParcelFileDescriptor;
@@ -34,12 +35,15 @@
import com.android.compatibility.common.util.BackupUtils;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.io.IOException;
import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
/**
* Device side routines to be invoked by the host side OtherSoundsSettingsHostSideTest. These
@@ -51,9 +55,12 @@
public class OtherSoundsSettingsTest {
/** The name of the package for backup */
private static final String SETTINGS_PACKAGE_NAME = "com.android.providers.settings";
+ private static final int SETTING_ABSENT_VALUE = -1;
private ContentResolver mContentResolver;
private BackupUtils mBackupUtils;
+ private Map<String, Integer> mOriginalSettingValues;
+ private UiAutomation mUiAutomation;
@Before
public void setUp() throws Exception {
@@ -67,6 +74,15 @@
return new ParcelFileDescriptor.AutoCloseInputStream(pfd);
}
};
+ mOriginalSettingValues = new HashMap<>();
+ mUiAutomation = getInstrumentation().getUiAutomation();
+ mUiAutomation.adoptShellPermissionIdentity();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ restoreOriginalSettingValues();
+ mUiAutomation.dropShellPermissionIdentity();
}
/**
@@ -81,17 +97,13 @@
*/
@Test
public void testOtherSoundsSettings_dialPadTones() throws Exception {
- int originalValue =
- Settings.System.getInt(
- mContentResolver, Settings.System.DTMF_TONE_WHEN_DIALING, -1);
+ int originalValue = prepareSystemSetting(Settings.System.DTMF_TONE_WHEN_DIALING);
assertTrue("Dial pad tones does not exist.", originalValue != -1);
mBackupUtils.backupNowAndAssertSuccess(SETTINGS_PACKAGE_NAME);
- boolean ret =
- Settings.System.putInt(
- mContentResolver, Settings.System.DTMF_TONE_WHEN_DIALING,
- 1 - originalValue);
+ boolean ret = setSystemSetting(Settings.System.DTMF_TONE_WHEN_DIALING,
+ 1 - originalValue);
assertTrue("Toggle Dial pad tones fail.", ret);
mBackupUtils.restoreAndAssertSuccess(LOCAL_TRANSPORT_TOKEN, SETTINGS_PACKAGE_NAME);
@@ -114,16 +126,13 @@
*/
@Test
public void testOtherSoundsSettings_touchSounds() throws Exception {
- int originalValue =
- Settings.System.getInt(
- mContentResolver, Settings.System.SOUND_EFFECTS_ENABLED, -1);
+ int originalValue = prepareSystemSetting(Settings.System.SOUND_EFFECTS_ENABLED);
assertTrue("Touch sounds does not exist.", originalValue != -1);
mBackupUtils.backupNowAndAssertSuccess(SETTINGS_PACKAGE_NAME);
- boolean ret =
- Settings.System.putInt(
- mContentResolver, Settings.System.SOUND_EFFECTS_ENABLED, 1 - originalValue);
+ boolean ret = setSystemSetting(Settings.System.SOUND_EFFECTS_ENABLED,
+ 1 - originalValue);
assertTrue("Toggle Touch sounds fail.", ret);
mBackupUtils.restoreAndAssertSuccess(LOCAL_TRANSPORT_TOKEN, SETTINGS_PACKAGE_NAME);
@@ -154,17 +163,13 @@
assumeTrue(
"Device Under Test does not have a vibrator, skipping.", mVibrator.hasVibrator());
- int originalValue =
- Settings.System.getInt(
- mContentResolver, Settings.System.HAPTIC_FEEDBACK_ENABLED, -1);
+ int originalValue = prepareSystemSetting(Settings.System.HAPTIC_FEEDBACK_ENABLED);
assertTrue("Touch vibration does not exist.", originalValue != -1);
mBackupUtils.backupNowAndAssertSuccess(SETTINGS_PACKAGE_NAME);
- boolean ret =
- Settings.System.putInt(
- mContentResolver, Settings.System.HAPTIC_FEEDBACK_ENABLED,
- 1 - originalValue);
+ boolean ret = setSystemSetting(Settings.System.HAPTIC_FEEDBACK_ENABLED,
+ 1 - originalValue);
assertTrue("Toggle Touch vibration fail.", ret);
mBackupUtils.restoreAndAssertSuccess(LOCAL_TRANSPORT_TOKEN, SETTINGS_PACKAGE_NAME);
@@ -174,4 +179,33 @@
mContentResolver, Settings.System.HAPTIC_FEEDBACK_ENABLED, -1);
assertTrue("Touch vibration restore fail.", originalValue == restoreValue);
}
+
+ private int prepareSystemSetting(String name) throws Exception {
+ int value = Settings.System.getInt(mContentResolver, name, SETTING_ABSENT_VALUE);
+ if (value == SETTING_ABSENT_VALUE) {
+ return SETTING_ABSENT_VALUE;
+ }
+
+ mOriginalSettingValues.put(name, value);
+ clearSystemSettingState(name);
+ setSystemSetting(name, value);
+
+ return value;
+ }
+
+ private boolean setSystemSetting(String name, int value) {
+ return Settings.System.putString(mContentResolver, name, String.valueOf(value),
+ /* overrideableByRestore */ true);
+ }
+
+ private void restoreOriginalSettingValues() throws Exception {
+ for (String settingName : mOriginalSettingValues.keySet()) {
+ clearSystemSettingState(settingName);
+ setSystemSetting(settingName, mOriginalSettingValues.get(settingName));
+ }
+ }
+
+ private void clearSystemSettingState(String setting) throws Exception {
+ mBackupUtils.executeShellCommandSync("settings delete system " + setting);
+ }
}
\ No newline at end of file
diff --git a/hostsidetests/blobstore/src/com/android/cts/host/blob/InstantAppAccessTest.java b/hostsidetests/blobstore/src/com/android/cts/host/blob/InstantAppAccessTest.java
new file mode 100644
index 0000000..0c2c13a
--- /dev/null
+++ b/hostsidetests/blobstore/src/com/android/cts/host/blob/InstantAppAccessTest.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2020 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.host.blob;
+
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class InstantAppAccessTest extends BaseBlobStoreHostTest {
+ private static final String TEST_CLASS = TARGET_PKG + ".InstantAppAccessTest";
+
+ @Before
+ public void setUp() throws Exception {
+ uninstallPackage(TARGET_PKG);
+ installPackage(TARGET_APK, "--instant");
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ uninstallPackage(TARGET_PKG);
+ }
+
+ @Test
+ public void testInstantAppAccess() throws Exception {
+ runDeviceTest(TARGET_PKG, TEST_CLASS, "testInstantAppAccess");
+ }
+}
diff --git a/hostsidetests/blobstore/test-apps/BlobStoreHostTestHelper/src/com/android/cts/device/blob/DataCleanupTest.java b/hostsidetests/blobstore/test-apps/BlobStoreHostTestHelper/src/com/android/cts/device/blob/DataCleanupTest.java
index 5bb82b9..72b907e 100644
--- a/hostsidetests/blobstore/test-apps/BlobStoreHostTestHelper/src/com/android/cts/device/blob/DataCleanupTest.java
+++ b/hostsidetests/blobstore/test-apps/BlobStoreHostTestHelper/src/com/android/cts/device/blob/DataCleanupTest.java
@@ -34,7 +34,6 @@
import org.junit.runner.RunWith;
import java.util.Base64;
-import java.util.Random;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
@@ -59,7 +58,6 @@
private Context mContext;
private Instrumentation mInstrumentation;
private BlobStoreManager mBlobStoreManager;
- private Random mRandom;
@Before
public void setUp() {
@@ -67,12 +65,14 @@
mContext = mInstrumentation.getContext();
mBlobStoreManager = (BlobStoreManager) mContext.getSystemService(
Context.BLOB_STORE_SERVICE);
- mRandom = new Random(24 /* seed */);
}
@Test
public void testCreateSession() throws Exception {
- final DummyBlobData blobData = new DummyBlobData(mContext, mRandom, "test_data_blob");
+ final DummyBlobData blobData = new DummyBlobData.Builder(mContext)
+ .setRandomSeed(24)
+ .setFileName("test_blob_data")
+ .build();
blobData.prepare();
final long sessionId = createSession(blobData.getBlobHandle());
@@ -106,8 +106,11 @@
@Test
public void testCommitBlob() throws Exception {
- final DummyBlobData blobData = new DummyBlobData(mContext, mRandom,
- "test_data_blob", "test_data_blob");
+ final DummyBlobData blobData = new DummyBlobData.Builder(mContext)
+ .setRandomSeed(24)
+ .setFileName("test_blob_data")
+ .setLabel("test_data_blob_label")
+ .build();
blobData.prepare();
final long sessionId = createSession(blobData.getBlobHandle());
diff --git a/hostsidetests/blobstore/test-apps/BlobStoreHostTestHelper/src/com/android/cts/device/blob/DataPersistenceTest.java b/hostsidetests/blobstore/test-apps/BlobStoreHostTestHelper/src/com/android/cts/device/blob/DataPersistenceTest.java
index b4226a6..72c6847 100644
--- a/hostsidetests/blobstore/test-apps/BlobStoreHostTestHelper/src/com/android/cts/device/blob/DataPersistenceTest.java
+++ b/hostsidetests/blobstore/test-apps/BlobStoreHostTestHelper/src/com/android/cts/device/blob/DataPersistenceTest.java
@@ -31,7 +31,6 @@
import org.junit.runner.RunWith;
import java.util.Base64;
-import java.util.Random;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
@@ -53,19 +52,20 @@
private Context mContext;
private BlobStoreManager mBlobStoreManager;
- private Random mRandom;
@Before
public void setUp() {
mContext = InstrumentationRegistry.getInstrumentation().getContext();
mBlobStoreManager = (BlobStoreManager) mContext.getSystemService(
Context.BLOB_STORE_SERVICE);
- mRandom = new Random(22 /* seed */);
}
@Test
public void testCreateSession() throws Exception {
- final DummyBlobData blobData = new DummyBlobData(mContext, mRandom, "test_data_blob");
+ final DummyBlobData blobData = new DummyBlobData.Builder(mContext)
+ .setRandomSeed(22)
+ .setFileName("test_blob_data")
+ .build();
blobData.prepare();
final long sessionId = createSession(blobData.getBlobHandle());
@@ -84,7 +84,10 @@
@Test
public void testOpenSessionAndWrite() throws Exception {
final long sessionId = readSessionIdFromDisk();
- final DummyBlobData blobData = new DummyBlobData(mContext, mRandom, "test_data_blob");
+ final DummyBlobData blobData = new DummyBlobData.Builder(mContext)
+ .setRandomSeed(22)
+ .setFileName("test_blob_data")
+ .build();
try (BlobStoreManager.Session session = mBlobStoreManager.openSession(sessionId)) {
assertThat(session.getSize()).isEqualTo(PARTIAL_FILE_LENGTH_BYTES);
blobData.writeToSession(session, PARTIAL_FILE_LENGTH_BYTES,
diff --git a/hostsidetests/blobstore/test-apps/BlobStoreHostTestHelper/src/com/android/cts/device/blob/InstantAppAccessTest.java b/hostsidetests/blobstore/test-apps/BlobStoreHostTestHelper/src/com/android/cts/device/blob/InstantAppAccessTest.java
new file mode 100644
index 0000000..4d7fd48
--- /dev/null
+++ b/hostsidetests/blobstore/test-apps/BlobStoreHostTestHelper/src/com/android/cts/device/blob/InstantAppAccessTest.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2020 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.device.blob;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+@RunWith(AndroidJUnit4.class)
+public class InstantAppAccessTest {
+ @Test
+ public void testInstantAppAccess() {
+ final Context context = InstrumentationRegistry.getInstrumentation().getContext();
+ assertThat(context.getPackageManager().isInstantApp()).isTrue();
+ assertThat(context.getSystemService(Context.BLOB_STORE_SERVICE)).isNull();
+ }
+}
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/AudioRestrictionTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/AudioRestrictionTest.java
index ffceb36..6fa0bcb 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/AudioRestrictionTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/AudioRestrictionTest.java
@@ -29,12 +29,14 @@
import java.util.Objects;
import java.util.concurrent.Callable;
+import java.util.regex.Pattern;
public class AudioRestrictionTest extends BaseDeviceAdminTest {
private static final String TAG = AudioRestrictionTest.class.getSimpleName();
private AudioManager mAudioManager;
private PackageManager mPackageManager;
private boolean mUseFixedVolume;
+ private boolean mUseFullVolume;
private final Callable<Boolean> mCheckIfMasterVolumeMuted = new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
@@ -49,6 +51,7 @@
mPackageManager = mContext.getPackageManager();
mUseFixedVolume = mContext.getResources().getBoolean(
Resources.getSystem().getIdentifier("config_useFixedVolume", "bool", "android"));
+ mUseFullVolume = isFullVolumeDevice();
}
// Here we test that DISALLOW_ADJUST_VOLUME disallows to unmute volume.
@@ -86,7 +89,8 @@
}
public void testDisallowAdjustVolume() throws Exception {
- if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUDIO_OUTPUT) || mUseFixedVolume) {
+ if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUDIO_OUTPUT)
+ || mUseFixedVolume || mUseFullVolume) {
return;
}
@@ -186,4 +190,17 @@
Thread.sleep(200);
}
}
+
+ private boolean isFullVolumeDevice() {
+ String commandOutput = runShellCommand("dumpsys audio");
+
+ for (String line : commandOutput.split("\\r?\\n")) {
+ if (Pattern.matches("\\s*mHdmiCecSink=true", line)
+ || (Pattern.matches("\\s*mHdmiPlayBackClient=", line)
+ && !Pattern.matches("=null$", line))) {
+ return true;
+ }
+ }
+ return false;
+ }
}
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/CommonCriteriaModeTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/CommonCriteriaModeTest.java
index 726dd87..e70e9a5 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/CommonCriteriaModeTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/CommonCriteriaModeTest.java
@@ -21,9 +21,11 @@
try {
// Default to false
assertFalse(mDevicePolicyManager.isCommonCriteriaModeEnabled(ADMIN_RECEIVER_COMPONENT));
+ assertFalse(mDevicePolicyManager.isCommonCriteriaModeEnabled(null));
mDevicePolicyManager.setCommonCriteriaModeEnabled(ADMIN_RECEIVER_COMPONENT, true);
assertTrue(mDevicePolicyManager.isCommonCriteriaModeEnabled(ADMIN_RECEIVER_COMPONENT));
+ assertTrue(mDevicePolicyManager.isCommonCriteriaModeEnabled(null));
} finally {
mDevicePolicyManager.setCommonCriteriaModeEnabled(ADMIN_RECEIVER_COMPONENT, false);
}
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/DevicePolicyLoggingTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/DevicePolicyLoggingTest.java
index 036f4a2..61fdb18 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/DevicePolicyLoggingTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/DevicePolicyLoggingTest.java
@@ -154,11 +154,12 @@
mDevicePolicyManager.setAutoTimeRequired(ADMIN_RECEIVER_COMPONENT, initialValue);
}
- public void testSetAutoTime() {
- final boolean initialValue = mDevicePolicyManager.getAutoTime(ADMIN_RECEIVER_COMPONENT);
- mDevicePolicyManager.setAutoTime(ADMIN_RECEIVER_COMPONENT, true);
- mDevicePolicyManager.setAutoTime(ADMIN_RECEIVER_COMPONENT, false);
- mDevicePolicyManager.setAutoTime(ADMIN_RECEIVER_COMPONENT, initialValue);
+ public void testSetAutoTimeEnabled() {
+ final boolean initialValue = mDevicePolicyManager.getAutoTimeEnabled(
+ ADMIN_RECEIVER_COMPONENT);
+ mDevicePolicyManager.setAutoTimeEnabled(ADMIN_RECEIVER_COMPONENT, true);
+ mDevicePolicyManager.setAutoTimeEnabled(ADMIN_RECEIVER_COMPONENT, false);
+ mDevicePolicyManager.setAutoTimeEnabled(ADMIN_RECEIVER_COMPONENT, initialValue);
}
public void testEnableSystemAppLogged() {
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/LockTaskTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/LockTaskTest.java
index 78b5b2e..c791f25 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/LockTaskTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/LockTaskTest.java
@@ -346,6 +346,43 @@
mDevicePolicyManager.setLockTaskFeatures(ADMIN_COMPONENT, 0);
}
+ // When LOCK_TASK_FEATURE_BLOCK_ACTIVITY_START_IN_TASK is set, the system dialog will also be
+ // shown when an un-whitelisted app is being launched in a new task.
+ public void testStartActivity_newTask_blockInTask() throws Exception {
+ mDevicePolicyManager.setLockTaskPackages(ADMIN_COMPONENT, new String[] { PACKAGE_NAME });
+ mDevicePolicyManager.setLockTaskFeatures(
+ ADMIN_COMPONENT, LOCK_TASK_FEATURE_BLOCK_ACTIVITY_START_IN_TASK);
+ startLockTask(UTILITY_ACTIVITY);
+ waitForResume();
+
+ mIsReceiverActivityRunning = false;
+ Intent launchIntent = createReceiverActivityIntent(true /*newTask*/, false /*shouldWait*/);
+ Intent lockTaskUtility = getLockTaskUtility(UTILITY_ACTIVITY);
+ lockTaskUtility.putExtra(LockTaskUtilityActivity.START_ACTIVITY, launchIntent);
+ mContext.startActivity(lockTaskUtility);
+
+ synchronized (mReceiverActivityRunningLock) {
+ mReceiverActivityRunningLock.wait(ACTIVITY_RESUMED_TIMEOUT_MILLIS);
+ assertFalse(mIsReceiverActivityRunning);
+ }
+
+ Log.d(TAG, "Waiting for the system dialog");
+ mUiDevice.waitForIdle();
+ assertTrue(mUiDevice.wait(
+ Until.hasObject(By.textContains(RECEIVER_ACTIVITY_PACKAGE_NAME)),
+ ACTIVITY_RESUMED_TIMEOUT_MILLIS));
+ Log.d(TAG, "dialog found");
+
+ // Dismiss the system dialog
+ mUiDevice.pressKeyCode(KeyEvent.KEYCODE_ENTER);
+ mUiDevice.pressKeyCode(KeyEvent.KEYCODE_ENTER);
+ assertFalse(mUiDevice.wait(
+ Until.hasObject(By.textContains(RECEIVER_ACTIVITY_PACKAGE_NAME)),
+ ACTIVITY_RESUMED_TIMEOUT_MILLIS));
+
+ mDevicePolicyManager.setLockTaskFeatures(ADMIN_COMPONENT, 0);
+ }
+
// This launches a whitelisted activity that is not part of the current task.
// This should be permitted as a part of lock task.
public void testStartActivity_outsideTaskWhitelisted() throws Exception {
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/SetPolicyActivity.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/SetPolicyActivity.java
index 6e92dda..1469e5a 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/SetPolicyActivity.java
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/SetPolicyActivity.java
@@ -21,9 +21,9 @@
import android.content.Intent;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Bundle;
-import android.os.Handler;
import android.os.Process;
import android.util.Log;
+
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -62,16 +62,6 @@
handleIntent(intent);
}
- @Override
- public void onResume() {
- super.onResume();
- // Posting finish() here because:
- // - calling it directly in onResume() or sooner makes
- // "adb shell am start" timeout if using the -W option.
- // - calling it in onPause() or later does nothing
- Handler.getMain().post(this::finish);
- }
-
private void handleIntent(Intent intent) {
DevicePolicyManager dpm = (DevicePolicyManager)
getSystemService(Context.DEVICE_POLICY_SERVICE);
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
index 24428d8..1f33446 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/TimeManagementTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/TimeManagementTest.java
@@ -39,18 +39,18 @@
super.tearDown();
}
- public void testSetAutoTimeZone() {
- mDevicePolicyManager.setAutoTimeZone(ADMIN_RECEIVER_COMPONENT, true);
+ public void testSetAutoTimeZoneEnabled() {
+ mDevicePolicyManager.setAutoTimeZoneEnabled(ADMIN_RECEIVER_COMPONENT, true);
- assertThat(mDevicePolicyManager.getAutoTimeZone(ADMIN_RECEIVER_COMPONENT)).isTrue();
+ assertThat(mDevicePolicyManager.getAutoTimeZoneEnabled(ADMIN_RECEIVER_COMPONENT)).isTrue();
- mDevicePolicyManager.setAutoTimeZone(ADMIN_RECEIVER_COMPONENT, false);
+ mDevicePolicyManager.setAutoTimeZoneEnabled(ADMIN_RECEIVER_COMPONENT, false);
- assertThat(mDevicePolicyManager.getAutoTimeZone(ADMIN_RECEIVER_COMPONENT)).isFalse();
+ assertThat(mDevicePolicyManager.getAutoTimeZoneEnabled(ADMIN_RECEIVER_COMPONENT)).isFalse();
}
public void testSetTime() {
- mDevicePolicyManager.setAutoTime(ADMIN_RECEIVER_COMPONENT, false);
+ mDevicePolicyManager.setAutoTimeEnabled(ADMIN_RECEIVER_COMPONENT, false);
final long estimatedNow = mStartTimeWallClockMillis +
TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - mStartTimeElapsedNanos);
@@ -59,20 +59,20 @@
}
public void testSetTime_failWhenAutoTimeEnabled() {
- mDevicePolicyManager.setAutoTime(ADMIN_RECEIVER_COMPONENT, true);
+ mDevicePolicyManager.setAutoTimeEnabled(ADMIN_RECEIVER_COMPONENT, true);
assertThat(mDevicePolicyManager.setTime(ADMIN_RECEIVER_COMPONENT, 0)).isFalse();
}
public void testSetTimeZone() {
- mDevicePolicyManager.setAutoTimeZone(ADMIN_RECEIVER_COMPONENT, false);
+ mDevicePolicyManager.setAutoTimeZoneEnabled(ADMIN_RECEIVER_COMPONENT, false);
assertThat(
mDevicePolicyManager.setTimeZone(ADMIN_RECEIVER_COMPONENT, "Singapore")).isTrue();
}
public void testSetTimeZone_failIfAutoTimeZoneEnabled() {
- mDevicePolicyManager.setAutoTimeZone(ADMIN_RECEIVER_COMPONENT, true);
+ mDevicePolicyManager.setAutoTimeZoneEnabled(ADMIN_RECEIVER_COMPONENT, true);
assertThat(
mDevicePolicyManager.setTimeZone(ADMIN_RECEIVER_COMPONENT, "Singapore")).isFalse();
@@ -84,12 +84,12 @@
}
private void restoreTime() {
- mDevicePolicyManager.setAutoTime(ADMIN_RECEIVER_COMPONENT, false);
+ mDevicePolicyManager.setAutoTimeEnabled(ADMIN_RECEIVER_COMPONENT, false);
final long estimatedNow = mStartTimeWallClockMillis +
TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - mStartTimeElapsedNanos);
mDevicePolicyManager.setTime(ADMIN_RECEIVER_COMPONENT, estimatedNow);
- mDevicePolicyManager.setAutoTime(ADMIN_RECEIVER_COMPONENT, true);
+ mDevicePolicyManager.setAutoTimeEnabled(ADMIN_RECEIVER_COMPONENT, true);
}
}
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/SetPolicyActivity.java b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/SetPolicyActivity.java
index 514b9e8..5637912 100644
--- a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/SetPolicyActivity.java
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/SetPolicyActivity.java
@@ -50,14 +50,6 @@
handleIntent(intent);
}
- @Override
- public void onPause() {
- super.onPause();
- // Calling finish() here because doing it in onCreate(), onStart() or onResume() makes
- // "adb shell am start" timeout if using the -W option.
- finish();
- }
-
private void handleIntent(Intent intent) {
DevicePolicyManager dpm = (DevicePolicyManager)
getSystemService(Context.DEVICE_POLICY_SERVICE);
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/ProtectedPackagesTest.java b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/UserControlDisabledPackagesTest.java
similarity index 71%
rename from hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/ProtectedPackagesTest.java
rename to hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/UserControlDisabledPackagesTest.java
index 4489bdb..91ca612 100644
--- a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/ProtectedPackagesTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/UserControlDisabledPackagesTest.java
@@ -21,13 +21,14 @@
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import java.util.ArrayList;
+import java.util.Collections;
/**
- * Test {@link DevicePolicyManager#setProtectedPackages} and
- * {@link DevicePolicyManager#getProtectedPackages}
+ * Test {@link DevicePolicyManager#setUserControlDisabledPackages} and
+ * {@link DevicePolicyManager#getUserControlDisabledPackages}
* Hostside test uses "am force-stop" and verifies that app is not stopped.
*/
-public class ProtectedPackagesTest extends BaseDeviceOwnerTest {
+public class UserControlDisabledPackagesTest extends BaseDeviceOwnerTest {
private static final String TEST_APP_APK = "CtsEmptyTestApp.apk";
private static final String TEST_APP_PKG = "android.packageinstaller.emptytestapp.cts";
@@ -36,10 +37,10 @@
private static final String SIMPLE_APP_ACTIVITY =
"com.android.cts.launcherapps.simpleapp.SimpleActivityImmediateExit";
- public void testSetProtectedPackages() throws Exception {
+ public void testSetUserControlDisabledPackages() throws Exception {
ArrayList<String> protectedPackages= new ArrayList<>();
protectedPackages.add(SIMPLE_APP_PKG);
- mDevicePolicyManager.setProtectedPackages(getWho(), protectedPackages);
+ mDevicePolicyManager.setUserControlDisabledPackages(getWho(), protectedPackages);
// Launch app so that the app exits stopped state.
Intent intent = new Intent(Intent.ACTION_MAIN);
@@ -49,21 +50,23 @@
}
- public void testForceStopForProtectedPackages() throws Exception {
+ public void testForceStopWithUserControlDisabled() throws Exception {
final ArrayList<String> pkgs = new ArrayList<>();
pkgs.add(SIMPLE_APP_PKG);
assertFalse(isPackageStopped(SIMPLE_APP_PKG));
- assertEquals(pkgs, mDevicePolicyManager.getProtectedPackages(getWho()));
+ assertEquals(pkgs, mDevicePolicyManager.getUserControlDisabledPackages(getWho()));
}
- public void testClearProtectedPackages() throws Exception {
+ public void testClearSetUserControlDisabledPackages() throws Exception {
final ArrayList<String> pkgs = new ArrayList<>();
- mDevicePolicyManager.setProtectedPackages(getWho(), pkgs);
- assertEquals(pkgs, mDevicePolicyManager.getProtectedPackages(getWho()));
+ mDevicePolicyManager.setUserControlDisabledPackages(getWho(), pkgs);
+ assertEquals(pkgs, mDevicePolicyManager.getUserControlDisabledPackages(getWho()));
}
- public void testForceStopForUnprotectedPackages() throws Exception {
+ public void testForceStopWithUserControlEnabled() throws Exception {
assertTrue(isPackageStopped(SIMPLE_APP_PKG));
+ assertEquals(Collections.emptyList(),
+ mDevicePolicyManager.getUserControlDisabledPackages(getWho()));
}
private boolean isPackageStopped(String packageName) throws Exception {
diff --git a/hostsidetests/devicepolicy/app/IntentSender/src/com/android/cts/intent/sender/SuspendPackageTest.java b/hostsidetests/devicepolicy/app/IntentSender/src/com/android/cts/intent/sender/SuspendPackageTest.java
index 5871ed8..bd95a35 100644
--- a/hostsidetests/devicepolicy/app/IntentSender/src/com/android/cts/intent/sender/SuspendPackageTest.java
+++ b/hostsidetests/devicepolicy/app/IntentSender/src/com/android/cts/intent/sender/SuspendPackageTest.java
@@ -3,7 +3,9 @@
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
import android.content.res.Configuration;
+import android.provider.Settings;
import android.support.test.uiautomator.By;
import android.support.test.uiautomator.BySelector;
import android.support.test.uiautomator.Direction;
@@ -14,21 +16,11 @@
public class SuspendPackageTest extends InstrumentationTestCase {
private static final int WAIT_DIALOG_TIMEOUT_IN_MS = 5000;
- private static final BySelector POPUP_IMAGE_SELECTOR = By
- .clazz(android.widget.ImageView.class.getName())
- .res("com.android.settings:id/admin_support_icon")
- .pkg("com.android.settings");
-
private static final BySelector POPUP_TITLE_WATCH_SELECTOR = By
.clazz(android.widget.TextView.class.getName())
.res("android:id/alertTitle")
.pkg("com.google.android.apps.wearable.settings");
- private static final BySelector POPUP_BUTTON_SELECTOR = By
- .clazz(android.widget.Button.class.getName())
- .res("android:id/button1")
- .pkg("com.android.settings");
-
private static final BySelector SUSPEND_BUTTON_SELECTOR = By
.clazz(android.widget.Button.class.getName())
.res("android:id/button1");
@@ -100,11 +92,11 @@
assertNotNull("Policy transparency dialog title not found", title);
title.swipe(Direction.RIGHT, 1.0f);
} else {
- device.wait(Until.hasObject(POPUP_IMAGE_SELECTOR), WAIT_DIALOG_TIMEOUT_IN_MS);
- final UiObject2 icon = device.findObject(POPUP_IMAGE_SELECTOR);
+ device.wait(Until.hasObject(getPopUpImageSelector()), WAIT_DIALOG_TIMEOUT_IN_MS);
+ final UiObject2 icon = device.findObject(getPopUpImageSelector());
assertNotNull("Policy transparency dialog icon not found", icon);
// "OK" button only present in the dialog if it is blocked by policy.
- final UiObject2 button = device.findObject(POPUP_BUTTON_SELECTOR);
+ final UiObject2 button = device.findObject(getPopUpButtonSelector());
assertNotNull("OK button not found", button);
button.click();
}
@@ -122,4 +114,27 @@
return (getInstrumentation().getContext().getResources().getConfiguration().uiMode
& Configuration.UI_MODE_TYPE_MASK) == Configuration.UI_MODE_TYPE_WATCH;
}
+
+ private String getSettingsPackageName() {
+ String settingsPackageName = "com.android.settings";
+ ResolveInfo resolveInfo = mPackageManager.resolveActivity(
+ new Intent(Settings.ACTION_SETTINGS), PackageManager.MATCH_SYSTEM_ONLY);
+ if (resolveInfo != null && resolveInfo.activityInfo != null) {
+ settingsPackageName = resolveInfo.activityInfo.packageName;
+ }
+ return settingsPackageName;
+ }
+
+ private BySelector getPopUpButtonSelector() {
+ return By.clazz(android.widget.Button.class.getName())
+ .res("android:id/button1")
+ .pkg(getSettingsPackageName());
+ }
+
+ private BySelector getPopUpImageSelector() {
+ final String settingsPackageName = getSettingsPackageName();
+ return By.clazz(android.widget.ImageView.class.getName())
+ .res(settingsPackageName + ":id/admin_support_icon")
+ .pkg(settingsPackageName);
+ }
}
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/Android.bp b/hostsidetests/devicepolicy/app/ManagedProfile/Android.bp
index c4f227c..4bd90fa 100644
--- a/hostsidetests/devicepolicy/app/ManagedProfile/Android.bp
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/Android.bp
@@ -31,7 +31,6 @@
"testng",
"androidx.legacy_legacy-support-v4",
],
- sdk_version: "test_current",
min_sdk_version: "27",
// tag this module as a cts test artifact
test_suites: [
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 3a3d7fb..5bcf4be 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
@@ -85,8 +85,8 @@
.add("isDeviceIdAttestationSupported")
.add("isUniqueDeviceAttestationSupported")
.add("wipeData")
- .add("getAutoTime")
- .add("setAutoTime")
+ .add("getAutoTimeEnabled")
+ .add("setAutoTimeEnabled")
.add("addUserRestriction")
.add("clearUserRestriction")
.add("getUserRestrictions")
@@ -169,10 +169,11 @@
public void testCannotCallAutoTimeMethodsOnParentProfile() {
assertThrows(SecurityException.class,
- () -> mParentDevicePolicyManager.setAutoTime(ADMIN_RECEIVER_COMPONENT, true));
+ () -> mParentDevicePolicyManager.setAutoTimeEnabled(ADMIN_RECEIVER_COMPONENT,
+ true));
assertThrows(SecurityException.class,
- () -> mParentDevicePolicyManager.getAutoTime(ADMIN_RECEIVER_COMPONENT));
+ () -> mParentDevicePolicyManager.getAutoTimeEnabled(ADMIN_RECEIVER_COMPONENT));
}
public void testCannotCallSetDefaultSmsApplicationOnParentProfile() {
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/SetPolicyActivity.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/SetPolicyActivity.java
index f59363b..091d1b9 100644
--- a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/SetPolicyActivity.java
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/SetPolicyActivity.java
@@ -23,8 +23,6 @@
import android.os.Process;
import android.util.Log;
-import com.android.cts.managedprofile.BaseManagedProfileTest;
-
/**
* Simple activity that adds or clears a user restriction depending on the value of the extras.
*/
@@ -54,14 +52,6 @@
handleIntent(intent);
}
- @Override
- public void onPause() {
- super.onPause();
- // Calling finish() here because doing it in onCreate(), onStart() or onResume() makes
- // "adb shell am start" timeout if using the -W option.
- finish();
- }
-
private void handleIntent(Intent intent) {
DevicePolicyManager dpm = (DevicePolicyManager)
getSystemService(Context.DEVICE_POLICY_SERVICE);
diff --git a/hostsidetests/devicepolicy/app/PackageInstaller/src/com/android/cts/packageinstaller/BasePackageInstallTest.java b/hostsidetests/devicepolicy/app/PackageInstaller/src/com/android/cts/packageinstaller/BasePackageInstallTest.java
index 4f0ce40..57cbab9 100644
--- a/hostsidetests/devicepolicy/app/PackageInstaller/src/com/android/cts/packageinstaller/BasePackageInstallTest.java
+++ b/hostsidetests/devicepolicy/app/PackageInstaller/src/com/android/cts/packageinstaller/BasePackageInstallTest.java
@@ -51,7 +51,7 @@
protected Context mContext;
protected UiDevice mDevice;
protected DevicePolicyManager mDevicePolicyManager;
- private PackageManager mPackageManager;
+ protected PackageManager mPackageManager;
private PackageInstaller mPackageInstaller;
private PackageInstaller.Session mSession;
protected boolean mCallbackReceived;
diff --git a/hostsidetests/devicepolicy/app/PackageInstaller/src/com/android/cts/packageinstaller/ManualPackageInstallTest.java b/hostsidetests/devicepolicy/app/PackageInstaller/src/com/android/cts/packageinstaller/ManualPackageInstallTest.java
index 88c3df9..3057273 100644
--- a/hostsidetests/devicepolicy/app/PackageInstaller/src/com/android/cts/packageinstaller/ManualPackageInstallTest.java
+++ b/hostsidetests/devicepolicy/app/PackageInstaller/src/com/android/cts/packageinstaller/ManualPackageInstallTest.java
@@ -18,6 +18,9 @@
import android.content.Intent;
import android.content.pm.PackageInstaller;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.provider.Settings;
import android.support.test.uiautomator.By;
import android.support.test.uiautomator.BySelector;
import android.support.test.uiautomator.UiObject2;
@@ -32,14 +35,6 @@
private static final int AUTOMATOR_WAIT_TIMEOUT = 5000;
private static final int INSTALL_WAIT_TIME = 5000;
- private static final BySelector POPUP_BUTTON_SELECTOR = By
- .clazz(android.widget.Button.class.getName())
- .res("android:id/button1")
- .pkg("com.android.settings");
- private static final BySelector POPUP_IMAGE_SELECTOR = By
- .clazz(android.widget.ImageView.class.getName())
- .res("com.android.settings:id/admin_support_icon")
- .pkg("com.android.settings");
private static final BySelector INSTALL_BUTTON_SELECTOR = By.text(Pattern.compile("Install",
Pattern.CASE_INSENSITIVE));
@@ -106,12 +101,35 @@
}
private void automateDismissInstallBlockedDialog() {
- mDevice.wait(Until.hasObject(POPUP_IMAGE_SELECTOR), AUTOMATOR_WAIT_TIMEOUT);
- UiObject2 icon = mDevice.findObject(POPUP_IMAGE_SELECTOR);
+ mDevice.wait(Until.hasObject(getPopUpImageSelector()), AUTOMATOR_WAIT_TIMEOUT);
+ UiObject2 icon = mDevice.findObject(getPopUpImageSelector());
assertNotNull("Policy transparency dialog icon not found", icon);
// "OK" button only present in the dialog if it is blocked by policy.
- UiObject2 button = mDevice.findObject(POPUP_BUTTON_SELECTOR);
+ UiObject2 button = mDevice.findObject(getPopUpButtonSelector());
assertNotNull("OK button not found", button);
button.click();
}
+
+ private String getSettingsPackageName() {
+ String settingsPackageName = "com.android.settings";
+ ResolveInfo resolveInfo = mPackageManager.resolveActivity(
+ new Intent(Settings.ACTION_SETTINGS), PackageManager.MATCH_SYSTEM_ONLY);
+ if (resolveInfo != null && resolveInfo.activityInfo != null) {
+ settingsPackageName = resolveInfo.activityInfo.packageName;
+ }
+ return settingsPackageName;
+ }
+
+ private BySelector getPopUpButtonSelector() {
+ return By.clazz(android.widget.Button.class.getName())
+ .res("android:id/button1")
+ .pkg(getSettingsPackageName());
+ }
+
+ private BySelector getPopUpImageSelector() {
+ final String settingsPackageName = getSettingsPackageName();
+ return By.clazz(android.widget.ImageView.class.getName())
+ .res(settingsPackageName + ":id/admin_support_icon")
+ .pkg(settingsPackageName);
+ }
}
diff --git a/hostsidetests/devicepolicy/app/SimpleApp/AndroidManifest.xml b/hostsidetests/devicepolicy/app/SimpleApp/AndroidManifest.xml
index 5e563d4..a25a1ee 100644
--- a/hostsidetests/devicepolicy/app/SimpleApp/AndroidManifest.xml
+++ b/hostsidetests/devicepolicy/app/SimpleApp/AndroidManifest.xml
@@ -73,6 +73,14 @@
</intent-filter>
</service>
+ <service android:name=".SimpleService6" android:exported="true"
+ android:isolatedProcess="true">
+ <intent-filter>
+ <action android:name="com.android.cts.launchertests.simpleapp.EXIT_ACTION" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ </service>
+
<receiver android:name=".SimpleReceiverStartService" android:exported="true">
</receiver>
<receiver android:name=".SimpleReceiver" android:exported="true">
diff --git a/hostsidetests/devicepolicy/app/SimpleApp/src/com/android/cts/launcherapps/simpleapp/SimpleService4.java b/hostsidetests/devicepolicy/app/SimpleApp/src/com/android/cts/launcherapps/simpleapp/SimpleService4.java
index 43fb201..7bcccc5 100644
--- a/hostsidetests/devicepolicy/app/SimpleApp/src/com/android/cts/launcherapps/simpleapp/SimpleService4.java
+++ b/hostsidetests/devicepolicy/app/SimpleApp/src/com/android/cts/launcherapps/simpleapp/SimpleService4.java
@@ -16,6 +16,7 @@
package com.android.cts.launcherapps.simpleapp;
+import android.app.ActivityManager;
import android.app.Service;
import android.content.ContentProviderClient;
import android.content.ContentResolver;
@@ -32,6 +33,10 @@
import android.system.OsConstants;
import android.util.Log;
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.io.IOException;
+
/**
* A simple service which accepts various test command.
*/
@@ -43,6 +48,7 @@
private static final String EXTRA_ACTION = "action";
private static final String EXTRA_MESSENGER = "messenger";
private static final String EXTRA_PROCESS_NAME = "process";
+ private static final String EXTRA_COOKIE = "cookie";
private static final String STUB_PROVIDER_AUTHORITY =
"com.android.cts.launcherapps.simpleapp.provider";
@@ -73,6 +79,7 @@
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
sendPidBack(intent);
+ setCookieIfNeeded(intent);
// perform the action after return from here,
// make a delay, otherwise the system might try to restart the service
// if the process dies before the system realize it's asking for START_NOT_STICKY.
@@ -86,7 +93,11 @@
}
protected String getProcessName() {
- return getPackageName();
+ try (BufferedReader reader = new BufferedReader(new FileReader("/proc/self/cmdline"))) {
+ return reader.readLine().trim();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
}
private void sendPidBack(Intent intent) {
@@ -143,4 +154,12 @@
}
}
}
+
+ private void setCookieIfNeeded(final Intent intent) {
+ if (intent.hasExtra(EXTRA_COOKIE)) {
+ byte[] cookie = intent.getByteArrayExtra(EXTRA_COOKIE);
+ ActivityManager am = getSystemService(ActivityManager.class);
+ am.setProcessStateSummary(cookie);
+ }
+ }
}
diff --git a/hostsidetests/devicepolicy/app/SimpleApp/src/com/android/cts/launcherapps/simpleapp/SimpleService5.java b/hostsidetests/devicepolicy/app/SimpleApp/src/com/android/cts/launcherapps/simpleapp/SimpleService5.java
index 03cd807..0945a6a 100644
--- a/hostsidetests/devicepolicy/app/SimpleApp/src/com/android/cts/launcherapps/simpleapp/SimpleService5.java
+++ b/hostsidetests/devicepolicy/app/SimpleApp/src/com/android/cts/launcherapps/simpleapp/SimpleService5.java
@@ -20,8 +20,4 @@
* A simple service which extends SimpleService4
*/
public class SimpleService5 extends SimpleService4 {
- @Override
- protected String getProcessName() {
- return getPackageName() + ":remote";
- }
}
diff --git a/apps/CtsVerifier/jni/audio_loopback/audio_utils/roundup.h b/hostsidetests/devicepolicy/app/SimpleApp/src/com/android/cts/launcherapps/simpleapp/SimpleService6.java
similarity index 65%
rename from apps/CtsVerifier/jni/audio_loopback/audio_utils/roundup.h
rename to hostsidetests/devicepolicy/app/SimpleApp/src/com/android/cts/launcherapps/simpleapp/SimpleService6.java
index ad34289..82df88b 100644
--- a/apps/CtsVerifier/jni/audio_loopback/audio_utils/roundup.h
+++ b/hostsidetests/devicepolicy/app/SimpleApp/src/com/android/cts/launcherapps/simpleapp/SimpleService6.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -14,18 +14,10 @@
* limitations under the License.
*/
-#ifndef ANDROID_AUDIO_ROUNDUP_H
-#define ANDROID_AUDIO_ROUNDUP_H
+package com.android.cts.launcherapps.simpleapp;
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// Round up to the next highest power of 2
-unsigned roundup(unsigned v);
-
-#ifdef __cplusplus
+/**
+ * A simple service which extends SimpleService4, but runs as isolated.
+ */
+public class SimpleService6 extends SimpleService4 {
}
-#endif
-
-#endif // ANDROID_AUDIO_ROUNDUP_H
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java
index d393b98..a447f63 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java
@@ -1569,7 +1569,7 @@
@Test
public void testPrintingPolicy() throws Exception {
- if (!mHasFeature) {
+ if (!mHasFeature || !hasDeviceFeature("android.software.print")) {
return;
}
installAppAsUser(PRINTING_APP_APK, mUserId);
@@ -1944,12 +1944,12 @@
}
@Test
- public void testSetAutoTime() throws Exception {
+ public void testSetAutoTimeEnabled() throws Exception {
if (!mHasFeature) {
return;
}
assertMetricsLogged(getDevice(), () -> {
- executeDeviceTestMethod(".DevicePolicyLoggingTest", "testSetAutoTime");
+ executeDeviceTestMethod(".DevicePolicyLoggingTest", "testSetAutoTimeEnabled");
}, new DevicePolicyEventWrapper.Builder(EventId.SET_AUTO_TIME_VALUE)
.setAdminPackageName(DEVICE_ADMIN_PKG)
.setBoolean(true)
@@ -1961,12 +1961,12 @@
}
@Test
- public void testSetAutoTimeZone() throws Exception {
+ public void testSetAutoTimeZoneEnabled() throws Exception {
if (!mHasFeature) {
return;
}
assertMetricsLogged(getDevice(), () -> {
- executeDeviceTestMethod(".TimeManagementTest", "testSetAutoTimeZone");
+ executeDeviceTestMethod(".TimeManagementTest", "testSetAutoTimeZoneEnabled");
}, new DevicePolicyEventWrapper.Builder(EventId.SET_AUTO_TIME_ZONE_VALUE)
.setAdminPackageName(DEVICE_ADMIN_PKG)
.setBoolean(true)
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
index e45e647..303baec 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
@@ -967,28 +967,32 @@
}
@Test
- public void testSetProtectedPackages() throws Exception {
+ public void testSetUserControlDisabledPackages() throws Exception {
if (!mHasFeature) {
return;
}
try {
installAppAsUser(SIMPLE_APP_APK, mPrimaryUserId);
assertMetricsLogged(getDevice(),
- () -> executeDeviceTestMethod(".ProtectedPackagesTest",
- "testSetProtectedPackages"),
- new DevicePolicyEventWrapper.Builder(EventId.SET_PACKAGES_PROTECTED_VALUE)
+ () -> executeDeviceTestMethod(".UserControlDisabledPackagesTest",
+ "testSetUserControlDisabledPackages"),
+ new DevicePolicyEventWrapper.Builder(
+ EventId.SET_USER_CONTROL_DISABLED_PACKAGES_VALUE)
.setAdminPackageName(DEVICE_OWNER_PKG)
.setStrings(new String[] {SIMPLE_APP_PKG})
.build());
forceStopPackageForUser(SIMPLE_APP_PKG, mPrimaryUserId);
- executeDeviceTestMethod(".ProtectedPackagesTest", "testForceStopForProtectedPackages");
+ executeDeviceTestMethod(".UserControlDisabledPackagesTest",
+ "testForceStopWithUserControlDisabled");
// Reboot and verify protected packages are persisted
rebootAndWaitUntilReady();
- executeDeviceTestMethod(".ProtectedPackagesTest", "testForceStopForProtectedPackages");
- executeDeviceTestMethod(".ProtectedPackagesTest", "testClearProtectedPackages");
+ executeDeviceTestMethod(".UserControlDisabledPackagesTest",
+ "testForceStopWithUserControlDisabled");
+ executeDeviceTestMethod(".UserControlDisabledPackagesTest",
+ "testClearSetUserControlDisabledPackages");
forceStopPackageForUser(SIMPLE_APP_PKG, mPrimaryUserId);
- executeDeviceTestMethod(".ProtectedPackagesTest",
- "testForceStopForUnprotectedPackages");
+ executeDeviceTestMethod(".UserControlDisabledPackagesTest",
+ "testForceStopWithUserControlEnabled");
} finally {
getDevice().uninstallPackage(SIMPLE_APP_APK);
}
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedManagedProfileOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedManagedProfileOwnerTest.java
index 51a312b..7a61083 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedManagedProfileOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedManagedProfileOwnerTest.java
@@ -200,14 +200,14 @@
@Override
@Test
- public void testSetAutoTime() {
+ public void testSetAutoTimeEnabled() {
// Managed profile owner cannot set auto time unless it is called by the profile owner of
// an organization-owned managed profile.
}
@Override
@Test
- public void testSetAutoTimeZone() {
+ public void testSetAutoTimeZoneEnabled() {
// Managed profile owner cannot set auto time zone unless it is called by the profile
// owner of an organization-owned managed profile.
}
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedProfileOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedProfileOwnerTest.java
index 2da4cba..66b2630 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedProfileOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedProfileOwnerTest.java
@@ -101,7 +101,7 @@
@Override
@Test
- public void testSetAutoTimeZone() {
+ public void testSetAutoTimeZoneEnabled() {
// Profile owner cannot set auto time zone unless it is called by the profile
// owner of an organization-owned managed profile or a profile owner on user 0.
}
diff --git a/hostsidetests/gputools/apps/jni/android_gputools_cts_RootlessGpuDebug.cpp b/hostsidetests/gputools/apps/jni/android_gputools_cts_RootlessGpuDebug.cpp
index 8a27b9e..f62a583 100644
--- a/hostsidetests/gputools/apps/jni/android_gputools_cts_RootlessGpuDebug.cpp
+++ b/hostsidetests/gputools/apps/jni/android_gputools_cts_RootlessGpuDebug.cpp
@@ -17,13 +17,15 @@
#define LOG_TAG "RootlessGpuDebug"
+#include <string>
+#include <vector>
+
#include <EGL/egl.h>
#include <GLES3/gl3.h>
#include <android/log.h>
#include <android/native_window.h>
#include <jni.h>
#include <vulkan/vulkan.h>
-#include <string>
#define ALOGI(msg, ...) \
__android_log_print(ANDROID_LOG_INFO, LOG_TAG, (msg), __VA_ARGS__)
@@ -39,6 +41,22 @@
std::string initVulkan() {
std::string result = "";
+ {
+ uint32_t count = 0;
+ vkEnumerateInstanceExtensionProperties(nullptr, &count, nullptr);
+ if (count > 0) {
+ std::vector<VkExtensionProperties> properties(count);
+ vkEnumerateInstanceExtensionProperties(nullptr, &count,
+ properties.data());
+ for (uint32_t i = 0; i < count; ++i) {
+ if (!strcmp("VK_EXT_debug_utils", properties[i].extensionName)) {
+ ALOGI("VK_EXT_debug_utils: %u", properties[i].specVersion);
+ break;
+ }
+ }
+ }
+ }
+
const VkApplicationInfo app_info = {
VK_STRUCTURE_TYPE_APPLICATION_INFO,
nullptr, // pNext
diff --git a/hostsidetests/gputools/layers/Android.bp b/hostsidetests/gputools/layers/Android.bp
index 9d12a7b..f0ee2c9 100644
--- a/hostsidetests/gputools/layers/Android.bp
+++ b/hostsidetests/gputools/layers/Android.bp
@@ -25,8 +25,6 @@
shared_libs: [
"libandroid",
"libvulkan",
- "libEGL",
- "libGLESv3",
"liblog",
],
stl: "c++_shared",
@@ -46,8 +44,6 @@
shared_libs: [
"libandroid",
"libvulkan",
- "libEGL",
- "libGLESv3",
"liblog",
],
stl: "c++_shared",
@@ -67,8 +63,46 @@
shared_libs: [
"libandroid",
"libvulkan",
- "libEGL",
- "libGLESv3",
+ "liblog",
+ ],
+ stl: "c++_shared",
+ sdk_version: "current",
+}
+
+cc_test_library {
+ name: "libVkLayer_nullLayerD",
+ gtest: false,
+ srcs: ["jni/nullLayer.cpp"],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-fvisibility=hidden",
+ "-DLAYERNAME=D",
+ "-DDEBUGUTILSPECVERSION=1",
+ ],
+ shared_libs: [
+ "libandroid",
+ "libvulkan",
+ "liblog",
+ ],
+ stl: "c++_shared",
+ sdk_version: "current",
+}
+
+cc_test_library {
+ name: "libVkLayer_nullLayerE",
+ gtest: false,
+ srcs: ["jni/nullLayer.cpp"],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-fvisibility=hidden",
+ "-DLAYERNAME=E",
+ "-DDEBUGUTILSPECVERSION=2",
+ ],
+ shared_libs: [
+ "libandroid",
+ "libvulkan",
"liblog",
],
stl: "c++_shared",
@@ -149,6 +183,8 @@
"libVkLayer_nullLayerA",
"libVkLayer_nullLayerB",
"libVkLayer_nullLayerC",
+ "libVkLayer_nullLayerD",
+ "libVkLayer_nullLayerE",
],
use_embedded_native_libs: false,
stl: "c++_shared",
diff --git a/hostsidetests/gputools/layers/jni/nullLayer.cpp b/hostsidetests/gputools/layers/jni/nullLayer.cpp
index c5f84ca..f772b36 100644
--- a/hostsidetests/gputools/layers/jni/nullLayer.cpp
+++ b/hostsidetests/gputools/layers/jni/nullLayer.cpp
@@ -14,19 +14,28 @@
* limitations under the License.
*/
-#include <android/log.h>
#include <cstring>
-#include <vulkan/vulkan.h>
+#include <string>
+
#include "vk_layer_interface.h"
+#include <android/log.h>
+#include <vulkan/vulkan.h>
#define xstr(a) str(a)
#define str(a) #a
-#define LOG_TAG "nullLayer" xstr(LAYERNAME)
+#define LAYER_FULL_NAME "VK_LAYER_ANDROID_nullLayer" xstr(LAYERNAME)
+#define LOG_TAG LAYER_FULL_NAME
#define ALOGI(msg, ...) \
__android_log_print(ANDROID_LOG_INFO, LOG_TAG, (msg), __VA_ARGS__)
+#ifdef DEBUGUTILSPECVERSION
+const VkExtensionProperties debug_utils_extension = {
+ "VK_EXT_debug_utils",
+ static_cast<uint32_t>(std::atoi(xstr(DEBUGUTILSPECVERSION))),
+};
+#endif
// Announce if anything loads this layer. LAYERNAME is defined in Android.mk
class StaticLogMessage {
@@ -35,8 +44,8 @@
ALOGI("%s", msg);
}
};
-StaticLogMessage g_initMessage("nullLayer" xstr(LAYERNAME) " loaded");
-
+StaticLogMessage
+ g_initMessage("VK_LAYER_ANDROID_nullLayer" xstr(LAYERNAME) " loaded");
namespace {
@@ -68,7 +77,10 @@
}
static const VkLayerProperties LAYER_PROPERTIES = {
- "VK_LAYER_ANDROID_nullLayer" xstr(LAYERNAME), VK_MAKE_VERSION(1, 0, VK_HEADER_VERSION), 1, "Layer: nullLayer" xstr(LAYERNAME),
+ LAYER_FULL_NAME,
+ VK_MAKE_VERSION(1, 0, VK_HEADER_VERSION),
+ 1,
+ "Layer: nullLayer" xstr(LAYERNAME),
};
VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
@@ -82,7 +94,12 @@
VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceExtensionProperties(const char* /* pLayerName */, uint32_t *pCount,
VkExtensionProperties *pProperties) {
- return getProperties<VkExtensionProperties>(0, NULL, pCount, pProperties);
+#ifdef DEBUGUTILSPECVERSION
+ return getProperties<VkExtensionProperties>(1, &debug_utils_extension, pCount,
+ pProperties);
+#else
+ return getProperties<VkExtensionProperties>(0, NULL, pCount, pProperties);
+#endif
}
VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice /* physicalDevice */, const char* /* pLayerName */,
@@ -94,16 +111,13 @@
const VkDeviceCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkDevice* pDevice) {
-
VkLayerDeviceCreateInfo *layerCreateInfo = (VkLayerDeviceCreateInfo*)pCreateInfo->pNext;
-
- const char* msg = "nullCreateDevice called in nullLayer" xstr(LAYERNAME);
+ const char *msg = "nullCreateDevice called in " LAYER_FULL_NAME;
ALOGI("%s", msg);
// Step through the pNext chain until we get to the link function
while(layerCreateInfo && (layerCreateInfo->sType != VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO ||
layerCreateInfo->function != VK_LAYER_FUNCTION_LINK)) {
-
layerCreateInfo = (VkLayerDeviceCreateInfo *)layerCreateInfo->pNext;
}
@@ -131,16 +145,13 @@
VKAPI_ATTR VkResult VKAPI_CALL nullCreateInstance(const VkInstanceCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkInstance* pInstance) {
-
VkLayerInstanceCreateInfo *layerCreateInfo = (VkLayerInstanceCreateInfo *)pCreateInfo->pNext;
-
- const char* msg = "nullCreateInstance called in nullLayer" xstr(LAYERNAME);
+ const char *msg = "nullCreateInstance called in " LAYER_FULL_NAME;
ALOGI("%s", msg);
// Step through the pNext chain until we get to the link function
while(layerCreateInfo && (layerCreateInfo->sType != VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO ||
layerCreateInfo->function != VK_LAYER_FUNCTION_LINK)) {
-
layerCreateInfo = (VkLayerInstanceCreateInfo *)layerCreateInfo->pNext;
}
diff --git a/hostsidetests/gputools/src/android/gputools/cts/CtsRootlessGpuDebugHostTest.java b/hostsidetests/gputools/src/android/gputools/cts/CtsRootlessGpuDebugHostTest.java
index fb14756..4ec4ef8 100644
--- a/hostsidetests/gputools/src/android/gputools/cts/CtsRootlessGpuDebugHostTest.java
+++ b/hostsidetests/gputools/src/android/gputools/cts/CtsRootlessGpuDebugHostTest.java
@@ -60,6 +60,9 @@
// - Ensure we can still use system properties if no layers loaded via Settings (testSystemPropertyEnableVulkan)
// - Ensure we can find layers in separate specified app and load them in a debuggable app (testDebugLayerLoadExternalVulkan)
// - Ensure we can find layers in separate specified app and load them in an injectLayers app (testInjectLayerLoadExternalVulkan)
+ // - Ensure we can enumerate the instance extension advertised by implicitly enabled layer (testInstanceExtensionPropertiesFromImplicitLayerVulkanBasic)
+ // - Ensure we can only enumerate first instance extension closest to application
+ // when multiple implicitly enabled layers advertise the same extension (testInstanceExtensionPropertiesFromImplicitLayerVulkanMultipleLayers)
// Negative Vulkan tests
// - Ensure we cannot push a layer to non-debuggable app (testReleaseLayerLoadVulkan)
// - Ensure non-debuggable app ignores the new Settings (testReleaseLayerLoadVulkan)
@@ -87,19 +90,20 @@
// Positive combined tests
// - Ensure we can load Vulkan and GLES layers at the same time, from multiple external apps (testMultipleExternalApps)
-
-
private static final String CLASS = "RootlessGpuDebugDeviceActivity";
private static final String ACTIVITY = "android.rootlessgpudebug.app.RootlessGpuDebugDeviceActivity";
- private static final String LAYER_A = "nullLayerA";
- private static final String LAYER_B = "nullLayerB";
- private static final String LAYER_C = "nullLayerC";
- private static final String LAYER_A_LIB = "libVkLayer_" + LAYER_A + ".so";
- private static final String LAYER_B_LIB = "libVkLayer_" + LAYER_B + ".so";
- private static final String LAYER_C_LIB = "libVkLayer_" + LAYER_C + ".so";
- private static final String LAYER_A_NAME = "VK_LAYER_ANDROID_" + LAYER_A;
- private static final String LAYER_B_NAME = "VK_LAYER_ANDROID_" + LAYER_B;
- private static final String LAYER_C_NAME = "VK_LAYER_ANDROID_" + LAYER_C;
+ private static final String VK_LAYER_LIB_PREFIX = "libVkLayer_nullLayer";
+ private static final String VK_LAYER_A_LIB = VK_LAYER_LIB_PREFIX + "A.so";
+ private static final String VK_LAYER_B_LIB = VK_LAYER_LIB_PREFIX + "B.so";
+ private static final String VK_LAYER_C_LIB = VK_LAYER_LIB_PREFIX + "C.so";
+ private static final String VK_LAYER_D_LIB = VK_LAYER_LIB_PREFIX + "D.so";
+ private static final String VK_LAYER_E_LIB = VK_LAYER_LIB_PREFIX + "E.so";
+ private static final String VK_LAYER_NAME_PREFIX = "VK_LAYER_ANDROID_nullLayer";
+ private static final String VK_LAYER_A = VK_LAYER_NAME_PREFIX + "A";
+ private static final String VK_LAYER_B = VK_LAYER_NAME_PREFIX + "B";
+ private static final String VK_LAYER_C = VK_LAYER_NAME_PREFIX + "C";
+ private static final String VK_LAYER_D = VK_LAYER_NAME_PREFIX + "D";
+ private static final String VK_LAYER_E = VK_LAYER_NAME_PREFIX + "E";
private static final String DEBUG_APP = "android.rootlessgpudebug.DEBUG.app";
private static final String RELEASE_APP = "android.rootlessgpudebug.RELEASE.app";
private static final String INJECT_APP = "android.rootlessgpudebug.INJECT.app";
@@ -117,14 +121,13 @@
private static final String GLES_LAYER_B_LIB = "libGLES_" + GLES_LAYER_B + ".so";
private static final String GLES_LAYER_C_LIB = "libGLES_" + GLES_LAYER_C + ".so";
- private static boolean initialized = false;
-
// This is how long we'll scan the log for a result before giving up. This limit will only
// be reached if something has gone wrong
private static final long LOG_SEARCH_TIMEOUT_MS = 5000;
-
private static final long SETTING_APPLY_TIMEOUT_MS = 5000;
+ private static boolean initialized = false;
+
private String removeWhitespace(String input) {
return input.replaceAll(System.getProperty("line.separator"), "").trim();
}
@@ -172,6 +175,41 @@
}
/**
+ * Check that the layer is loaded by only checking the log after startTime.
+ */
+ private void assertVkLayerLoading(String startTime, String layerName, boolean loaded) throws Exception {
+ String searchString = "nullCreateInstance called in " + layerName;
+ LogScanResult result = scanLog(TAG + "," + layerName, searchString, startTime);
+ if (loaded) {
+ Assert.assertTrue(layerName + " was not loaded", result.found);
+ } else {
+ Assert.assertFalse(layerName + " was loaded", result.found);
+ }
+ }
+
+ /**
+ * Check that the layer is enumerated by only checking the log after startTime.
+ */
+ private void assertVkLayerEnumeration(String startTime, String layerName, boolean enumerated) throws Exception {
+ String searchString = layerName + " loaded";
+ LogScanResult result = scanLog(TAG + "," + layerName, searchString, startTime);
+ if (enumerated) {
+ Assert.assertTrue(layerName + " was not enumerated", result.found);
+ } else {
+ Assert.assertFalse(layerName + " was enumerated", result.found);
+ }
+ }
+
+ /**
+ * Check whether an extension is properly advertised by only checking the log after startTime.
+ */
+ private void assertVkExtension(String startTime, String extensionName, int specVersion) throws Exception {
+ String searchString = extensionName + ": " + specVersion;
+ LogScanResult result = scanLog(TAG + ",RootlessGpuDebug", searchString, startTime);
+ Assert.assertTrue(extensionName + "with spec version: " + specVersion + " was not advertised", result.found);
+ }
+
+ /**
* Simple helper class for returning multiple results
*/
public class LogScanResult {
@@ -242,9 +280,9 @@
getDevice().executeAdbCommand("shell", "am", "force-stop", DEBUG_APP);
getDevice().executeAdbCommand("shell", "am", "force-stop", RELEASE_APP);
getDevice().executeAdbCommand("shell", "am", "force-stop", INJECT_APP);
- getDevice().executeAdbCommand("shell", "rm", "-f", "/data/local/tmp/" + LAYER_A_LIB);
- getDevice().executeAdbCommand("shell", "rm", "-f", "/data/local/tmp/" + LAYER_B_LIB);
- getDevice().executeAdbCommand("shell", "rm", "-f", "/data/local/tmp/" + LAYER_C_LIB);
+ getDevice().executeAdbCommand("shell", "rm", "-f", "/data/local/tmp/" + VK_LAYER_A_LIB);
+ getDevice().executeAdbCommand("shell", "rm", "-f", "/data/local/tmp/" + VK_LAYER_B_LIB);
+ getDevice().executeAdbCommand("shell", "rm", "-f", "/data/local/tmp/" + VK_LAYER_C_LIB);
getDevice().executeAdbCommand("shell", "rm", "-f", "/data/local/tmp/" + GLES_LAYER_A_LIB);
getDevice().executeAdbCommand("shell", "rm", "-f", "/data/local/tmp/" + GLES_LAYER_B_LIB);
getDevice().executeAdbCommand("shell", "rm", "-f", "/data/local/tmp/" + GLES_LAYER_C_LIB);
@@ -282,20 +320,20 @@
// Set up layers to be loaded
applySetting("enable_gpu_debug_layers", "1");
applySetting("gpu_debug_app", DEBUG_APP);
- applySetting("gpu_debug_layers", LAYER_A_NAME + ":" + LAYER_B_NAME);
+ applySetting("gpu_debug_layers", VK_LAYER_A + ":" + VK_LAYER_B);
// Copy the layers from our LAYERS APK to tmp
- setupLayer(LAYER_A_LIB, LAYERS_APP);
- setupLayer(LAYER_B_LIB, LAYERS_APP);
+ setupLayer(VK_LAYER_A_LIB, LAYERS_APP);
+ setupLayer(VK_LAYER_B_LIB, LAYERS_APP);
// Copy them over to our DEBUG app
- getDevice().executeAdbCommand("shell", "cat", "/data/local/tmp/" + LAYER_A_LIB, "|",
+ getDevice().executeAdbCommand("shell", "cat", "/data/local/tmp/" + VK_LAYER_A_LIB, "|",
"run-as", DEBUG_APP, "--user", Integer.toString(getDevice().getCurrentUser()),
- "sh", "-c", "\'cat", ">", LAYER_A_LIB, ";", "chmod", "700", LAYER_A_LIB + "\'");
- getDevice().executeAdbCommand("shell", "cat", "/data/local/tmp/" + LAYER_B_LIB, "|",
+ "sh", "-c", "\'cat", ">", VK_LAYER_A_LIB, ";", "chmod", "700", VK_LAYER_A_LIB + "\'");
+ getDevice().executeAdbCommand("shell", "cat", "/data/local/tmp/" + VK_LAYER_B_LIB, "|",
"run-as", DEBUG_APP, "--user", Integer.toString(getDevice().getCurrentUser()),
- "sh", "-c", "\'cat", ">", LAYER_B_LIB, ";", "chmod", "700", LAYER_B_LIB + "\'");
+ "sh", "-c", "\'cat", ">", VK_LAYER_B_LIB, ";", "chmod", "700", VK_LAYER_B_LIB + "\'");
// Kick off our DEBUG app
@@ -303,12 +341,12 @@
getDevice().executeAdbCommand("shell", "am", "start", "-n", DEBUG_APP + "/" + ACTIVITY);
// Check that both layers were loaded, in the correct order
- String searchStringA = "nullCreateInstance called in " + LAYER_A;
- LogScanResult resultA = scanLog(TAG + "," + LAYER_A + "," + LAYER_B, searchStringA, appStartTime);
+ String searchStringA = "nullCreateInstance called in " + VK_LAYER_A;
+ LogScanResult resultA = scanLog(TAG + "," + VK_LAYER_A + "," + VK_LAYER_B, searchStringA, appStartTime);
Assert.assertTrue("LayerA was not loaded", resultA.found);
- String searchStringB = "nullCreateInstance called in " + LAYER_B;
- LogScanResult resultB = scanLog(TAG + "," + LAYER_A + "," + LAYER_B, searchStringB, appStartTime);
+ String searchStringB = "nullCreateInstance called in " + VK_LAYER_B;
+ LogScanResult resultB = scanLog(TAG + "," + VK_LAYER_A + "," + VK_LAYER_B, searchStringB, appStartTime);
Assert.assertTrue("LayerB was not loaded", resultB.found);
Assert.assertTrue("LayerA should be loaded before LayerB", resultA.lineNumber < resultB.lineNumber);
@@ -318,24 +356,22 @@
// Set up a layers to be loaded for RELEASE or INJECT app
applySetting("enable_gpu_debug_layers", "1");
applySetting("gpu_debug_app", APP_NAME);
- applySetting("gpu_debug_layers", LAYER_A_NAME + ":" + LAYER_B_NAME);
+ applySetting("gpu_debug_layers", VK_LAYER_A + ":" + VK_LAYER_B);
// Copy a layer from our LAYERS APK to tmp
- setupLayer(LAYER_A_LIB, LAYERS_APP);
+ setupLayer(VK_LAYER_A_LIB, LAYERS_APP);
// Attempt to copy them over to our RELEASE or INJECT app (this should fail)
- getDevice().executeAdbCommand("shell", "cat", "/data/local/tmp/" + LAYER_A_LIB, "|",
+ getDevice().executeAdbCommand("shell", "cat", "/data/local/tmp/" + VK_LAYER_A_LIB, "|",
"run-as", APP_NAME, "--user", Integer.toString(getDevice().getCurrentUser()),
- "sh", "-c", "\'cat", ">", LAYER_A_LIB, ";", "chmod", "700", LAYER_A_LIB + "\'", "||", "echo", "run-as", "failed");
+ "sh", "-c", "\'cat", ">", VK_LAYER_A_LIB, ";", "chmod", "700", VK_LAYER_A_LIB + "\'", "||", "echo", "run-as", "failed");
// Kick off our RELEASE app
String appStartTime = getTime();
getDevice().executeAdbCommand("shell", "am", "start", "-n", APP_NAME + "/" + ACTIVITY);
// Ensure we don't load the layer in base dir
- String searchStringA = LAYER_A_NAME + "loaded";
- LogScanResult resultA = scanLog(TAG + "," + LAYER_A, searchStringA, appStartTime);
- Assert.assertFalse("LayerA was enumerated", resultA.found);
+ assertVkLayerEnumeration(appStartTime, VK_LAYER_A, false);
}
/**
@@ -366,24 +402,22 @@
// Ensure the global layer enable settings is NOT enabled
applySetting("enable_gpu_debug_layers", "0");
applySetting("gpu_debug_app", DEBUG_APP);
- applySetting("gpu_debug_layers", LAYER_A_NAME);
+ applySetting("gpu_debug_layers", VK_LAYER_A);
// Copy a layer from our LAYERS APK to tmp
- setupLayer(LAYER_A_LIB, LAYERS_APP);
+ setupLayer(VK_LAYER_A_LIB, LAYERS_APP);
// Copy it over to our DEBUG app
- getDevice().executeAdbCommand("shell", "cat", "/data/local/tmp/" + LAYER_A_LIB, "|",
+ getDevice().executeAdbCommand("shell", "cat", "/data/local/tmp/" + VK_LAYER_A_LIB, "|",
"run-as", DEBUG_APP, "--user", Integer.toString(getDevice().getCurrentUser()),
- "sh", "-c", "\'cat", ">", LAYER_A_LIB, ";", "chmod", "700", LAYER_A_LIB + "\'");
+ "sh", "-c", "\'cat", ">", VK_LAYER_A_LIB, ";", "chmod", "700", VK_LAYER_A_LIB + "\'");
// Kick off our DEBUG app
String appStartTime = getTime();
getDevice().executeAdbCommand("shell", "am", "start", "-n", DEBUG_APP + "/" + ACTIVITY);
// Ensure we don't load the layer in base dir
- String searchStringA = LAYER_A_NAME + "loaded";
- LogScanResult resultA = scanLog(TAG + "," + LAYER_A, searchStringA, appStartTime);
- Assert.assertFalse("LayerA was enumerated", resultA.found);
+ assertVkLayerEnumeration(appStartTime, VK_LAYER_A, false);
}
/**
@@ -396,24 +430,22 @@
// Ensure the gpu_debug_app does not match what we launch
applySetting("enable_gpu_debug_layers", "1");
applySetting("gpu_debug_app", RELEASE_APP);
- applySetting("gpu_debug_layers", LAYER_A_NAME);
+ applySetting("gpu_debug_layers", VK_LAYER_A);
// Copy a layer from our LAYERS APK to tmp
- setupLayer(LAYER_A_LIB, LAYERS_APP);
+ setupLayer(VK_LAYER_A_LIB, LAYERS_APP);
// Copy it over to our DEBUG app
- getDevice().executeAdbCommand("shell", "cat", "/data/local/tmp/" + LAYER_A_LIB, "|",
+ getDevice().executeAdbCommand("shell", "cat", "/data/local/tmp/" + VK_LAYER_A_LIB, "|",
"run-as", DEBUG_APP, "--user", Integer.toString(getDevice().getCurrentUser()),
- "sh", "-c", "\'cat", ">", LAYER_A_LIB, ";", "chmod", "700", LAYER_A_LIB + "\'");
+ "sh", "-c", "\'cat", ">", VK_LAYER_A_LIB, ";", "chmod", "700", VK_LAYER_A_LIB + "\'");
// Kick off our DEBUG app
String appStartTime = getTime();
getDevice().executeAdbCommand("shell", "am", "start", "-n", DEBUG_APP + "/" + ACTIVITY);
// Ensure we don't load the layer in base dir
- String searchStringA = LAYER_A_NAME + "loaded";
- LogScanResult resultA = scanLog(TAG + "," + LAYER_A, searchStringA, appStartTime);
- Assert.assertFalse("LayerA was enumerated", resultA.found);
+ assertVkLayerEnumeration(appStartTime, VK_LAYER_A, false);
}
/**
@@ -429,21 +461,19 @@
applySetting("gpu_debug_layers", "foo");
// Copy a layer from our LAYERS APK to tmp
- setupLayer(LAYER_A_LIB, LAYERS_APP);
+ setupLayer(VK_LAYER_A_LIB, LAYERS_APP);
// Copy it over to our DEBUG app
- getDevice().executeAdbCommand("shell", "cat", "/data/local/tmp/" + LAYER_A_LIB, "|",
+ getDevice().executeAdbCommand("shell", "cat", "/data/local/tmp/" + VK_LAYER_A_LIB, "|",
"run-as", DEBUG_APP, "--user", Integer.toString(getDevice().getCurrentUser()),
- "sh", "-c", "\'cat", ">", LAYER_A_LIB, ";", "chmod", "700", LAYER_A_LIB + "\'");
+ "sh", "-c", "\'cat", ">", VK_LAYER_A_LIB, ";", "chmod", "700", VK_LAYER_A_LIB + "\'");
// Kick off our DEBUG app
String appStartTime = getTime();
getDevice().executeAdbCommand("shell", "am", "start", "-n", DEBUG_APP + "/" + ACTIVITY);
// Ensure layerA is not loaded
- String searchStringA = "nullCreateInstance called in " + LAYER_A;
- LogScanResult resultA = scanLog(TAG + "," + LAYER_A, searchStringA, appStartTime);
- Assert.assertFalse("LayerA was loaded", resultA.found);
+ assertVkLayerLoading(appStartTime, VK_LAYER_A, false);
}
/**
@@ -458,20 +488,15 @@
deleteSetting("gpu_debug_layers");
// Enable layerC (which is packaged with the RELEASE app) with system properties
- getDevice().executeAdbCommand("shell", "setprop", "debug.vulkan.layers " + LAYER_C_NAME);
+ getDevice().executeAdbCommand("shell", "setprop", "debug.vulkan.layers " + VK_LAYER_C);
// Kick off our RELEASE app
String appStartTime = getTime();
getDevice().executeAdbCommand("shell", "am", "start", "-n", RELEASE_APP + "/" + ACTIVITY);
// Check that only layerC was loaded
- String searchStringA = LAYER_A_NAME + "loaded";
- LogScanResult resultA = scanLog(TAG + "," + LAYER_A, searchStringA, appStartTime);
- Assert.assertFalse("LayerA was enumerated", resultA.found);
-
- String searchStringC = "nullCreateInstance called in " + LAYER_C;
- LogScanResult resultC = scanLog(TAG + "," + LAYER_C, searchStringC, appStartTime);
- Assert.assertTrue("LayerC was not loaded", resultC.found);
+ assertVkLayerEnumeration(appStartTime, VK_LAYER_A, false);
+ assertVkLayerLoading(appStartTime, VK_LAYER_C, true);
}
/**
@@ -483,44 +508,42 @@
// Set up layerA to be loaded, but not layerB
applySetting("enable_gpu_debug_layers", "1");
applySetting("gpu_debug_app", DEBUG_APP);
- applySetting("gpu_debug_layers", LAYER_A_NAME);
+ applySetting("gpu_debug_layers", VK_LAYER_A);
// Copy the layers from our LAYERS APK
- setupLayer(LAYER_A_LIB, LAYERS_APP);
- setupLayer(LAYER_B_LIB, LAYERS_APP);
+ setupLayer(VK_LAYER_A_LIB, LAYERS_APP);
+ setupLayer(VK_LAYER_B_LIB, LAYERS_APP);
// Copy them over to our DEBUG app
- getDevice().executeAdbCommand("shell", "cat", "/data/local/tmp/" + LAYER_A_LIB, "|",
+ getDevice().executeAdbCommand("shell", "cat", "/data/local/tmp/" + VK_LAYER_A_LIB, "|",
"run-as", DEBUG_APP, "--user", Integer.toString(getDevice().getCurrentUser()),
- "sh", "-c", "\'cat", ">", LAYER_A_LIB, ";", "chmod", "700", LAYER_A_LIB + "\'");
- getDevice().executeAdbCommand("shell", "cat", "/data/local/tmp/" + LAYER_B_LIB, "|",
+ "sh", "-c", "\'cat", ">", VK_LAYER_A_LIB, ";", "chmod", "700", VK_LAYER_A_LIB + "\'");
+ getDevice().executeAdbCommand("shell", "cat", "/data/local/tmp/" + VK_LAYER_B_LIB, "|",
"run-as", DEBUG_APP, "--user", Integer.toString(getDevice().getCurrentUser()),
- "sh", "-c", "\'cat", ">", LAYER_B_LIB, ";", "chmod", "700", LAYER_B_LIB + "\'");
+ "sh", "-c", "\'cat", ">", VK_LAYER_B_LIB, ";", "chmod", "700", VK_LAYER_B_LIB + "\'");
// Enable layerB with system properties
- getDevice().executeAdbCommand("shell", "setprop", "debug.vulkan.layers " + LAYER_B_NAME);
+ getDevice().executeAdbCommand("shell", "setprop", "debug.vulkan.layers " + VK_LAYER_B);
// Kick off our DEBUG app
String appStartTime = getTime();
getDevice().executeAdbCommand("shell", "am", "start", "-n", DEBUG_APP + "/" + ACTIVITY);
// Ensure only layerA is loaded
- String searchStringA = "nullCreateInstance called in " + LAYER_A;
- LogScanResult resultA = scanLog(TAG + "," + LAYER_A, searchStringA, appStartTime);
- Assert.assertTrue("LayerA was not loaded", resultA.found);
-
- String searchStringB = "nullCreateInstance called in " + LAYER_B;
- LogScanResult resultB = scanLog(TAG + "," + LAYER_B, searchStringB, appStartTime);
- Assert.assertFalse("LayerB was loaded", resultB.found);
+ assertVkLayerLoading(appStartTime, VK_LAYER_A, true);
+ assertVkLayerLoading(appStartTime, VK_LAYER_B, false);
}
-
- public void testLayerLoadExternalVulkan(final String APP_NAME) throws Exception {
+ /**
+ * The common functionality to load layers from an external package.
+ * Returns the app start time.
+ */
+ public String testLayerLoadExternalVulkan(final String APP_NAME, String layers) throws Exception {
// Set up layers to be loaded
applySetting("enable_gpu_debug_layers", "1");
applySetting("gpu_debug_app", APP_NAME);
- applySetting("gpu_debug_layers", LAYER_C_NAME);
+ applySetting("gpu_debug_layers", layers);
// Specify the external app that hosts layers
applySetting("gpu_debug_layer_app", LAYERS_APP);
@@ -529,10 +552,11 @@
String appStartTime = getTime();
getDevice().executeAdbCommand("shell", "am", "start", "-n", APP_NAME + "/" + ACTIVITY);
- // Check that our external layer was loaded
- String searchStringC = "nullCreateInstance called in " + LAYER_C;
- LogScanResult resultC = scanLog(TAG + "," + LAYER_C, searchStringC, appStartTime);
- Assert.assertTrue("LayerC was not loaded", resultC.found);
+ String[] layerNames = layers.split(":");
+ for (String layerName : layerNames) {
+ assertVkLayerLoading(appStartTime, layerName, true);
+ }
+ return appStartTime;
}
/**
@@ -540,7 +564,7 @@
*/
@Test
public void testDebugLayerLoadExternalVulkan() throws Exception {
- testLayerLoadExternalVulkan(DEBUG_APP);
+ testLayerLoadExternalVulkan(DEBUG_APP, VK_LAYER_C);
}
/**
@@ -548,7 +572,27 @@
*/
@Test
public void testInjectLayerLoadExternalVulkan() throws Exception {
- testLayerLoadExternalVulkan(INJECT_APP);
+ testLayerLoadExternalVulkan(INJECT_APP, VK_LAYER_C);
+ }
+
+ /**
+ * Test that the instance extension is advertised properly from the implicitly enabled layer.
+ */
+ @Test
+ public void testInstanceExtensionPropertiesFromImplicitLayerVulkanBasic() throws Exception {
+ String appStartTime = testLayerLoadExternalVulkan(DEBUG_APP, VK_LAYER_D);
+ assertVkExtension(appStartTime, "VK_EXT_debug_utils", 1);
+ }
+
+ /**
+ * Test that when there are multiple implicit layers are enabled, if there are several instance
+ * extensions with the same extension names advertised by multiple layers, only the extension
+ * that is closer to the application is advertised by the loader.
+ */
+ @Test
+ public void testInstanceExtensionPropertiesFromImplicitLayerVulkanMultipleLayers() throws Exception {
+ String appStartTime = testLayerLoadExternalVulkan(DEBUG_APP, VK_LAYER_E + ":" + VK_LAYER_D);
+ assertVkExtension(appStartTime, "VK_EXT_debug_utils", 2);
}
/**
@@ -820,7 +864,7 @@
// Set up layers to be loaded
applySetting("enable_gpu_debug_layers", "1");
applySetting("gpu_debug_app", DEBUG_APP);
- applySetting("gpu_debug_layers", LAYER_C_NAME);
+ applySetting("gpu_debug_layers", VK_LAYER_C);
applySetting("gpu_debug_layers_gles", GLES_LAYER_C_LIB);
// Specify multple external apps that host layers
@@ -831,9 +875,7 @@
getDevice().executeAdbCommand("shell", "am", "start", "-n", DEBUG_APP + "/" + ACTIVITY);
// Check that external layers were loaded from both apps
- String vulkanString = "nullCreateInstance called in " + LAYER_C;
- LogScanResult vulkanResult = scanLog(TAG + "," + LAYER_C, vulkanString, appStartTime);
- Assert.assertTrue(LAYER_C + " was not loaded", vulkanResult.found);
+ assertVkLayerLoading(appStartTime, VK_LAYER_C, true);
String glesString = "glesLayer_eglChooseConfig called in " + GLES_LAYER_C;
LogScanResult glesResult = scanLog(TAG + "," + GLES_LAYER_C, glesString, appStartTime);
diff --git a/hostsidetests/inputmethodservice/hostside/src/android/inputmethodservice/cts/hostside/InputMethodServiceLifecycleTest.java b/hostsidetests/inputmethodservice/hostside/src/android/inputmethodservice/cts/hostside/InputMethodServiceLifecycleTest.java
index ed4e672..644ba72 100644
--- a/hostsidetests/inputmethodservice/hostside/src/android/inputmethodservice/cts/hostside/InputMethodServiceLifecycleTest.java
+++ b/hostsidetests/inputmethodservice/hostside/src/android/inputmethodservice/cts/hostside/InputMethodServiceLifecycleTest.java
@@ -37,6 +37,7 @@
import android.platform.test.annotations.AppModeInstant;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
import org.junit.After;
import org.junit.Before;
@@ -50,7 +51,7 @@
* Test general lifecycle events around InputMethodService.
*/
@RunWith(DeviceJUnit4ClassRunner.class)
-public class InputMethodServiceLifecycleTest extends RebootFreeHostTestBase {
+public class InputMethodServiceLifecycleTest extends BaseHostJUnit4Test {
private static final long WAIT_TIMEOUT = TimeUnit.SECONDS.toMillis(1);
private static final long PACKAGE_OP_TIMEOUT = TimeUnit.SECONDS.toMillis(7);
diff --git a/hostsidetests/inputmethodservice/hostside/src/android/inputmethodservice/cts/hostside/MultiUserTest.java b/hostsidetests/inputmethodservice/hostside/src/android/inputmethodservice/cts/hostside/MultiUserTest.java
index 8fece56..f1e73a2 100644
--- a/hostsidetests/inputmethodservice/hostside/src/android/inputmethodservice/cts/hostside/MultiUserTest.java
+++ b/hostsidetests/inputmethodservice/hostside/src/android/inputmethodservice/cts/hostside/MultiUserTest.java
@@ -30,6 +30,7 @@
import android.platform.test.annotations.AppModeInstant;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
import com.android.tradefed.testtype.junit4.DeviceTestRunOptions;
import com.android.tradefed.util.CommandResult;
import com.android.tradefed.util.CommandStatus;
@@ -48,7 +49,7 @@
* Test IME APIs for multi-user environment.
*/
@RunWith(DeviceJUnit4ClassRunner.class)
-public class MultiUserTest extends RebootFreeHostTestBase {
+public class MultiUserTest extends BaseHostJUnit4Test {
private static final long USER_SWITCH_TIMEOUT = TimeUnit.SECONDS.toMillis(60);
private static final long USER_SWITCH_POLLING_INTERVAL = TimeUnit.MILLISECONDS.toMillis(100);
private static final long IME_COMMAND_TIMEOUT = TimeUnit.SECONDS.toMillis(7);
diff --git a/hostsidetests/inputmethodservice/hostside/src/android/inputmethodservice/cts/hostside/RebootFreeHostTestBase.java b/hostsidetests/inputmethodservice/hostside/src/android/inputmethodservice/cts/hostside/RebootFreeHostTestBase.java
deleted file mode 100644
index e90f1f6..0000000
--- a/hostsidetests/inputmethodservice/hostside/src/android/inputmethodservice/cts/hostside/RebootFreeHostTestBase.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright (C) 2020 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.inputmethodservice.cts.hostside;
-
-import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.rules.TestName;
-
-import java.util.Objects;
-import java.util.WeakHashMap;
-
-/**
- * A utility class that enforces the device under test must never reboot during the test runs.
- *
- * <p>For instance, suppose the following test class.</p>
- * <pre>{@code
- * @RunWith(DeviceJUnit4ClassRunner.class)
- * public class MyTestClass extends RebootFreeHostTestBase {
- * @Test
- * public void test1() throws Exception {
- * // do something;
- * }
- *
- * @Test
- * public void test2() throws Exception {
- * // do something;
- * }
- *
- * @Test
- * public void test3() throws Exception {
- * // do something;
- * }
- * }
- * }</pre>
- *
- * <p>If the device (soft-)rebooted between {@code test1()} and {@code test2()}, then this base
- * class would let {@code test2()} and {@code test3()} immediately fail by throwing
- * {@link IllegalStateException} with saying that the device reboot is detected and the last
- * test method before reboot is {@code test1()}</p>
- *
- * <p>Note that reboot-free is enforced only within each subclass of {@link RebootFreeHostTestBase}.
- * Another sub-class such as {@code class MyTestClass2 extends RebootFreeHostTestBase} will not
- * immediately fail because of device restart detected while running {@code class MyTestClass}.</p>
- */
-public class RebootFreeHostTestBase extends BaseHostJUnit4Test {
- private static final String PROP_SYSTEM_SERVER_START_COUNT = "sys.system_server.start_count";
-
- private static final WeakHashMap<Class<?>, String> sExpectedSystemStartCount =
- new WeakHashMap<>();
- private static final WeakHashMap<Class<?>, String> sLastRunningTestName = new WeakHashMap<>();
-
- /**
- * A {@link TestName} object to receive the currently running test name.
- *
- * <p>Note this field needs to be {@code public} due to a restriction of JUnit4.</p>
- */
- @Rule
- public TestName mTestName = new TestName();
-
- /**
- * @return device start count as {@link String}.
- * @throws DeviceNotAvailableException
- */
- private String getSystemStartCountAsString() throws DeviceNotAvailableException {
- final String countString = getDevice().getProperty(PROP_SYSTEM_SERVER_START_COUNT);
- if (countString == null) {
- throw new IllegalStateException(
- String.format("Property %s must not be null", PROP_SYSTEM_SERVER_START_COUNT));
- }
- return countString;
- }
-
- /**
- * Ensures there was no unexpected device reboot.
- *
- * @throws IllegalStateException when an unexpected device reboot is detected.
- */
- @Before
- public void ensureNoSystemRestart() throws Exception {
- final Class<?> myClass = getClass();
- final String currentCount = getSystemStartCountAsString();
- final String expectedCount = sExpectedSystemStartCount.get(myClass);
- if (expectedCount == null) {
- // This is the first time for the given test class to run.
- // Just remember the current system start count.
- sExpectedSystemStartCount.put(myClass, currentCount);
- } else if (!Objects.equals(expectedCount, currentCount)) {
- final String lastTest = sLastRunningTestName.getOrDefault(myClass, "<unknown>");
- throw new IllegalStateException(String.format(
- "Unexpected device restart detected [%s: %s -> %s]. "
- + "lastTestBeforeRestart=%s. Check the device log!",
- PROP_SYSTEM_SERVER_START_COUNT, expectedCount, currentCount, lastTest));
- }
- sLastRunningTestName.put(myClass, mTestName.getMethodName());
- }
-}
diff --git a/hostsidetests/inputmethodservice/hostside/src/android/inputmethodservice/cts/hostside/ShellCommandFromAppTest.java b/hostsidetests/inputmethodservice/hostside/src/android/inputmethodservice/cts/hostside/ShellCommandFromAppTest.java
index 0ab53cd..6c66949 100644
--- a/hostsidetests/inputmethodservice/hostside/src/android/inputmethodservice/cts/hostside/ShellCommandFromAppTest.java
+++ b/hostsidetests/inputmethodservice/hostside/src/android/inputmethodservice/cts/hostside/ShellCommandFromAppTest.java
@@ -25,6 +25,7 @@
import android.platform.test.annotations.AppModeInstant;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
import com.android.tradefed.testtype.junit4.DeviceTestRunOptions;
import org.junit.After;
@@ -36,7 +37,7 @@
* Test IInputMethodManager#shellComman verifies callers.
*/
@RunWith(DeviceJUnit4ClassRunner.class)
-public class ShellCommandFromAppTest extends RebootFreeHostTestBase {
+public class ShellCommandFromAppTest extends BaseHostJUnit4Test {
/**
* {@code true} if {@link #tearDown()} needs to be fully executed.
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2017-0479/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2017-0479/poc.cpp
index 0c64210..d9acb35 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2017-0479/poc.cpp
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2017-0479/poc.cpp
@@ -79,8 +79,8 @@
for (i=0; i<100; i++) {
gEffect = audioFlinger->createEffect(&descriptor, effectClient, priority,
- io, sessionId, device, opPackageName, getpid(),
- &err, &id, &enabled);
+ io, sessionId, device, opPackageName,
+ getpid(), false, &err, &id, &enabled);
if (gEffect == NULL || err != NO_ERROR) {
return -1;
}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/AdbUtils.java b/hostsidetests/securitybulletin/src/android/security/cts/AdbUtils.java
index b1eeb5e..ac8908b 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/AdbUtils.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/AdbUtils.java
@@ -393,9 +393,22 @@
*/
public static void runPocAssertNoCrashes(String pocName, ITestDevice device,
String... processPatternStrings) throws Exception {
+ runPocAssertNoCrashes(pocName, device,
+ new CrashUtils.Config().setProcessPatterns(processPatternStrings));
+ }
+
+ /**
+ * Runs the poc binary and asserts that there are no security crashes that match the expected
+ * process pattern.
+ * @param pocName a string path to poc from the /res folder
+ * @param device device to be ran on
+ * @param config a crash parser configuration
+ */
+ public static void runPocAssertNoCrashes(String pocName, ITestDevice device,
+ CrashUtils.Config config) throws Exception {
AdbUtils.runCommandLine("logcat -c", device);
AdbUtils.runPocNoOutput(pocName, device, SecurityTestCase.TIMEOUT_NONDETERMINISTIC);
- assertNoCrashes(device, processPatternStrings);
+ assertNoCrashes(device, config);
}
/**
@@ -500,27 +513,21 @@
*/
public static void assertNoCrashes(ITestDevice device, String... processPatternStrings)
throws Exception {
- assertNoCrashes(device, true, processPatternStrings);
+ assertNoCrashes(device, new CrashUtils.Config().setProcessPatterns(processPatternStrings));
}
/**
* Dumps logcat and asserts that there are no security crashes that match the expected process
* pattern. Ensure that adb logcat -c is called beforehand.
* @param device device to be ran on
- * @param checkMinAddress if the minimum fault address should be respected
- * @param processPatternStrings a Pattern string to match the crash tombstone process
+ * @param config a crash parser configuration
*/
- public static void assertNoCrashes(ITestDevice device, boolean checkMinAddress,
- String... processPatternStrings) throws Exception {
+ public static void assertNoCrashes(ITestDevice device,
+ CrashUtils.Config config) throws Exception {
String logcat = AdbUtils.runCommandLine("logcat -d *:S DEBUG:V", device);
- Pattern[] processPatterns = new Pattern[processPatternStrings.length];
- for (int i = 0; i < processPatternStrings.length; i++) {
- processPatterns[i] = Pattern.compile(processPatternStrings[i]);
- }
JSONArray crashes = CrashUtils.addAllCrashes(logcat, new JSONArray());
- JSONArray securityCrashes =
- CrashUtils.matchSecurityCrashes(crashes, checkMinAddress, processPatterns);
+ JSONArray securityCrashes = CrashUtils.matchSecurityCrashes(crashes, config);
if (securityCrashes.length() == 0) {
return; // no security crashes detected
@@ -529,8 +536,8 @@
StringBuilder error = new StringBuilder();
error.append("Security crash detected:\n");
error.append("Process patterns:");
- for (String pattern : processPatternStrings) {
- error.append(String.format(" '%s'", pattern));
+ for (Pattern pattern : config.getProcessPatterns()) {
+ error.append(String.format(" '%s'", pattern.toString()));
}
error.append("\nCrashes:\n");
for (int i = 0; i < crashes.length(); i++) {
diff --git a/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/AtomTests.java b/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/AtomTests.java
index 7458be5..fa74b7f 100644
--- a/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/AtomTests.java
+++ b/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/AtomTests.java
@@ -60,6 +60,7 @@
import android.os.SystemClock;
import android.os.VibrationEffect;
import android.os.Vibrator;
+import android.util.ArrayMap;
import android.util.Log;
import androidx.test.InstrumentationRegistry;
@@ -70,6 +71,7 @@
import java.util.Arrays;
import java.util.List;
+import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -78,6 +80,108 @@
private static final String MY_PACKAGE_NAME = "com.android.server.cts.device.statsd";
+ private static final Map<String, Integer> APP_OPS_ENUM_MAP = new ArrayMap<>();
+ static {
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_COARSE_LOCATION, 0);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_FINE_LOCATION, 1);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_GPS, 2);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_VIBRATE, 3);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_READ_CONTACTS, 4);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_WRITE_CONTACTS, 5);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_READ_CALL_LOG, 6);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_WRITE_CALL_LOG, 7);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_READ_CALENDAR, 8);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_WRITE_CALENDAR, 9);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_WIFI_SCAN, 10);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_POST_NOTIFICATION, 11);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_NEIGHBORING_CELLS, 12);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_CALL_PHONE, 13);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_READ_SMS, 14);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_WRITE_SMS, 15);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_RECEIVE_SMS, 16);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_RECEIVE_EMERGENCY_BROADCAST, 17);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_RECEIVE_MMS, 18);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_RECEIVE_WAP_PUSH, 19);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_SEND_SMS, 20);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_READ_ICC_SMS, 21);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_WRITE_ICC_SMS, 22);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_WRITE_SETTINGS, 23);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_SYSTEM_ALERT_WINDOW, 24);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_ACCESS_NOTIFICATIONS, 25);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_CAMERA, 26);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_RECORD_AUDIO, 27);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_PLAY_AUDIO, 28);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_READ_CLIPBOARD, 29);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_WRITE_CLIPBOARD, 30);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_TAKE_MEDIA_BUTTONS, 31);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_TAKE_AUDIO_FOCUS, 32);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_AUDIO_MASTER_VOLUME, 33);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_AUDIO_VOICE_VOLUME, 34);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_AUDIO_RING_VOLUME, 35);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_AUDIO_MEDIA_VOLUME, 36);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_AUDIO_ALARM_VOLUME, 37);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_AUDIO_NOTIFICATION_VOLUME, 38);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_AUDIO_BLUETOOTH_VOLUME, 39);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_WAKE_LOCK, 40);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_MONITOR_LOCATION, 41);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_MONITOR_HIGH_POWER_LOCATION, 42);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_GET_USAGE_STATS, 43);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_MUTE_MICROPHONE, 44);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_TOAST_WINDOW, 45);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_PROJECT_MEDIA, 46);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_ACTIVATE_VPN, 47);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_WRITE_WALLPAPER, 48);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_ASSIST_STRUCTURE, 49);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_ASSIST_SCREENSHOT, 50);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_READ_PHONE_STATE, 51);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_ADD_VOICEMAIL, 52);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_USE_SIP, 53);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_PROCESS_OUTGOING_CALLS, 54);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_USE_FINGERPRINT, 55);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_BODY_SENSORS, 56);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_READ_CELL_BROADCASTS, 57);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_MOCK_LOCATION, 58);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_READ_EXTERNAL_STORAGE, 59);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_WRITE_EXTERNAL_STORAGE, 60);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_TURN_SCREEN_ON, 61);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_GET_ACCOUNTS, 62);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_RUN_IN_BACKGROUND, 63);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_AUDIO_ACCESSIBILITY_VOLUME, 64);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_READ_PHONE_NUMBERS, 65);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_REQUEST_INSTALL_PACKAGES, 66);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_PICTURE_IN_PICTURE, 67);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_INSTANT_APP_START_FOREGROUND, 68);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_ANSWER_PHONE_CALLS, 69);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_RUN_ANY_IN_BACKGROUND, 70);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_CHANGE_WIFI_STATE, 71);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_REQUEST_DELETE_PACKAGES, 72);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_BIND_ACCESSIBILITY_SERVICE, 73);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_ACCEPT_HANDOVER, 74);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_MANAGE_IPSEC_TUNNELS, 75);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_START_FOREGROUND, 76);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_BLUETOOTH_SCAN, 77);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_USE_BIOMETRIC, 78);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_ACTIVITY_RECOGNITION, 79);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_SMS_FINANCIAL_TRANSACTIONS, 80);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_READ_MEDIA_AUDIO, 81);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_WRITE_MEDIA_AUDIO, 82);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_READ_MEDIA_VIDEO, 83);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_WRITE_MEDIA_VIDEO, 84);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_READ_MEDIA_IMAGES, 85);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_WRITE_MEDIA_IMAGES, 86);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_LEGACY_STORAGE, 87);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_ACCESS_ACCESSIBILITY, 88);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_READ_DEVICE_IDENTIFIERS, 89);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_ACCESS_MEDIA_LOCATION, 90);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_QUERY_ALL_PACKAGES, 91);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_MANAGE_EXTERNAL_STORAGE, 92);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_INTERACT_ACROSS_PROFILES, 93);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN, 94);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_LOADER_USAGE_STATS, 95);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_ACCESS_CALL_AUDIO, 96);
+ APP_OPS_ENUM_MAP.put(AppOpsManager.OPSTR_AUTO_REVOKE_PERMISSIONS_IF_UNUSED, 97);
+ }
+
@Test
public void testAudioState() {
// TODO: This should surely be getTargetContext(), here and everywhere, but test first.
@@ -244,6 +348,7 @@
// No foreground service session
noteAppOp(appOpsManager, AppOpsManager.OPSTR_COARSE_LOCATION, true);
+ sleep(500);
// Foreground service session 1
context.startService(fgsIntent);
@@ -255,14 +360,34 @@
noteAppOp(appOpsManager, AppOpsManager.OPSTR_CAMERA, true);
noteAppOp(appOpsManager, AppOpsManager.OPSTR_RECORD_AUDIO, false);
noteAppOp(appOpsManager, AppOpsManager.OPSTR_RECORD_AUDIO, true);
+ sleep(500);
context.stopService(fgsIntent);
// No foreground service session
noteAppOp(appOpsManager, AppOpsManager.OPSTR_COARSE_LOCATION, true);
+ sleep(500);
// TODO(b/149098800): Start fgs a second time and log OPSTR_CAMERA again
}
+ @Test
+ public void testAppOps() throws Exception {
+ Context context = InstrumentationRegistry.getContext();
+ AppOpsManager appOpsManager = context.getSystemService(AppOpsManager.class);
+
+ String[] opsList = appOpsManager.getOpStrs();
+
+ for (int i = 0; i < opsList.length; i++) {
+ String op = opsList[i];
+ int noteCount = APP_OPS_ENUM_MAP.getOrDefault(op, opsList.length) + 1;
+ for (int j = 0; j < noteCount; j++) {
+ try {
+ noteAppOp(appOpsManager, opsList[i], true);
+ } catch (SecurityException e) {}
+ }
+ }
+ }
+
/** @param doNote true if should use noteOp; false if should use startOp. */
private void noteAppOp(AppOpsManager appOpsManager, String opStr, boolean doNote) {
if (doNote) {
@@ -274,7 +399,6 @@
(aom) -> aom.startOp(opStr, android.os.Process.myUid(),
MY_PACKAGE_NAME, null, "statsdTest"));
}
- sleep(500);
}
/** Check if service is running. */
diff --git a/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/DirectoryTests.java b/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/DirectoryTests.java
new file mode 100644
index 0000000..fd849c9
--- /dev/null
+++ b/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/DirectoryTests.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2020 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.server.cts.device.statsd;
+
+import org.junit.Test;
+
+import java.io.File;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class DirectoryTests {
+
+ @Test
+ public void testStatsActiveMetricDirectoryExists() {
+ final File f = new File("/data/misc/stats-active-metric/");
+ assertTrue(f.exists());
+ assertFalse(f.isFile());
+ }
+
+ @Test
+ public void testStatsDataDirectoryExists() {
+ final File f = new File("/data/misc/stats-data/");
+ assertTrue(f.exists());
+ assertFalse(f.isFile());
+ }
+
+ @Test
+ public void testStatsMetadataDirectoryExists() {
+ final File f = new File("/data/misc/stats-metadata/");
+ assertTrue(f.exists());
+ assertFalse(f.isFile());
+ }
+
+ @Test
+ public void testStatsServiceDirectoryExists() {
+ final File f = new File("/data/misc/stats-service/");
+ assertTrue(f.exists());
+ assertFalse(f.isFile());
+ }
+
+ @Test
+ public void testTrainInfoDirectoryExists() {
+ final File f = new File("/data/misc/train-info/");
+ assertTrue(f.exists());
+ assertFalse(f.isFile());
+ }
+}
diff --git a/hostsidetests/statsd/src/android/cts/statsd/atom/UidAtomTests.java b/hostsidetests/statsd/src/android/cts/statsd/atom/UidAtomTests.java
index 82fdaf9..15d5bb6 100644
--- a/hostsidetests/statsd/src/android/cts/statsd/atom/UidAtomTests.java
+++ b/hostsidetests/statsd/src/android/cts/statsd/atom/UidAtomTests.java
@@ -19,6 +19,7 @@
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
+import android.app.AppOpEnum;
import android.net.wifi.WifiModeEnum;
import android.os.WakeLockLevelEnum;
import android.server.ErrorSource;
@@ -31,6 +32,7 @@
import com.android.os.AtomsProto.AppStartOccurred;
import com.android.os.AtomsProto.Atom;
import com.android.os.AtomsProto.AttributionNode;
+import com.android.os.AtomsProto.AttributedAppOps;
import com.android.os.AtomsProto.AudioStateChanged;
import com.android.os.AtomsProto.BinderCalls;
import com.android.os.AtomsProto.BleScanResultReceived;
@@ -85,8 +87,13 @@
private static final String TAG = "Statsd.UidAtomTests";
+ private static final String TEST_PACKAGE_NAME = "com.android.server.cts.device.statsd";
+
private static final boolean DAVEY_ENABLED = false;
+ private static final int NUM_APP_OPS = AttributedAppOps.getDefaultInstance().getOp().
+ getDescriptorForType().getValues().size() - 1;
+
@Override
protected void setUp() throws Exception {
super.setUp();
@@ -171,7 +178,7 @@
.isEqualTo(AppCrashOccurred.InstantApp.FALSE_VALUE);
assertThat(atom.getForegroundState().getNumber())
.isEqualTo(AppCrashOccurred.ForegroundState.FOREGROUND_VALUE);
- assertThat(atom.getPackageName()).isEqualTo("com.android.server.cts.device.statsd");
+ assertThat(atom.getPackageName()).isEqualTo(TEST_PACKAGE_NAME);
}
public void testAppStartOccurred() throws Exception {
@@ -189,7 +196,7 @@
List<EventMetricData> data = getEventMetricDataList();
AppStartOccurred atom = data.get(0).getAtom().getAppStartOccurred();
- assertThat(atom.getPkgName()).isEqualTo("com.android.server.cts.device.statsd");
+ assertThat(atom.getPkgName()).isEqualTo(TEST_PACKAGE_NAME);
assertThat(atom.getActivityName())
.isEqualTo("com.android.server.cts.device.statsd.StatsdCtsForegroundActivity");
assertThat(atom.getIsInstantApp()).isFalse();
@@ -570,22 +577,21 @@
final int count = acceptances + rejections;
int expectedCount = 0;
switch (opName) {
- case ForegroundServiceAppOpSessionEnded.AppOpName.OP_CAMERA_VALUE:
+ case AppOpEnum.APP_OP_CAMERA_VALUE:
expectedCount = 2;
break;
- case ForegroundServiceAppOpSessionEnded.AppOpName.OP_FINE_LOCATION_VALUE:
+ case AppOpEnum.APP_OP_FINE_LOCATION_VALUE:
expectedCount = 1;
break;
- case ForegroundServiceAppOpSessionEnded.AppOpName.OP_RECORD_AUDIO_VALUE:
+ case AppOpEnum.APP_OP_RECORD_AUDIO_VALUE:
expectedCount = 2;
break;
- case ForegroundServiceAppOpSessionEnded.AppOpName.OP_COARSE_LOCATION_VALUE:
+ case AppOpEnum.APP_OP_COARSE_LOCATION_VALUE:
// fall-through
default:
fail("Unexpected opName " + opName);
}
assertWithMessage("Wrong count for " + opName).that(count).isEqualTo(expectedCount);
-
}
}
@@ -1560,20 +1566,38 @@
StatsdConfig.Builder config = getPulledConfig();
addGaugeAtomWithDimensions(config, Atom.APP_OPS_FIELD_NUMBER, null);
uploadConfig(config);
+
+ runDeviceTests(DEVICE_SIDE_TEST_PACKAGE, ".AtomTests", "testAppOps");
Thread.sleep(WAIT_TIME_SHORT);
// Pull a report
setAppBreadcrumbPredicate();
Thread.sleep(WAIT_TIME_SHORT);
- long accessInstancesRecorded = 0;
-
- for (Atom atom : getGaugeMetricDataList()) {
- AppOps appOps = atom.getAppOps();
- accessInstancesRecorded += appOps.getTrustedForegroundGrantedCount();
+ ArrayList<Integer> expectedOps = new ArrayList<>();
+ for (int i = 0; i < NUM_APP_OPS; i++) {
+ expectedOps.add(i);
}
- assertThat(accessInstancesRecorded).isAtLeast(1l);
+ for (Atom atom : getGaugeMetricDataList()) {
+
+ AppOps appOps = atom.getAppOps();
+ if (appOps.getPackageName().equals(TEST_PACKAGE_NAME)) {
+ if (appOps.getOpId().getNumber() == -1) {
+ continue;
+ }
+ long totalNoted = appOps.getTrustedForegroundGrantedCount()
+ + appOps.getTrustedBackgroundGrantedCount()
+ + appOps.getTrustedForegroundRejectedCount()
+ + appOps.getTrustedBackgroundRejectedCount();
+ assertWithMessage("Operation in APP_OPS_ENUM_MAP: " + appOps.getOpId().getNumber())
+ .that(totalNoted - 1).isEqualTo(appOps.getOpId().getNumber());
+ assertWithMessage("Unexpected Op reported").that(expectedOps).contains(
+ appOps.getOpId().getNumber());
+ expectedOps.remove(expectedOps.indexOf(appOps.getOpId().getNumber()));
+ }
+ }
+ assertWithMessage("Logging app op ids are missing in report.").that(expectedOps).isEmpty();
}
public void testANROccurred() throws Exception {
diff --git a/hostsidetests/statsd/src/android/cts/statsd/validation/DirectoryValidationTest.java b/hostsidetests/statsd/src/android/cts/statsd/validation/DirectoryValidationTest.java
new file mode 100644
index 0000000..37ded0b
--- /dev/null
+++ b/hostsidetests/statsd/src/android/cts/statsd/validation/DirectoryValidationTest.java
@@ -0,0 +1,34 @@
+package android.cts.statsd.validation;
+
+import android.cts.statsd.atom.DeviceAtomTestCase;
+
+/**
+ * Tests Suite for directories used by Statsd.
+ */
+public class DirectoryValidationTest extends DeviceAtomTestCase {
+
+ public void testStatsActiveMetricDirectoryExists() throws Exception {
+ runDeviceTests(DEVICE_SIDE_TEST_PACKAGE,
+ ".DirectoryTests", "testStatsActiveMetricDirectoryExists");
+ }
+
+ public void testStatsDataDirectoryExists() throws Exception {
+ runDeviceTests(DEVICE_SIDE_TEST_PACKAGE,
+ ".DirectoryTests", "testStatsDataDirectoryExists");
+ }
+
+ public void testStatsMetadataDirectoryExists() throws Exception {
+ runDeviceTests(DEVICE_SIDE_TEST_PACKAGE,
+ ".DirectoryTests", "testStatsMetadataDirectoryExists");
+ }
+
+ public void testStatsServiceDirectoryExists() throws Exception {
+ runDeviceTests(DEVICE_SIDE_TEST_PACKAGE,
+ ".DirectoryTests", "testStatsServiceDirectoryExists");
+ }
+
+ public void testTrainInfoDirectoryExists() throws Exception {
+ runDeviceTests(DEVICE_SIDE_TEST_PACKAGE,
+ ".DirectoryTests", "testTrainInfoDirectoryExists");
+ }
+}
diff --git a/hostsidetests/userspacereboot/TEST_MAPPING b/hostsidetests/userspacereboot/TEST_MAPPING
index d0a1adb..e066051 100644
--- a/hostsidetests/userspacereboot/TEST_MAPPING
+++ b/hostsidetests/userspacereboot/TEST_MAPPING
@@ -4,5 +4,10 @@
"name": "CtsUserspaceRebootHostSideTestCases",
"keywords": ["primary-device"]
}
+ ],
+ "postsubmit": [
+ {
+ "name": "CtsUserspaceRebootHostSideTestCases"
+ }
]
}
diff --git a/tests/BlobStore/Android.bp b/tests/BlobStore/Android.bp
index 61d34e4..5bd782a 100644
--- a/tests/BlobStore/Android.bp
+++ b/tests/BlobStore/Android.bp
@@ -40,6 +40,7 @@
name: "CtsBlobStoreTestHelper",
defaults: ["cts_defaults"],
static_libs: [
+ "androidx.test.ext.junit",
"truth-prebuilt",
"BlobStoreTestUtils",
],
@@ -60,6 +61,7 @@
name: "CtsBlobStoreTestHelperDiffSig",
defaults: ["cts_defaults"],
static_libs: [
+ "androidx.test.ext.junit",
"truth-prebuilt",
"BlobStoreTestUtils",
],
@@ -84,6 +86,7 @@
name: "CtsBlobStoreTestHelperDiffSig2",
defaults: ["cts_defaults"],
static_libs: [
+ "androidx.test.ext.junit",
"truth-prebuilt",
"BlobStoreTestUtils",
],
diff --git a/tests/BlobStore/helper-app/src/com/android/cts/blob/helper/BlobStoreTestService.java b/tests/BlobStore/helper-app/src/com/android/cts/blob/helper/BlobStoreTestService.java
index ce8cd6c..5f3547d 100644
--- a/tests/BlobStore/helper-app/src/com/android/cts/blob/helper/BlobStoreTestService.java
+++ b/tests/BlobStore/helper-app/src/com/android/cts/blob/helper/BlobStoreTestService.java
@@ -29,8 +29,10 @@
import android.content.Intent;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.IBinder;
+import android.os.Parcel;
import android.os.ParcelFileDescriptor;
import android.os.Process;
+import android.os.RemoteException;
import com.android.cts.blob.ICommandReceiver;
import com.android.utils.blob.Utils;
@@ -66,7 +68,7 @@
return callback.get(timeoutSec, TimeUnit.SECONDS);
}
} catch (IOException | InterruptedException | TimeoutException | ExecutionException e) {
- throw new RuntimeException(e);
+ throw new IllegalStateException(e);
}
}
@@ -77,7 +79,7 @@
try {
return blobStoreManager.openBlob(blobHandle);
} catch (IOException e) {
- throw new RuntimeException(e);
+ throw new IllegalStateException(e);
}
}
@@ -90,7 +92,7 @@
assertThat(session).isNotNull();
}
} catch (IOException e) {
- throw new RuntimeException(e);
+ throw new IllegalStateException(e);
}
}
@@ -99,9 +101,10 @@
final BlobStoreManager blobStoreManager = getSystemService(
BlobStoreManager.class);
try {
- blobStoreManager.acquireLease(blobHandle, "Test description");
+ Utils.acquireLease(BlobStoreTestService.this, blobHandle, "Test description");
+ assertThat(blobStoreManager.getLeasedBlobs()).contains(blobHandle);
} catch (IOException e) {
- throw new RuntimeException(e);
+ throw new IllegalStateException(e);
}
}
@@ -110,9 +113,10 @@
final BlobStoreManager blobStoreManager = getSystemService(
BlobStoreManager.class);
try {
- blobStoreManager.releaseLease(blobHandle);
+ Utils.releaseLease(BlobStoreTestService.this, blobHandle);
+ assertThat(blobStoreManager.getLeasedBlobs()).doesNotContain(blobHandle);
} catch (IOException e) {
- throw new RuntimeException(e);
+ throw new IllegalStateException(e);
}
}
@@ -124,7 +128,7 @@
return storageStatsManager
.queryStatsForPackage(UUID_DEFAULT, getPackageName(), getUser());
} catch (IOException | NameNotFoundException e) {
- throw new RuntimeException(e);
+ throw new IllegalStateException(e);
}
}
@@ -136,7 +140,17 @@
return storageStatsManager
.queryStatsForUid(UUID_DEFAULT, Process.myUid());
} catch (IOException e) {
- throw new RuntimeException(e);
+ throw new IllegalStateException(e);
+ }
+ }
+
+ @Override
+ public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
+ throws RemoteException {
+ try {
+ return super.onTransact(code, data, reply, flags);
+ } catch (AssertionError e) {
+ throw new IllegalStateException(e);
}
}
}
diff --git a/tests/BlobStore/src/com/android/cts/blob/BlobStoreManagerTest.java b/tests/BlobStore/src/com/android/cts/blob/BlobStoreManagerTest.java
index 7c39970..2c81ca7 100644
--- a/tests/BlobStore/src/com/android/cts/blob/BlobStoreManagerTest.java
+++ b/tests/BlobStore/src/com/android/cts/blob/BlobStoreManagerTest.java
@@ -17,12 +17,14 @@
import static android.os.storage.StorageManager.UUID_DEFAULT;
-import static com.android.compatibility.common.util.SystemUtil.runShellCommand;
+import static com.android.utils.blob.Utils.acquireLease;
+import static com.android.utils.blob.Utils.assertLeasedBlobs;
+import static com.android.utils.blob.Utils.assertNoLeasedBlobs;
+import static com.android.utils.blob.Utils.releaseLease;
import static com.google.common.truth.Truth.assertThat;
import static org.testng.Assert.assertThrows;
-import static org.testng.Assert.expectThrows;
import android.app.blob.BlobHandle;
import android.app.blob.BlobStoreManager;
@@ -35,23 +37,27 @@
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
import android.os.Process;
+import android.os.SystemClock;
+import android.provider.DeviceConfig;
import android.util.Log;
+import com.android.compatibility.common.util.SystemUtil;
+import com.android.compatibility.common.util.ThrowingRunnable;
import com.android.cts.blob.R;
import com.android.cts.blob.ICommandReceiver;
import com.android.utils.blob.DummyBlobData;
-import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.io.IOException;
-import java.util.ArrayList;
+import java.util.Objects;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.platform.app.InstrumentationRegistry;
@@ -66,6 +72,12 @@
private static final long TIMEOUT_BIND_SERVICE_SEC = 2;
+ // TODO: Make it a @TestApi or move the test using this to a different location.
+ // Copy of DeviceConfig.NAMESPACE_BLOBSTORE constant
+ public static final String NAMESPACE_BLOBSTORE = "blobstore";
+ public static final String KEY_LEASE_ACQUISITION_WAIT_DURATION_MS =
+ "lease_acquisition_wait_time_ms";
+
private static final String HELPER_PKG = "com.android.cts.blob.helper";
private static final String HELPER_PKG2 = "com.android.cts.blob.helper2";
private static final String HELPER_PKG3 = "com.android.cts.blob.helper3";
@@ -91,7 +103,7 @@
@Test
public void testGetCreateSession() throws Exception {
- final DummyBlobData blobData = new DummyBlobData(mContext);
+ final DummyBlobData blobData = new DummyBlobData.Builder(mContext).build();
blobData.prepare();
try {
final long sessionId = mBlobStoreManager.createSession(blobData.getBlobHandle());
@@ -104,7 +116,7 @@
@Test
public void testCreateBlobHandle_invalidArguments() throws Exception {
- final DummyBlobData blobData = new DummyBlobData(mContext);
+ final DummyBlobData blobData = new DummyBlobData.Builder(mContext).build();
blobData.prepare();
final BlobHandle handle = blobData.getBlobHandle();
try {
@@ -140,7 +152,7 @@
@Test
public void testAbandonSession() throws Exception {
- final DummyBlobData blobData = new DummyBlobData(mContext);
+ final DummyBlobData blobData = new DummyBlobData.Builder(mContext).build();
blobData.prepare();
try {
final long sessionId = mBlobStoreManager.createSession(blobData.getBlobHandle());
@@ -158,7 +170,7 @@
@Test
public void testOpenReadWriteSession() throws Exception {
- final DummyBlobData blobData = new DummyBlobData(mContext);
+ final DummyBlobData blobData = new DummyBlobData.Builder(mContext).build();
blobData.prepare();
try {
final long sessionId = mBlobStoreManager.createSession(blobData.getBlobHandle());
@@ -180,7 +192,7 @@
@Test
public void testOpenSession_fromAnotherPkg() throws Exception {
- final DummyBlobData blobData = new DummyBlobData(mContext);
+ final DummyBlobData blobData = new DummyBlobData.Builder(mContext).build();
blobData.prepare();
try {
final long sessionId = mBlobStoreManager.createSession(blobData.getBlobHandle());
@@ -206,7 +218,7 @@
@Test
public void testOpenSessionAndAbandon() throws Exception {
- final DummyBlobData blobData = new DummyBlobData(mContext);
+ final DummyBlobData blobData = new DummyBlobData.Builder(mContext).build();
blobData.prepare();
try {
final long sessionId = mBlobStoreManager.createSession(blobData.getBlobHandle());
@@ -231,7 +243,7 @@
@Test
public void testCloseSession() throws Exception {
- final DummyBlobData blobData = new DummyBlobData(mContext);
+ final DummyBlobData blobData = new DummyBlobData.Builder(mContext).build();
blobData.prepare();
try {
final long sessionId = mBlobStoreManager.createSession(blobData.getBlobHandle());
@@ -267,21 +279,16 @@
@Test
public void testAllowPublicAccess() throws Exception {
- final DummyBlobData blobData = new DummyBlobData(mContext);
+ final DummyBlobData blobData = new DummyBlobData.Builder(mContext).build();
blobData.prepare();
try {
final long sessionId = mBlobStoreManager.createSession(blobData.getBlobHandle());
assertThat(sessionId).isGreaterThan(0L);
- try (BlobStoreManager.Session session = mBlobStoreManager.openSession(sessionId)) {
- blobData.writeToSession(session);
+ commitBlob(blobData, session -> {
session.allowPublicAccess();
-
- final CompletableFuture<Integer> callback = new CompletableFuture<>();
- session.commit(mContext.getMainExecutor(), callback::complete);
- assertThat(callback.get(TIMEOUT_COMMIT_CALLBACK_SEC, TimeUnit.SECONDS))
- .isEqualTo(0);
- }
+ assertThat(session.isPublicAccessAllowed()).isTrue();
+ });
assertPkgCanAccess(blobData, HELPER_PKG);
assertPkgCanAccess(blobData, HELPER_PKG2);
@@ -293,7 +300,7 @@
@Test
public void testAllowPublicAccess_abandonedSession() throws Exception {
- final DummyBlobData blobData = new DummyBlobData(mContext);
+ final DummyBlobData blobData = new DummyBlobData.Builder(mContext).build();
blobData.prepare();
try {
final long sessionId = mBlobStoreManager.createSession(blobData.getBlobHandle());
@@ -316,21 +323,16 @@
@Test
public void testAllowSameSignatureAccess() throws Exception {
- final DummyBlobData blobData = new DummyBlobData(mContext);
+ final DummyBlobData blobData = new DummyBlobData.Builder(mContext).build();
blobData.prepare();
try {
final long sessionId = mBlobStoreManager.createSession(blobData.getBlobHandle());
assertThat(sessionId).isGreaterThan(0L);
- try (BlobStoreManager.Session session = mBlobStoreManager.openSession(sessionId)) {
- blobData.writeToSession(session);
+ commitBlob(blobData, session -> {
session.allowSameSignatureAccess();
-
- final CompletableFuture<Integer> callback = new CompletableFuture<>();
- session.commit(mContext.getMainExecutor(), callback::complete);
- assertThat(callback.get(TIMEOUT_COMMIT_CALLBACK_SEC, TimeUnit.SECONDS))
- .isEqualTo(0);
- }
+ assertThat(session.isSameSignatureAccessAllowed()).isTrue();
+ });
assertPkgCanAccess(blobData, HELPER_PKG);
assertPkgCannotAccess(blobData, HELPER_PKG2);
@@ -342,7 +344,7 @@
@Test
public void testAllowSameSignatureAccess_abandonedSession() throws Exception {
- final DummyBlobData blobData = new DummyBlobData(mContext);
+ final DummyBlobData blobData = new DummyBlobData.Builder(mContext).build();
blobData.prepare();
try {
final long sessionId = mBlobStoreManager.createSession(blobData.getBlobHandle());
@@ -365,21 +367,17 @@
@Test
public void testAllowPackageAccess() throws Exception {
- final DummyBlobData blobData = new DummyBlobData(mContext);
+ final DummyBlobData blobData = new DummyBlobData.Builder(mContext).build();
blobData.prepare();
try {
final long sessionId = mBlobStoreManager.createSession(blobData.getBlobHandle());
assertThat(sessionId).isGreaterThan(0L);
- try (BlobStoreManager.Session session = mBlobStoreManager.openSession(sessionId)) {
- blobData.writeToSession(session);
+ commitBlob(blobData, session -> {
session.allowPackageAccess(HELPER_PKG2, HELPER_PKG2_CERT_SHA256);
-
- final CompletableFuture<Integer> callback = new CompletableFuture<>();
- session.commit(mContext.getMainExecutor(), callback::complete);
- assertThat(callback.get(TIMEOUT_COMMIT_CALLBACK_SEC, TimeUnit.SECONDS))
- .isEqualTo(0);
- }
+ assertThat(session.isPackageAccessAllowed(HELPER_PKG2, HELPER_PKG2_CERT_SHA256))
+ .isTrue();
+ });
assertPkgCannotAccess(blobData, HELPER_PKG);
assertPkgCanAccess(blobData, HELPER_PKG2);
@@ -391,22 +389,20 @@
@Test
public void testAllowPackageAccess_allowMultiple() throws Exception {
- final DummyBlobData blobData = new DummyBlobData(mContext);
+ final DummyBlobData blobData = new DummyBlobData.Builder(mContext).build();
blobData.prepare();
try {
final long sessionId = mBlobStoreManager.createSession(blobData.getBlobHandle());
assertThat(sessionId).isGreaterThan(0L);
- try (BlobStoreManager.Session session = mBlobStoreManager.openSession(sessionId)) {
- blobData.writeToSession(session);
+ commitBlob(blobData, session -> {
session.allowPackageAccess(HELPER_PKG2, HELPER_PKG2_CERT_SHA256);
session.allowPackageAccess(HELPER_PKG3, HELPER_PKG3_CERT_SHA256);
-
- final CompletableFuture<Integer> callback = new CompletableFuture<>();
- session.commit(mContext.getMainExecutor(), callback::complete);
- assertThat(callback.get(TIMEOUT_COMMIT_CALLBACK_SEC, TimeUnit.SECONDS))
- .isEqualTo(0);
- }
+ assertThat(session.isPackageAccessAllowed(HELPER_PKG2, HELPER_PKG2_CERT_SHA256))
+ .isTrue();
+ assertThat(session.isPackageAccessAllowed(HELPER_PKG3, HELPER_PKG3_CERT_SHA256))
+ .isTrue();
+ });
assertPkgCannotAccess(blobData, HELPER_PKG);
assertPkgCanAccess(blobData, HELPER_PKG2);
@@ -418,7 +414,7 @@
@Test
public void testAllowPackageAccess_abandonedSession() throws Exception {
- final DummyBlobData blobData = new DummyBlobData(mContext);
+ final DummyBlobData blobData = new DummyBlobData.Builder(mContext).build();
blobData.prepare();
try {
final long sessionId = mBlobStoreManager.createSession(blobData.getBlobHandle());
@@ -444,7 +440,7 @@
@Test
public void testPrivateAccess() throws Exception {
- final DummyBlobData blobData = new DummyBlobData(mContext);
+ final DummyBlobData blobData = new DummyBlobData.Builder(mContext).build();
blobData.prepare();
final TestServiceConnection connection1 = bindToHelperService(HELPER_PKG);
final TestServiceConnection connection2 = bindToHelperService(HELPER_PKG2);
@@ -453,14 +449,7 @@
final long sessionId = mBlobStoreManager.createSession(blobData.getBlobHandle());
assertThat(sessionId).isGreaterThan(0L);
- try (BlobStoreManager.Session session = mBlobStoreManager.openSession(sessionId)) {
- blobData.writeToSession(session);
-
- final CompletableFuture<Integer> callback = new CompletableFuture<>();
- session.commit(mContext.getMainExecutor(), callback::complete);
- assertThat(callback.get(TIMEOUT_COMMIT_CALLBACK_SEC, TimeUnit.SECONDS))
- .isEqualTo(0);
- }
+ commitBlob(blobData);
assertPkgCannotAccess(blobData, connection1);
assertPkgCannotAccess(blobData, connection2);
@@ -485,28 +474,20 @@
@Test
public void testMixedAccessType() throws Exception {
- final DummyBlobData blobData = new DummyBlobData(mContext);
+ final DummyBlobData blobData = new DummyBlobData.Builder(mContext).build();
blobData.prepare();
try {
final long sessionId = mBlobStoreManager.createSession(blobData.getBlobHandle());
assertThat(sessionId).isGreaterThan(0L);
- try (BlobStoreManager.Session session = mBlobStoreManager.openSession(sessionId)) {
- blobData.writeToSession(session);
-
+ commitBlob(blobData, session -> {
session.allowSameSignatureAccess();
session.allowPackageAccess(HELPER_PKG3, HELPER_PKG3_CERT_SHA256);
-
assertThat(session.isSameSignatureAccessAllowed()).isTrue();
assertThat(session.isPackageAccessAllowed(HELPER_PKG3, HELPER_PKG3_CERT_SHA256))
.isTrue();
assertThat(session.isPublicAccessAllowed()).isFalse();
-
- final CompletableFuture<Integer> callback = new CompletableFuture<>();
- session.commit(mContext.getMainExecutor(), callback::complete);
- assertThat(callback.get(TIMEOUT_COMMIT_CALLBACK_SEC, TimeUnit.SECONDS))
- .isEqualTo(0);
- }
+ });
assertPkgCanAccess(blobData, HELPER_PKG);
assertPkgCannotAccess(blobData, HELPER_PKG2);
@@ -518,7 +499,7 @@
@Test
public void testMixedAccessType_fromMultiplePackages() throws Exception {
- final DummyBlobData blobData = new DummyBlobData(mContext);
+ final DummyBlobData blobData = new DummyBlobData.Builder(mContext).build();
blobData.prepare();
final TestServiceConnection connection1 = bindToHelperService(HELPER_PKG);
final TestServiceConnection connection2 = bindToHelperService(HELPER_PKG2);
@@ -527,22 +508,14 @@
final long sessionId = mBlobStoreManager.createSession(blobData.getBlobHandle());
assertThat(sessionId).isGreaterThan(0L);
- try (BlobStoreManager.Session session = mBlobStoreManager.openSession(sessionId)) {
- blobData.writeToSession(session);
-
+ commitBlob(blobData, session -> {
session.allowSameSignatureAccess();
session.allowPackageAccess(HELPER_PKG2, HELPER_PKG2_CERT_SHA256);
-
assertThat(session.isSameSignatureAccessAllowed()).isTrue();
assertThat(session.isPackageAccessAllowed(HELPER_PKG2, HELPER_PKG2_CERT_SHA256))
.isTrue();
assertThat(session.isPublicAccessAllowed()).isFalse();
-
- final CompletableFuture<Integer> callback = new CompletableFuture<>();
- session.commit(mContext.getMainExecutor(), callback::complete);
- assertThat(callback.get(TIMEOUT_COMMIT_CALLBACK_SEC, TimeUnit.SECONDS))
- .isEqualTo(0);
- }
+ });
assertPkgCanAccess(blobData, connection1);
assertPkgCanAccess(blobData, connection2);
@@ -563,7 +536,7 @@
@Test
public void testSessionCommit() throws Exception {
- final DummyBlobData blobData = new DummyBlobData(mContext);
+ final DummyBlobData blobData = new DummyBlobData.Builder(mContext).build();
blobData.prepare();
try {
final long sessionId = mBlobStoreManager.createSession(blobData.getBlobHandle());
@@ -594,7 +567,7 @@
@Test
public void testOpenBlob() throws Exception {
- final DummyBlobData blobData = new DummyBlobData(mContext);
+ final DummyBlobData blobData = new DummyBlobData.Builder(mContext).build();
blobData.prepare();
try {
final long sessionId = mBlobStoreManager.createSession(blobData.getBlobHandle());
@@ -631,43 +604,104 @@
@Test
public void testAcquireReleaseLease() throws Exception {
- final DummyBlobData blobData = new DummyBlobData(mContext);
+ final DummyBlobData blobData = new DummyBlobData.Builder(mContext).build();
blobData.prepare();
try {
final long sessionId = mBlobStoreManager.createSession(blobData.getBlobHandle());
assertThat(sessionId).isGreaterThan(0L);
- try (BlobStoreManager.Session session = mBlobStoreManager.openSession(sessionId)) {
- blobData.writeToSession(session);
-
- final CompletableFuture<Integer> callback = new CompletableFuture<>();
- session.commit(mContext.getMainExecutor(), callback::complete);
- assertThat(callback.get(TIMEOUT_COMMIT_CALLBACK_SEC, TimeUnit.SECONDS))
- .isEqualTo(0);
- }
+ commitBlob(blobData);
assertThrows(IllegalArgumentException.class, () ->
- mBlobStoreManager.acquireLease(blobData.getBlobHandle(),
+ acquireLease(mContext, blobData.getBlobHandle(),
R.string.test_desc, blobData.getExpiryTimeMillis() + 1000));
+ assertNoLeasedBlobs(mBlobStoreManager);
- mBlobStoreManager.acquireLease(blobData.getBlobHandle(), R.string.test_desc,
+ acquireLease(mContext, blobData.getBlobHandle(), R.string.test_desc,
blobData.getExpiryTimeMillis() - 1000);
- mBlobStoreManager.acquireLease(blobData.getBlobHandle(), R.string.test_desc);
- // TODO: verify acquiring lease took effect.
- mBlobStoreManager.releaseLease(blobData.getBlobHandle());
+ assertLeasedBlobs(mBlobStoreManager, blobData.getBlobHandle());
+ acquireLease(mContext, blobData.getBlobHandle(), R.string.test_desc);
+ assertLeasedBlobs(mBlobStoreManager, blobData.getBlobHandle());
+ releaseLease(mContext, blobData.getBlobHandle());
+ assertNoLeasedBlobs(mBlobStoreManager);
- mBlobStoreManager.acquireLease(blobData.getBlobHandle(), "Test description",
+ acquireLease(mContext, blobData.getBlobHandle(), "Test description",
blobData.getExpiryTimeMillis() - 20000);
- mBlobStoreManager.acquireLease(blobData.getBlobHandle(), "Test description two");
- mBlobStoreManager.releaseLease(blobData.getBlobHandle());
+ assertLeasedBlobs(mBlobStoreManager, blobData.getBlobHandle());
+ acquireLease(mContext, blobData.getBlobHandle(), "Test description two");
+ assertLeasedBlobs(mBlobStoreManager, blobData.getBlobHandle());
+ releaseLease(mContext, blobData.getBlobHandle());
+ assertNoLeasedBlobs(mBlobStoreManager);
} finally {
blobData.delete();
}
}
@Test
+ public void testAcquireLease_multipleLeases() throws Exception {
+ final DummyBlobData blobData = new DummyBlobData.Builder(mContext).build();
+ final DummyBlobData blobData2 = new DummyBlobData.Builder(mContext)
+ .setRandomSeed(42)
+ .build();
+ blobData.prepare();
+ blobData2.prepare();
+ try {
+ commitBlob(blobData);
+
+ acquireLease(mContext, blobData.getBlobHandle(), R.string.test_desc,
+ blobData.getExpiryTimeMillis() - 1000);
+ assertLeasedBlobs(mBlobStoreManager, blobData.getBlobHandle());
+
+ commitBlob(blobData2);
+
+ acquireLease(mContext, blobData2.getBlobHandle(), "Test desc2",
+ blobData.getExpiryTimeMillis() - 2000);
+ assertLeasedBlobs(mBlobStoreManager, blobData.getBlobHandle(),
+ blobData2.getBlobHandle());
+
+ releaseLease(mContext, blobData.getBlobHandle());
+ assertLeasedBlobs(mBlobStoreManager, blobData2.getBlobHandle());
+
+ releaseLease(mContext, blobData2.getBlobHandle());
+ assertNoLeasedBlobs(mBlobStoreManager);
+ } finally {
+ blobData.delete();
+ blobData2.delete();
+ }
+ }
+
+ @Test
+ public void testAcquireRelease_deleteImmediately() throws Exception {
+ final DummyBlobData blobData = new DummyBlobData.Builder(mContext).build();
+ blobData.prepare();
+ final long waitDurationMs = TimeUnit.SECONDS.toMillis(1);
+ runWithKeyValue(KEY_LEASE_ACQUISITION_WAIT_DURATION_MS, String.valueOf(waitDurationMs),
+ () -> {
+ try {
+ commitBlob(blobData);
+
+ acquireLease(mContext, blobData.getBlobHandle(), R.string.test_desc,
+ blobData.getExpiryTimeMillis());
+ assertLeasedBlobs(mBlobStoreManager, blobData.getBlobHandle());
+
+ SystemClock.sleep(waitDurationMs);
+
+ releaseLease(mContext, blobData.getBlobHandle());
+ assertNoLeasedBlobs(mBlobStoreManager);
+
+ assertThrows(SecurityException.class, () -> mBlobStoreManager.acquireLease(
+ blobData.getBlobHandle(), R.string.test_desc,
+ blobData.getExpiryTimeMillis()));
+ assertNoLeasedBlobs(mBlobStoreManager);
+ } finally {
+ blobData.delete();
+ }
+ });
+ }
+
+ @Test
public void testAcquireReleaseLease_invalidArguments() throws Exception {
- final DummyBlobData blobData = new DummyBlobData(mContext);
+ final DummyBlobData blobData = new DummyBlobData.Builder(mContext).build();
blobData.prepare();
try {
assertThrows(NullPointerException.class, () -> mBlobStoreManager.acquireLease(
@@ -689,7 +723,7 @@
@Test
public void testStorageAttributedToSelf() throws Exception {
- final DummyBlobData blobData = new DummyBlobData(mContext);
+ final DummyBlobData blobData = new DummyBlobData.Builder(mContext).build();
blobData.prepare();
final long partialFileSize = 3373L;
@@ -744,7 +778,8 @@
.isEqualTo(0);
}
- mBlobStoreManager.acquireLease(blobData.getBlobHandle(), R.string.test_desc);
+ acquireLease(mContext, blobData.getBlobHandle(), R.string.test_desc);
+ assertLeasedBlobs(mBlobStoreManager, blobData.getBlobHandle());
afterStatsForPkg = storageStatsManager
.queryStatsForPackage(UUID_DEFAULT, mContext.getPackageName(), mContext.getUser());
@@ -758,7 +793,8 @@
assertThat(afterStatsForUid.getDataBytes() - beforeStatsForUid.getDataBytes())
.isEqualTo(totalFileSize);
- mBlobStoreManager.releaseLease(blobData.getBlobHandle());
+ releaseLease(mContext, blobData.getBlobHandle());
+ assertNoLeasedBlobs(mBlobStoreManager);
afterStatsForPkg = storageStatsManager
.queryStatsForPackage(UUID_DEFAULT, mContext.getPackageName(), mContext.getUser());
@@ -774,7 +810,7 @@
@Test
public void testStorageAttribution_acquireLease() throws Exception {
- final DummyBlobData blobData = new DummyBlobData(mContext);
+ final DummyBlobData blobData = new DummyBlobData.Builder(mContext).build();
blobData.prepare();
final StorageStatsManager storageStatsManager = mContext.getSystemService(
@@ -853,6 +889,56 @@
}
}
+ private static void runWithKeyValue(String key, String value, ThrowingRunnable runnable)
+ throws Exception {
+ final AtomicReference<String> previousValue = new AtomicReference<>();
+ SystemUtil.runWithShellPermissionIdentity(() -> {
+ previousValue.set(DeviceConfig.getProperty(NAMESPACE_BLOBSTORE, key));
+ Log.i(TAG, key + " previous value: " + previousValue.get());
+ assertThat(DeviceConfig.setProperty(NAMESPACE_BLOBSTORE, key, value,
+ false /* makeDefault */)).isTrue();
+ Log.i(TAG, key + " value set: " + value);
+ });
+ try {
+ runnable.run();
+ } finally {
+ SystemUtil.runWithShellPermissionIdentity(() -> {
+ final String currentValue = DeviceConfig.getProperty(
+ NAMESPACE_BLOBSTORE, key);
+ if (!Objects.equals(previousValue.get(), currentValue)) {
+ assertThat(DeviceConfig.setProperty(NAMESPACE_BLOBSTORE,
+ key, previousValue.get(), false /* makeDefault */)).isTrue();
+ Log.i(TAG, key + " value restored: " + previousValue.get());
+ }
+ });
+ }
+ }
+
+ private void commitBlob(DummyBlobData blobData) throws Exception {
+ commitBlob(blobData, null);
+ }
+
+ private void commitBlob(DummyBlobData blobData,
+ AccessModifier accessModifier) throws Exception {
+ final long sessionId = mBlobStoreManager.createSession(blobData.getBlobHandle());
+ assertThat(sessionId).isGreaterThan(0L);
+ try (BlobStoreManager.Session session = mBlobStoreManager.openSession(sessionId)) {
+ blobData.writeToSession(session);
+
+ if (accessModifier != null) {
+ accessModifier.modify(session);
+ }
+ final CompletableFuture<Integer> callback = new CompletableFuture<>();
+ session.commit(mContext.getMainExecutor(), callback::complete);
+ assertThat(callback.get(TIMEOUT_COMMIT_CALLBACK_SEC, TimeUnit.SECONDS))
+ .isEqualTo(0);
+ }
+ }
+
+ private interface AccessModifier {
+ void modify(BlobStoreManager.Session session) throws Exception;
+ }
+
private void commitBlobFromPkg(DummyBlobData blobData, TestServiceConnection serviceConnection)
throws Exception {
commitBlobFromPkg(blobData, ICommandReceiver.FLAG_ACCESS_TYPE_PRIVATE, serviceConnection);
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEmbeddedHierarchyTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEmbeddedHierarchyTest.java
index 8f79102..4d84a73 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEmbeddedHierarchyTest.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEmbeddedHierarchyTest.java
@@ -17,6 +17,7 @@
package android.accessibilityservice.cts;
import static android.accessibilityservice.cts.utils.ActivityLaunchUtils.launchActivityAndWaitForItToBeOnscreen;
+import static android.accessibilityservice.cts.utils.AsyncUtils.DEFAULT_TIMEOUT_MS;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
@@ -27,13 +28,18 @@
import android.accessibilityservice.cts.activities.AccessibilityTestActivity;
import android.app.Instrumentation;
import android.app.UiAutomation;
+import android.graphics.Point;
import android.graphics.Rect;
+import android.hardware.display.DisplayManager;
import android.os.Bundle;
+import android.util.DisplayMetrics;
+import android.view.Display;
import android.view.SurfaceControlViewHost;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.accessibility.AccessibilityNodeInfo;
+import android.view.accessibility.AccessibilityWindowInfo;
import androidx.test.InstrumentationRegistry;
import androidx.test.rule.ActivityTestRule;
@@ -49,6 +55,7 @@
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
/**
* Tests that AccessibilityNodeInfos from an embedded hierarchy that is present to another
@@ -131,7 +138,7 @@
}
@Test
- public void testEmbeddedViewHasCorrectBoundAfterHostViewMove() {
+ public void testEmbeddedViewHasCorrectBoundAfterHostViewMove() throws TimeoutException {
final AccessibilityNodeInfo target =
findEmbeddedAccessibilityNodeInfo(sUiAutomation.getRootInActiveWindow());
@@ -140,14 +147,13 @@
final Rect oldEmbeddedViewBoundsInScreen = new Rect();
target.getBoundsInScreen(oldEmbeddedViewBoundsInScreen);
- // Move Host SurfaceView from (0, 0) to (100, 100).
- mActivity.requestNewLayoutForTest();
+ // Move Host SurfaceView from (0, 0) to (50, 50).
+ mActivity.requestNewLayoutForTest(50, 50);
- final AccessibilityNodeInfo newTarget =
- findEmbeddedAccessibilityNodeInfo(sUiAutomation.getRootInActiveWindow());
- final AccessibilityNodeInfo parent = newTarget.getParent();
+ target.refresh();
+ final AccessibilityNodeInfo parent = target.getParent();
- newTarget.getBoundsInScreen(newEmbeddedViewBoundsInScreen);
+ target.getBoundsInScreen(newEmbeddedViewBoundsInScreen);
parent.getBoundsInScreen(hostViewBoundsInScreen);
assertTrue("hostViewBoundsInScreen" + hostViewBoundsInScreen.toShortString()
@@ -160,6 +166,22 @@
newEmbeddedViewBoundsInScreen.equals(oldEmbeddedViewBoundsInScreen));
}
+ @Test
+ public void testEmbeddedViewIsInvisibleAfterMovingOutOfScreen() throws TimeoutException {
+ final AccessibilityNodeInfo target =
+ findEmbeddedAccessibilityNodeInfo(sUiAutomation.getRootInActiveWindow());
+ assertTrue("Embedded view should be visible at beginning.",
+ target.isVisibleToUser());
+
+ // Move Host SurfaceView out of screen
+ final Point screenSize = getScreenSize();
+ mActivity.requestNewLayoutForTest(screenSize.x, screenSize.y);
+
+ target.refresh();
+ assertFalse("Embedded view should be invisible after moving out of screen.",
+ target.isVisibleToUser());
+ }
+
private AccessibilityNodeInfo findEmbeddedAccessibilityNodeInfo(AccessibilityNodeInfo root) {
final int childCount = root.getChildCount();
for (int i = 0; i < childCount; i++) {
@@ -177,6 +199,15 @@
return null;
}
+ private Point getScreenSize() {
+ final DisplayManager dm = sInstrumentation.getContext().getSystemService(
+ DisplayManager.class);
+ final Display display = dm.getDisplay(Display.DEFAULT_DISPLAY);
+ final DisplayMetrics metrics = new DisplayMetrics();
+ display.getRealMetrics(metrics);
+ return new Point(metrics.widthPixels, metrics.heightPixels);
+ }
+
/**
* This class is an dummy {@link android.app.Activity} used to perform embedded hierarchy
* testing of the accessibility feature by interaction with the UI widgets.
@@ -188,9 +219,6 @@
private static final int DEFAULT_WIDTH = 150;
private static final int DEFAULT_HEIGHT = 150;
- private static final int POSITION_X = 50;
- private static final int POSITION_Y = 50;
-
private SurfaceView mSurfaceView;
private SurfaceControlViewHost mViewHost;
@@ -211,7 +239,7 @@
View layout = getLayoutInflater().inflate(
R.layout.accessibility_embedded_hierarchy_test_embedded_side, null);
- mViewHost.addView(layout, DEFAULT_WIDTH, DEFAULT_HEIGHT);
+ mViewHost.setView(layout, DEFAULT_WIDTH, DEFAULT_HEIGHT);
mCountDownLatch.countDown();
}
@@ -234,12 +262,20 @@
}
}
- public void requestNewLayoutForTest() {
- sInstrumentation.runOnMainSync(() -> {
- mSurfaceView.setX(POSITION_X);
- mSurfaceView.setY(POSITION_Y);
- mSurfaceView.requestLayout();
- });
+ public void requestNewLayoutForTest(int x, int y) throws TimeoutException {
+ sUiAutomation.executeAndWaitForEvent(
+ () -> sInstrumentation.runOnMainSync(() -> {
+ mSurfaceView.setX(x);
+ mSurfaceView.setY(y);
+ mSurfaceView.requestLayout();
+ }),
+ (event) -> {
+ final Rect boundsInScreen = new Rect();
+ final AccessibilityWindowInfo window =
+ sUiAutomation.getRootInActiveWindow().getWindow();
+ window.getBoundsInScreen(boundsInScreen);
+ return !boundsInScreen.isEmpty();
+ }, DEFAULT_TIMEOUT_MS);
}
}
}
diff --git a/tests/admin/src/android/admin/cts/DevicePolicyManagerTest.java b/tests/admin/src/android/admin/cts/DevicePolicyManagerTest.java
index c1a02ab..1c38b39 100644
--- a/tests/admin/src/android/admin/cts/DevicePolicyManagerTest.java
+++ b/tests/admin/src/android/admin/cts/DevicePolicyManagerTest.java
@@ -1114,29 +1114,29 @@
}
}
- public void testSetProtectedPackages_failIfNotDeviceOwner() {
+ public void testSetUserControlDisabledPackages_failIfNotDeviceOwner() {
if (!mDeviceAdmin) {
- Log.w(TAG, "Skipping testSetProtectedPackages_failIfNotDeviceOwner()");
+ Log.w(TAG, "Skipping testSetUserControlDisabledPackages_failIfNotDeviceOwner()");
return;
}
final String TEST_PACKAGE_NAME = "package1";
List<String> packages = new ArrayList<>();
packages.add(TEST_PACKAGE_NAME);
try {
- mDevicePolicyManager.setProtectedPackages(mComponent, packages);
- fail("setProtectedPackages did not throw expected SecurityException");
+ mDevicePolicyManager.setUserControlDisabledPackages(mComponent, packages);
+ fail("setUserControlDisabledPackages did not throw expected SecurityException");
} catch(SecurityException e) {
}
}
- public void testGetProtectedPackages_failIfNotDeviceOwner() {
+ public void testGetUserControlDisabledPackages_failIfNotDeviceOwner() {
if (!mDeviceAdmin) {
- Log.w(TAG, "Skipping testGetProtectedPackages_failIfNotDeviceOwner()");
+ Log.w(TAG, "Skipping testGetUserControlDisabledPackages_failIfNotDeviceOwner()");
return;
}
try {
- mDevicePolicyManager.getProtectedPackages(mComponent);
- fail("getProtectedPackages did not throw expected SecurityException");
+ mDevicePolicyManager.getUserControlDisabledPackages(mComponent);
+ fail("getUserControlDisabledPackages did not throw expected SecurityException");
} catch(SecurityException e) {
}
}
diff --git a/tests/app/ActivityManagerApi29Test/AndroidManifest.xml b/tests/app/ActivityManagerApi29Test/AndroidManifest.xml
index 86f1cd2..0c75ff4 100644
--- a/tests/app/ActivityManagerApi29Test/AndroidManifest.xml
+++ b/tests/app/ActivityManagerApi29Test/AndroidManifest.xml
@@ -35,7 +35,7 @@
</intent-filter>
</activity>
<service android:name="LocationForegroundService"
- android:foregroundServiceType="location"
+ android:foregroundServiceType="location|camera|microphone"
android:exported="true">
</service>
</application>
diff --git a/tests/app/AppExitTest/AndroidManifest.xml b/tests/app/AppExitTest/AndroidManifest.xml
index a73a72e..316959d 100644
--- a/tests/app/AppExitTest/AndroidManifest.xml
+++ b/tests/app/AppExitTest/AndroidManifest.xml
@@ -18,6 +18,9 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="android.app.cts.appexit">
+ <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS"/>
+ <uses-permission android:name="android.permission.READ_LOGS"/>
+
<application android:usesCleartextTraffic="true">
<uses-library android:name="android.test.runner" />
</application>
diff --git a/tests/app/AppExitTest/AndroidTest.xml b/tests/app/AppExitTest/AndroidTest.xml
index 0fdb0a7..1658417 100644
--- a/tests/app/AppExitTest/AndroidTest.xml
+++ b/tests/app/AppExitTest/AndroidTest.xml
@@ -26,6 +26,16 @@
<option name="test-file-name" value="CtsSimpleApp.apk" />
<option name="test-file-name" value="CtsAppExitTestCases.apk" />
</target_preparer>
+ <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+ <option name="run-command"
+ value="pm grant android.app.cts.appexit android.permission.PACKAGE_USAGE_STATS" />
+ <option name="run-command"
+ value="pm grant android.app.cts.appexit android.permission.READ_LOGS" />
+ <option name="teardown-command"
+ value="pm revoke android.app.cts.appexit android.permission.PACKAGE_USAGE_STATS"/>
+ <option name="teardown-command"
+ value="pm revoke android.app.cts.appexit android.permission.READ_LOGS"/>
+ </target_preparer>
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
<option name="package" value="android.app.cts.appexit" />
diff --git a/tests/app/AppExitTest/src/android/app/cts/ActivityManagerAppExitInfoTest.java b/tests/app/AppExitTest/src/android/app/cts/ActivityManagerAppExitInfoTest.java
index b815cc0..5aaca09 100644
--- a/tests/app/AppExitTest/src/android/app/cts/ActivityManagerAppExitInfoTest.java
+++ b/tests/app/AppExitTest/src/android/app/cts/ActivityManagerAppExitInfoTest.java
@@ -21,11 +21,13 @@
import android.app.ApplicationExitInfo;
import android.app.Instrumentation;
import android.app.cts.android.app.cts.tools.WatchUidRunner;
+import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
-import android.content.pm.PackageManager;
+import android.content.IntentFilter;
import android.os.Bundle;
+import android.os.DropBoxManager;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
@@ -46,8 +48,10 @@
import com.android.compatibility.common.util.ShellIdentityUtils;
import com.android.compatibility.common.util.SystemUtil;
+import com.android.internal.util.ArrayUtils;
import com.android.internal.util.MemInfoReader;
+import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.FileDescriptor;
@@ -71,6 +75,8 @@
"com.android.cts.launcherapps.simpleapp.SimpleService4";
private static final String STUB_SERVICE_REMOTE_NAME =
"com.android.cts.launcherapps.simpleapp.SimpleService5";
+ private static final String STUB_SERVICE_ISOLATED_NAME =
+ "com.android.cts.launcherapps.simpleapp.SimpleService6";
private static final String STUB_RECEIVER_NAMWE =
"com.android.cts.launcherapps.simpleapp.SimpleReceiver";
private static final String STUB_ROCESS_NAME = STUB_PACKAGE_NAME;
@@ -81,6 +87,7 @@
private static final String EXTRA_ACTION = "action";
private static final String EXTRA_MESSENGER = "messenger";
private static final String EXTRA_PROCESS_NAME = "process";
+ private static final String EXTRA_COOKIE = "cookie";
private static final int ACTION_NONE = 0;
private static final int ACTION_FINISH = 1;
@@ -106,6 +113,9 @@
private int mStubPackageOtherUid;
private int mStubPackageOtherUserPid;
private int mStubPackageRemoteOtherUserPid;
+ private int mStubPackageIsolatedUid;
+ private int mStubPackageIsolatedPid;
+ private String mStubPackageIsolatedProcessName;
private WatchUidRunner mWatcher;
private WatchUidRunner mOtherUidWatcher;
private ActivityManager mActivityManager;
@@ -119,6 +129,7 @@
private UserHandle mCurrentUserHandle;
private int mOtherUserId;
private UserHandle mOtherUserHandle;
+ private DropBoxManager.Entry mAnrEntry;
@Override
protected void setUp() throws Exception {
@@ -152,7 +163,6 @@
mStubPackagePid = msg.arg1;
assertTrue(mStubPackagePid > 0);
}
- didSomething = true;
} else if (STUB_REMOTE_ROCESS_NAME.equals(processName)) {
if (mOtherUserId != 0 && UserHandle.getUserId(msg.arg2) == mOtherUserId) {
mStubPackageRemoteOtherUserPid = msg.arg1;
@@ -161,13 +171,17 @@
mStubPackageRemotePid = msg.arg1;
assertTrue(mStubPackageRemotePid > 0);
}
- didSomething = true;
+ } else { // must be isolated process
+ mStubPackageIsolatedPid = msg.arg1;
+ mStubPackageIsolatedUid = msg.arg2;
+ mStubPackageIsolatedProcessName = processName;
+ assertTrue(mStubPackageIsolatedPid > 0);
+ assertTrue(mStubPackageIsolatedUid > 0);
+ assertNotNull(processName);
}
- if (didSomething) {
- if (mLatch != null) {
- mLatch.countDown();
- }
+ if (mLatch != null) {
+ mLatch.countDown();
}
}
@@ -270,15 +284,18 @@
// Start the target package
private void startService(int commandCode, String serviceName, boolean waitForGone,
boolean other) {
- startService(commandCode, serviceName, waitForGone, true, other);
+ startService(commandCode, serviceName, waitForGone, true, other, false, null);
}
private void startService(int commandCode, String serviceName, boolean waitForGone,
- boolean waitForIdle, boolean other) {
+ boolean waitForIdle, boolean other, boolean includeCookie, byte[] cookie) {
Intent intent = new Intent(EXIT_ACTION);
intent.setClassName(STUB_PACKAGE_NAME, serviceName);
intent.putExtra(EXTRA_ACTION, commandCode);
intent.putExtra(EXTRA_MESSENGER, mMessenger);
+ if (includeCookie) {
+ intent.putExtra(EXTRA_COOKIE, cookie);
+ }
mLatch = new CountDownLatch(1);
UserHandle user = other ? mOtherUserHandle : mCurrentUserHandle;
WatchUidRunner watcher = other ? mOtherUidWatcher : mWatcher;
@@ -292,6 +309,16 @@
awaitForLatch(mLatch);
}
+ private void startIsolatedService(int commandCode, String serviceName) {
+ Intent intent = new Intent(EXIT_ACTION);
+ intent.setClassName(STUB_PACKAGE_NAME, serviceName);
+ intent.putExtra(EXTRA_ACTION, commandCode);
+ intent.putExtra(EXTRA_MESSENGER, mMessenger);
+ mLatch = new CountDownLatch(1);
+ mContext.startServiceAsUser(intent, mCurrentUserHandle);
+ awaitForLatch(mLatch);
+ }
+
private void waitForGone(WatchUidRunner watcher) {
watcher.waitFor(WatchUidRunner.CMD_GONE, null);
// Give a few seconds to generate the exit report.
@@ -464,6 +491,21 @@
// Remove old records to avoid interference with the test.
clearHistoricalExitInfo();
+ final DropBoxManager dbox = mContext.getSystemService(DropBoxManager.class);
+ final CountDownLatch dboxLatch = new CountDownLatch(1);
+ final BroadcastReceiver receiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ final String tag_anr = "data_app_anr";
+ if (tag_anr.equals(intent.getStringExtra(DropBoxManager.EXTRA_TAG))) {
+ mAnrEntry = dbox.getNextEntry(tag_anr, intent.getLongExtra(
+ DropBoxManager.EXTRA_TIME, 0) - 1);
+ dboxLatch.countDown();
+ }
+ }
+ };
+ mContext.registerReceiver(receiver,
+ new IntentFilter(DropBoxManager.ACTION_DROPBOX_ENTRY_ADDED));
final long timeout = Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.BROADCAST_FG_CONSTANTS, 10 * 1000) * 3;
@@ -483,6 +525,10 @@
// This will result an ANR
mContext.sendOrderedBroadcast(intent, null);
+ // Wait for the early ANR
+ monitor.waitFor(Monitor.WAIT_FOR_EARLY_ANR, timeout);
+ // Continue, so we could collect ANR traces
+ monitor.sendCommand(Monitor.CMD_CONTINUE);
// Wait for the ANR
monitor.waitFor(Monitor.WAIT_FOR_ANR, timeout);
// Kill it
@@ -491,67 +537,85 @@
waitForGone(mWatcher);
long now2 = System.currentTimeMillis();
+ awaitForLatch(dboxLatch);
+ assertTrue(mAnrEntry != null);
+
List<ApplicationExitInfo> list = ShellIdentityUtils.invokeMethodWithShellPermissions(
STUB_PACKAGE_NAME, mStubPackagePid, 1,
mActivityManager::getHistoricalProcessExitReasons,
android.Manifest.permission.DUMP);
assertTrue(list != null && list.size() == 1);
- verify(list.get(0), mStubPackagePid, mStubPackageUid, STUB_PACKAGE_NAME,
+ ApplicationExitInfo info = list.get(0);
+ verify(info, mStubPackagePid, mStubPackageUid, STUB_PACKAGE_NAME,
ApplicationExitInfo.REASON_ANR, null, null, now, now2);
+ // Verify the traces
+
+ // Read from dropbox
+ final String dboxTrace = mAnrEntry.getText(0x100000 /* 1M */);
+ assertFalse(TextUtils.isEmpty(dboxTrace));
+
+ // Read the input stream from the ApplicationExitInfo
+ String trace = ShellIdentityUtils.invokeMethodWithShellPermissions(info, (i) -> {
+ try (BufferedInputStream input = new BufferedInputStream(i.getTraceInputStream())) {
+ StringBuilder sb = new StringBuilder();
+ byte[] buf = new byte[8192];
+ while (true) {
+ final int len = input.read(buf, 0, buf.length);
+ if (len <= 0) {
+ break;
+ }
+ sb.append(new String(buf, 0, len));
+ }
+ return sb.toString();
+ } catch (IOException e) {
+ return null;
+ }
+ }, android.Manifest.permission.DUMP);
+ assertFalse(TextUtils.isEmpty(trace));
+ assertTrue(trace.indexOf(Integer.toString(info.getPid())) >= 0);
+ assertTrue(trace.indexOf("Cmd line: " + STUB_PACKAGE_NAME) >= 0);
+ assertTrue(dboxTrace.indexOf(trace) >= 0);
+
monitor.finish();
+ mContext.unregisterReceiver(receiver);
}
public void testOther() throws Exception {
// Remove old records to avoid interference with the test.
clearHistoricalExitInfo();
- // Enable a compat feature
- executeShellCmd("am compat enable " + PackageManager.FILTER_APPLICATION_QUERY
- + " " + STUB_PACKAGE_NAME);
- mInstrumentation.getUiAutomation().grantRuntimePermission(
- STUB_PACKAGE_NAME, android.Manifest.permission.READ_CALENDAR);
long now = System.currentTimeMillis();
- // Start a process and do nothing
- startService(ACTION_FINISH, STUB_SERVICE_NAME, false, false);
+ // Start an isolated process and do nothing
+ startIsolatedService(ACTION_NONE, STUB_SERVICE_ISOLATED_NAME);
- // Enable high frequency memory sampling
- executeShellCmd("dumpsys procstats --start-testing");
- // Sleep for a while to wait for the sampling of memory info
- sleep(10000);
- // Stop the high frequency memory sampling
- executeShellCmd("dumpsys procstats --stop-testing");
- // Get the memory info from it.
- String dump = executeShellCmd("dumpsys activity processes " + STUB_PACKAGE_NAME);
- assertNotNull(dump);
- final String lastPss = extractMemString(dump, " lastPss=", ' ');
- final String lastRss = extractMemString(dump, " lastRss=", '\n');
+ final WatchUidRunner watcher = new WatchUidRunner(mInstrumentation,
+ mStubPackageIsolatedUid, WAITFOR_MSEC);
- // Disable the compat feature
- executeShellCmd("am compat disable " + PackageManager.FILTER_APPLICATION_QUERY
- + " " + STUB_PACKAGE_NAME);
+ // Finish the service in the isolated process
+ startIsolatedService(ACTION_FINISH, STUB_SERVICE_ISOLATED_NAME);
- waitForGone(mWatcher);
+ try {
+ // Isolated process should have been killed as long as its service is done.
+ waitForGone(watcher);
+ } finally {
+ watcher.finish();
+ }
long now2 = System.currentTimeMillis();
List<ApplicationExitInfo> list = ShellIdentityUtils.invokeMethodWithShellPermissions(
- STUB_PACKAGE_NAME, mStubPackagePid, 1,
+ STUB_PACKAGE_NAME, mStubPackageIsolatedPid, 1,
mActivityManager::getHistoricalProcessExitReasons,
android.Manifest.permission.DUMP);
assertTrue(list != null && list.size() == 1);
ApplicationExitInfo info = list.get(0);
- verify(info, mStubPackagePid, mStubPackageUid, STUB_PACKAGE_NAME,
- ApplicationExitInfo.REASON_OTHER, null, "PlatformCompat overrides", now, now2);
-
- // Also verify that we get the expected meminfo
- assertEquals(lastPss, DebugUtils.sizeValueToString(
- info.getPss() * 1024, new StringBuilder()));
- assertEquals(lastRss, DebugUtils.sizeValueToString(
- info.getRss() * 1024, new StringBuilder()));
+ verify(info, mStubPackageIsolatedPid, mStubPackageIsolatedUid,
+ mStubPackageIsolatedProcessName, ApplicationExitInfo.REASON_OTHER, null,
+ "isolated not needed", now, now2);
}
private String extractMemString(String dump, String prefix, char nextSep) {
@@ -575,6 +639,18 @@
// Start a process and do nothing
startService(ACTION_FINISH, STUB_SERVICE_NAME, false, false);
+ // Enable high frequency memory sampling
+ executeShellCmd("dumpsys procstats --start-testing");
+ // Sleep for a while to wait for the sampling of memory info
+ sleep(10000);
+ // Stop the high frequency memory sampling
+ executeShellCmd("dumpsys procstats --stop-testing");
+ // Get the memory info from it.
+ String dump = executeShellCmd("dumpsys activity processes " + STUB_PACKAGE_NAME);
+ assertNotNull(dump);
+ final String lastPss = extractMemString(dump, " lastPss=", ' ');
+ final String lastRss = extractMemString(dump, " lastRss=", '\n');
+
// Revoke the read calendar permission
mInstrumentation.getUiAutomation().revokeRuntimePermission(
STUB_PACKAGE_NAME, android.Manifest.permission.READ_CALENDAR);
@@ -591,6 +667,12 @@
ApplicationExitInfo info = list.get(0);
verify(info, mStubPackagePid, mStubPackageUid, STUB_PACKAGE_NAME,
ApplicationExitInfo.REASON_PERMISSION_CHANGE, null, null, now, now2);
+
+ // Also verify that we get the expected meminfo
+ assertEquals(lastPss, DebugUtils.sizeValueToString(
+ info.getPss() * 1024, new StringBuilder()));
+ assertEquals(lastRss, DebugUtils.sizeValueToString(
+ info.getRss() * 1024, new StringBuilder()));
}
public void testCrash() throws Exception {
@@ -691,7 +773,7 @@
now = System.currentTimeMillis();
// Now let the provider exit itself
- startService(ACTION_KILL_PROVIDER, STUB_SERVICE_NAME, false, false, false);
+ startService(ACTION_KILL_PROVIDER, STUB_SERVICE_NAME, false, false, false, false, null);
// Wait for both of the processes gone
waitForGone(mWatcher);
@@ -789,25 +871,39 @@
// Create the test user, we'll remove it during tearDown
prepareTestUser();
+ final byte[] cookie0 = {(byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x03,
+ (byte) 0x04, (byte) 0x05, (byte) 0x06, (byte) 0x07};
+ final byte[] cookie1 = {(byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x04,
+ (byte) 0x05, (byte) 0x06, (byte) 0x07, (byte) 0x08};
+ final byte[] cookie2 = {(byte) 0x02, (byte) 0x03, (byte) 0x04, (byte) 0x05,
+ (byte) 0x06, (byte) 0x07, (byte) 0x08, (byte) 0x01};
+ final byte[] cookie3 = {(byte) 0x03, (byte) 0x04, (byte) 0x05, (byte) 0x06,
+ (byte) 0x07, (byte) 0x08, (byte) 0x01, (byte) 0x02};
+ final byte[] cookie4 = {(byte) 0x04, (byte) 0x05, (byte) 0x06, (byte) 0x07,
+ (byte) 0x08, (byte) 0x01, (byte) 0x02, (byte) 0x03};
+ final byte[] cookie5 = null;
+
long now = System.currentTimeMillis();
- // Start a process and exit itself
- startService(ACTION_EXIT, STUB_SERVICE_NAME, true, false);
+ // Start a process and do nothing
+ startService(ACTION_NONE, STUB_SERVICE_NAME, false, true, false, true, cookie0);
+ // request to exit by itself with a different cookie
+ startService(ACTION_EXIT, STUB_SERVICE_NAME, true, false, false, true, cookie1);
long now2 = System.currentTimeMillis();
// Start the process in a secondary user and kill itself
- startService(ACTION_KILL, STUB_SERVICE_NAME, true, true);
+ startService(ACTION_KILL, STUB_SERVICE_NAME, true, true, true, true, cookie2);
long now3 = System.currentTimeMillis();
// Start a remote process in a secondary user and exit
- startService(ACTION_EXIT, STUB_SERVICE_REMOTE_NAME, true, true);
+ startService(ACTION_EXIT, STUB_SERVICE_REMOTE_NAME, true, true, true, true, cookie3);
long now4 = System.currentTimeMillis();
// Start a remote process and kill itself
- startService(ACTION_KILL, STUB_SERVICE_REMOTE_NAME, true, false);
+ startService(ACTION_KILL, STUB_SERVICE_REMOTE_NAME, true, true, false, true, cookie4);
long now5 = System.currentTimeMillis();
// drop the permissions
@@ -845,9 +941,10 @@
assertTrue(list != null && list.size() == 2);
verify(list.get(0), mStubPackageRemotePid, mStubPackageUid, STUB_REMOTE_ROCESS_NAME,
- ApplicationExitInfo.REASON_SIGNALED, OsConstants.SIGKILL, null, now4, now5);
+ ApplicationExitInfo.REASON_SIGNALED, OsConstants.SIGKILL, null, now4, now5,
+ cookie4);
verify(list.get(1), mStubPackagePid, mStubPackageUid, STUB_ROCESS_NAME,
- ApplicationExitInfo.REASON_EXIT_SELF, EXIT_CODE, null, now, now2);
+ ApplicationExitInfo.REASON_EXIT_SELF, EXIT_CODE, null, now, now2, cookie1);
// Now try the other user
try {
@@ -870,16 +967,17 @@
assertTrue(list != null && list.size() == 2);
verify(list.get(0), mStubPackageRemoteOtherUserPid, mStubPackageOtherUid,
STUB_REMOTE_ROCESS_NAME, ApplicationExitInfo.REASON_EXIT_SELF, EXIT_CODE,
- null, now3, now4);
+ null, now3, now4, cookie3);
verify(list.get(1), mStubPackageOtherUserPid, mStubPackageOtherUid, STUB_ROCESS_NAME,
- ApplicationExitInfo.REASON_SIGNALED, OsConstants.SIGKILL, null, now2, now3);
+ ApplicationExitInfo.REASON_SIGNALED, OsConstants.SIGKILL, null,
+ now2, now3, cookie2);
// Get the full user permission in order to start service as other user
mInstrumentation.getUiAutomation().adoptShellPermissionIdentity(
android.Manifest.permission.INTERACT_ACROSS_USERS,
android.Manifest.permission.INTERACT_ACROSS_USERS_FULL);
// Start the process in a secondary user and do nothing
- startService(ACTION_NONE, STUB_SERVICE_NAME, false, true);
+ startService(ACTION_NONE, STUB_SERVICE_NAME, false, true, true, true, cookie5);
// drop the permissions
mInstrumentation.getUiAutomation().dropShellPermissionIdentity();
@@ -896,7 +994,7 @@
android.Manifest.permission.DUMP,
android.Manifest.permission.INTERACT_ACROSS_USERS);
verify(list.get(0), mStubPackageOtherUserPid, mStubPackageOtherUid, STUB_ROCESS_NAME,
- ApplicationExitInfo.REASON_USER_STOPPED, null, null, now6, now7);
+ ApplicationExitInfo.REASON_USER_STOPPED, null, null, now6, now7, cookie5);
int otherUserId = mOtherUserId;
// Now remove the other user
@@ -927,13 +1025,20 @@
assertTrue(list != null && list.size() == 2);
verify(list.get(0), mStubPackageRemotePid, mStubPackageUid, STUB_REMOTE_ROCESS_NAME,
- ApplicationExitInfo.REASON_SIGNALED, OsConstants.SIGKILL, null, now4, now5);
+ ApplicationExitInfo.REASON_SIGNALED, OsConstants.SIGKILL, null, now4, now5,
+ cookie4);
verify(list.get(1), mStubPackagePid, mStubPackageUid, STUB_ROCESS_NAME,
- ApplicationExitInfo.REASON_EXIT_SELF, EXIT_CODE, null, now, now2);
+ ApplicationExitInfo.REASON_EXIT_SELF, EXIT_CODE, null, now, now2, cookie1);
}
private void verify(ApplicationExitInfo info, int pid, int uid, String processName,
int reason, Integer status, String description, long before, long after) {
+ verify(info, pid, uid, processName, reason, status, description, before, after, null);
+ }
+
+ private void verify(ApplicationExitInfo info, int pid, int uid, String processName,
+ int reason, Integer status, String description, long before, long after,
+ byte[] cookie) {
assertNotNull(info);
assertEquals(pid, info.getPid());
assertEquals(uid, info.getRealUid());
@@ -947,13 +1052,17 @@
}
assertTrue(before <= info.getTimestamp());
assertTrue(after >= info.getTimestamp());
+ assertTrue(ArrayUtils.equals(info.getProcessStateSummary(), cookie,
+ cookie == null ? 0 : cookie.length));
}
/**
* A utility class interact with "am monitor"
*/
private static class Monitor {
- static final String WAIT_FOR_ANR = "Waiting after early ANR... available commands:";
+ static final String WAIT_FOR_EARLY_ANR = "Waiting after early ANR... available commands:";
+ static final String WAIT_FOR_ANR = "Waiting after ANR... available commands:";
+ static final String CMD_CONTINUE = "c";
static final String CMD_KILL = "k";
final Instrumentation mInstrumentation;
diff --git a/tests/app/app/AndroidManifest.xml b/tests/app/app/AndroidManifest.xml
index 59368ad..c73b7d1 100644
--- a/tests/app/app/AndroidManifest.xml
+++ b/tests/app/app/AndroidManifest.xml
@@ -135,14 +135,15 @@
<service android:name="android.app.stubs.LocalStoppedService" />
- <service android:name="android.app.stubs.LocalForegroundService">
+ <service android:name="android.app.stubs.LocalForegroundService"
+ android:foregroundServiceType="camera|microphone">
<intent-filter>
<action android:name="android.app.stubs.FOREGROUND_SERVICE" />
</intent-filter>
</service>
<service android:name="android.app.stubs.LocalForegroundServiceLocation"
- android:foregroundServiceType="location">
+ android:foregroundServiceType="location|camera|microphone">
<intent-filter>
<action android:name="android.app.stubs.FOREGROUND_SERVICE_LOCATION" />
</intent-filter>
diff --git a/tests/app/app/src/android/app/stubs/LocalForegroundServiceLocation.java b/tests/app/app/src/android/app/stubs/LocalForegroundServiceLocation.java
index e013dc2..56346db 100644
--- a/tests/app/app/src/android/app/stubs/LocalForegroundServiceLocation.java
+++ b/tests/app/app/src/android/app/stubs/LocalForegroundServiceLocation.java
@@ -63,7 +63,7 @@
.setContentTitle(getNotificationTitle(mNotificationId))
.setSmallIcon(R.drawable.black)
.build();
- startForeground(mNotificationId, notification, type);
+ startForeground(mNotificationId, notification);
//assertEquals(type, getForegroundServiceType());
break;
default:
diff --git a/tests/app/app/src/android/app/stubs/SendBubbleActivity.java b/tests/app/app/src/android/app/stubs/SendBubbleActivity.java
index e2552bc..223f885 100644
--- a/tests/app/app/src/android/app/stubs/SendBubbleActivity.java
+++ b/tests/app/app/src/android/app/stubs/SendBubbleActivity.java
@@ -28,7 +28,6 @@
import android.graphics.drawable.Icon;
import android.os.Bundle;
import android.os.SystemClock;
-import android.util.Log;
/**
* Used by NotificationManagerTest for testing policy around bubbles, this activity is able to
@@ -59,7 +58,7 @@
* Sends a notification that has bubble metadata but the rest of the notification isn't
* configured correctly so the system won't allow it to bubble.
*/
- public void sendInvalidBubble(int i, boolean autoExpand) {
+ public void sendInvalidBubble(boolean autoExpand) {
Context context = getApplicationContext();
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, new Intent(), 0);
@@ -75,7 +74,6 @@
NotificationManager noMan = (NotificationManager) context.getSystemService(
Context.NOTIFICATION_SERVICE);
noMan.notify(BUBBLE_NOTIF_ID, n);
- Log.d(TAG, "posting bubble: " + n + ", " + i);
}
/** Sends a notification that is properly configured to bubble. */
diff --git a/tests/app/src/android/app/cts/ActivityManagerTest.java b/tests/app/src/android/app/cts/ActivityManagerTest.java
index 277ec3a..61b5cbc 100644
--- a/tests/app/src/android/app/cts/ActivityManagerTest.java
+++ b/tests/app/src/android/app/cts/ActivityManagerTest.java
@@ -80,6 +80,12 @@
private static final String PACKAGE_NAME_APP1 = "com.android.app1";
+ private static final String MCC_TO_UPDATE = "987";
+ private static final String MNC_TO_UPDATE = "654";
+ private static final String SHELL_COMMAND_GET_CONFIG = "am get-config";
+ private static final String SHELL_COMMAND_RESULT_CONFIG_NAME_MCC = "mcc";
+ private static final String SHELL_COMMAND_RESULT_CONFIG_NAME_MNC = "mnc";
+
// Return states of the ActivityReceiverFilter.
public static final int RESULT_PASS = 1;
public static final int RESULT_FAIL = 2;
@@ -333,6 +339,11 @@
Log.d(TAG, "executed[" + cmd + "]; output[" + output.trim() + "]");
}
+ private String executeShellCommand(String cmd) throws IOException {
+ final UiDevice uiDevice = UiDevice.getInstance(mInstrumentation);
+ return uiDevice.executeShellCommand(cmd).trim();
+ }
+
private void setForcedAppStandby(String packageName, boolean enabled) throws IOException {
final StringBuilder cmdBuilder = new StringBuilder("appops set ")
.append(packageName)
@@ -426,6 +437,62 @@
}
/**
+ * Due to the corresponding API is hidden in R and will be public in S, this test
+ * is commented and will be un-commented in Android S.
+ *
+ public void testUpdateMccMncConfiguration() throws Exception {
+ // Store the original mcc mnc to set back
+ String[] mccMncConfigOriginal = new String[2];
+ // Store other configs to check they won't be affected
+ Set<String> otherConfigsOriginal = new HashSet<String>();
+ getMccMncConfigsAndOthers(mccMncConfigOriginal, otherConfigsOriginal);
+
+ String[] mccMncConfigToUpdate = new String[] {MCC_TO_UPDATE, MNC_TO_UPDATE};
+ boolean success = ShellIdentityUtils.invokeMethodWithShellPermissions(mActivityManager,
+ (am) -> am.updateMccMncConfiguration(mccMncConfigToUpdate[0],
+ mccMncConfigToUpdate[1]));
+
+ if (success) {
+ String[] mccMncConfigUpdated = new String[2];
+ Set<String> otherConfigsUpdated = new HashSet<String>();
+ getMccMncConfigsAndOthers(mccMncConfigUpdated, otherConfigsUpdated);
+ // Check the mcc mnc are updated as expected
+ assertTrue(Arrays.equals(mccMncConfigToUpdate, mccMncConfigUpdated));
+ // Check other configs are not changed
+ assertTrue(otherConfigsOriginal.equals(otherConfigsUpdated));
+ }
+
+ // Set mcc mnc configs back in the end of the test
+ ShellIdentityUtils.invokeMethodWithShellPermissions(mActivityManager,
+ (am) -> am.updateMccMncConfiguration(mccMncConfigOriginal[0],
+ mccMncConfigOriginal[1]));
+ }
+ */
+
+ /**
+ * Due to the corresponding API is hidden in R and will be public in S, this method
+ * for test "testUpdateMccMncConfiguration" is commented and will be un-commented in
+ * Android S.
+ *
+ private void getMccMncConfigsAndOthers(String[] mccMncConfigs, Set<String> otherConfigs)
+ throws Exception {
+ String[] configs = SystemUtil.runShellCommand(
+ mInstrumentation, SHELL_COMMAND_GET_CONFIG).split(" |\\-");
+ for (String config : configs) {
+ if (config.startsWith(SHELL_COMMAND_RESULT_CONFIG_NAME_MCC)) {
+ mccMncConfigs[0] = config.substring(
+ SHELL_COMMAND_RESULT_CONFIG_NAME_MCC.length());
+ } else if (config.startsWith(SHELL_COMMAND_RESULT_CONFIG_NAME_MNC)) {
+ mccMncConfigs[1] = config.substring(
+ SHELL_COMMAND_RESULT_CONFIG_NAME_MNC.length());
+ } else {
+ otherConfigs.add(config);
+ }
+ }
+ }
+ */
+
+ /**
* Simple test for {@link ActivityManager#isUserAMonkey()} - verifies its false.
*
* TODO: test positive case
@@ -737,7 +804,11 @@
ActivityReceiverFilter appStartedReceiver = new ActivityReceiverFilter(
ACTIVITY_LAUNCHED_ACTION);
+ boolean disabled = "0".equals(executeShellCommand("cmd deviceidle enabled light"));
try {
+ if (disabled) {
+ executeAndLogShellCommand("cmd deviceidle enable light");
+ }
intent = new Intent(Intent.ACTION_MAIN);
intent.setClassName(SIMPLE_PACKAGE_NAME, SIMPLE_PACKAGE_NAME + SIMPLE_ACTIVITY);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
@@ -810,6 +881,9 @@
toggleScreenOn(true);
appStartedReceiver.close();
+ if (disabled) {
+ executeAndLogShellCommand("cmd deviceidle disable light");
+ }
SystemUtil.runWithShellPermissionIdentity(() -> {
mActivityManager.forceStopPackage(SIMPLE_PACKAGE_NAME);
});
diff --git a/tests/app/src/android/app/cts/NotificationManagerTest.java b/tests/app/src/android/app/cts/NotificationManagerTest.java
index 73e02c2..4de36b9 100644
--- a/tests/app/src/android/app/cts/NotificationManagerTest.java
+++ b/tests/app/src/android/app/cts/NotificationManagerTest.java
@@ -117,6 +117,7 @@
import androidx.test.InstrumentationRegistry;
+import com.android.compatibility.common.util.FeatureUtil;
import com.android.compatibility.common.util.SystemUtil;
import junit.framework.Assert;
@@ -450,8 +451,21 @@
}
}
+ private void setUpNotifListener() {
+ try {
+ toggleListenerAccess(TestNotificationListener.getId(),
+ InstrumentationRegistry.getInstrumentation(), true);
+ mListener = TestNotificationListener.getInstance();
+ mListener.resetData();
+ assertNotNull(mListener);
+ } catch (IOException e) {
+ }
+ }
+
private void sendAndVerifyBubble(final int id, Notification.Builder builder,
Notification.BubbleMetadata data, boolean shouldBeBubble) {
+ setUpNotifListener();
+
final Intent intent = new Intent(mContext, BubbledActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP
@@ -478,50 +492,48 @@
Notification notif = builder.build();
mNotificationManager.notify(id, notif);
- if (!checkNotificationExistence(id, /*shouldExist=*/ true, shouldBeBubble)) {
- fail("couldn't find posted notification bubble with id=" + id);
- }
+ verifyNotificationBubbleState(id, shouldBeBubble);
}
- private StatusBarNotification getNotification(int id) {
- // notification is a bit asynchronous so it may take a few ms to appear in
- // getActiveNotifications()
- // we will check for it for up to 300ms before giving up
- for (int tries = 3; tries-- > 0;) {
- // Need reset flag.
- final StatusBarNotification[] sbns = mNotificationManager.getActiveNotifications();
- for (StatusBarNotification sbn : sbns) {
- if (sbn.getId() == id) {
- return sbn;
+ /**
+ * Make sure {@link #setUpNotifListener()} is called prior to sending the notif and verifying
+ * in this method.
+ */
+ private void verifyNotificationBubbleState(int id, boolean shouldBeBubble) {
+ try {
+ // FLAG_BUBBLE relies on notification being posted, wait for notification listener
+ Thread.sleep(500);
+ } catch (InterruptedException ex) {
+ }
+
+ for (StatusBarNotification sbn : mListener.mPosted) {
+ if (sbn.getId() == id) {
+ boolean isBubble = (sbn.getNotification().flags & FLAG_BUBBLE) != 0;
+ if (isBubble != shouldBeBubble) {
+ final String failure = shouldBeBubble
+ ? "Notification with id= " + id + " wasn't a bubble"
+ : "Notification with id= " + id + " was a bubble and shouldn't be";
+ fail(failure);
+ } else {
+ // pass
+ return;
}
}
- try {
- Thread.sleep(100);
- } catch (InterruptedException ex) {
- // pass
- }
}
- return null;
+ fail("Couldn't find posted notification with id= " + id);
}
private boolean checkNotificationExistence(int id, boolean shouldExist) {
- return checkNotificationExistence(id, shouldExist, false /* shouldBeBubble */);
- }
-
- private boolean checkNotificationExistence(int id, boolean shouldExist,
- boolean shouldBeBubble) {
// notification is a bit asynchronous so it may take a few ms to appear in
// getActiveNotifications()
// we will check for it for up to 300ms before giving up
boolean found = false;
- boolean isBubble = false;
for (int tries = 3; tries--> 0;) {
// Need reset flag.
found = false;
final StatusBarNotification[] sbns = mNotificationManager.getActiveNotifications();
for (StatusBarNotification sbn : sbns) {
- isBubble = (sbn.getNotification().flags & FLAG_BUBBLE) != 0;
- Log.d(TAG, "Found " + sbn.getKey() + " Bubble? " + isBubble);
+ Log.d(TAG, "Found " + sbn.getKey());
if (sbn.getId() == id) {
found = true;
break;
@@ -534,7 +546,7 @@
// pass
}
}
- return (found == shouldExist) && (isBubble == shouldBeBubble);
+ return found == shouldExist;
}
private void assertNotificationCount(int expectedCount) {
@@ -1371,7 +1383,8 @@
}
public void testCanBubble_ranking() throws Exception {
- if (mActivityManager.isLowRamDevice() && !mPackageManager.hasSystemFeature(FEATURE_WATCH)) {
+ if ((mActivityManager.isLowRamDevice() && !FeatureUtil.isWatch())
+ || FeatureUtil.isAutomotive()) {
return;
}
@@ -2769,8 +2782,12 @@
badNumberString);
}
- public void testNotificationManagerBubblePolicy_flagForMessage_failsNoRemoteInput()
+ public void testNotificationManagerBubblePolicy_flagForMessage_passesNoRemoteInput()
throws InterruptedException {
+ if (FeatureUtil.isAutomotive()) {
+ // Automotive does not support notification bubbles.
+ return;
+ }
// turn on bubbles globally
toggleBubbleSetting(true);
@@ -2787,11 +2804,17 @@
SystemClock.currentThreadTimeMillis(), person)
)
.setSmallIcon(android.R.drawable.sym_def_app_icon);
- sendAndVerifyBubble(1, nb, null /* use default metadata */, false);
+ boolean shouldBeBubble = !mActivityManager.isLowRamDevice();
+ sendAndVerifyBubble(1, nb, null /* use default metadata */, shouldBeBubble);
}
public void testNotificationManagerBubblePolicy_flagForMessage_succeeds()
throws InterruptedException {
+ if (FeatureUtil.isAutomotive()) {
+ // Automotive does not support notification bubbles.
+ return;
+ }
+
// turn on bubbles globally
toggleBubbleSetting(true);
@@ -2825,39 +2848,45 @@
public void testNotificationManagerBubblePolicy_flagForMessagingWithService_fails()
throws Exception {
+ if (FeatureUtil.isAutomotive()) {
+ // Automotive does not support notification bubbles.
+ return;
+ }
Intent serviceIntent = new Intent(mContext, BubblesTestService.class);
serviceIntent.putExtra(EXTRA_TEST_CASE, TEST_MESSAGING);
try {
// turn on bubbles globally
toggleBubbleSetting(true);
+
+ setUpNotifListener();
+
mContext.startService(serviceIntent);
- if (!checkNotificationExistence(BUBBLE_NOTIF_ID,
- true /* shouldExist */, false /* shouldBeBubble */)) {
- fail("found bubble notification id=" + BUBBLE_NOTIF_ID
- + " when it should just be a notification");
- }
+ verifyNotificationBubbleState(BUBBLE_NOTIF_ID, false /* shouldBeBubble */);
} finally {
mContext.stopService(serviceIntent);
}
}
public void testNotificationManagerBubblePolicy_flagForPhonecall() throws InterruptedException {
+ if (FeatureUtil.isAutomotive()) {
+ // Automotive does not support notification bubbles.
+ return;
+ }
Intent serviceIntent = new Intent(mContext, BubblesTestService.class);
serviceIntent.putExtra(EXTRA_TEST_CASE, TEST_SUCCESS);
try {
// turn on bubbles globally
toggleBubbleSetting(true);
+
+ setUpNotifListener();
+
mContext.startService(serviceIntent);
boolean shouldBeBubble = !mActivityManager.isLowRamDevice();
- if (!checkNotificationExistence(BUBBLE_NOTIF_ID,
- true /* shouldExist */, shouldBeBubble)) {
- fail("couldn't find posted notification bubble with id=" + BUBBLE_NOTIF_ID);
- }
-
+ verifyNotificationBubbleState(BUBBLE_NOTIF_ID, shouldBeBubble);
} finally {
mContext.stopService(serviceIntent);
}
@@ -2865,19 +2894,22 @@
public void testNotificationManagerBubblePolicy_flagForPhonecallFailsNoPerson()
throws InterruptedException {
+ if (FeatureUtil.isAutomotive()) {
+ // Automotive does not support notification bubbles.
+ return;
+ }
Intent serviceIntent = new Intent(mContext, BubblesTestService.class);
serviceIntent.putExtra(EXTRA_TEST_CASE, TEST_NO_PERSON);
try {
// turn on bubbles globally
toggleBubbleSetting(true);
+
+ setUpNotifListener();
+
mContext.startService(serviceIntent);
- if (!checkNotificationExistence(BUBBLE_NOTIF_ID,
- true /* shouldExist */, false /* shouldBeBubble */)) {
- fail("couldn't find posted notification with id=" + BUBBLE_NOTIF_ID
- + " or it was a bubble when it shouldn't be");
- }
+ verifyNotificationBubbleState(BUBBLE_NOTIF_ID, false /* shouldBeBubble */);
} finally {
mContext.stopService(serviceIntent);
}
@@ -2885,6 +2917,10 @@
public void testNotificationManagerBubblePolicy_flagForPhonecallFailsNoForeground()
throws InterruptedException {
+ if (FeatureUtil.isAutomotive()) {
+ // Automotive does not support notification bubbles.
+ return;
+ }
// turn on bubbles globally
toggleBubbleSetting(true);
@@ -2901,19 +2937,22 @@
public void testNotificationManagerBubblePolicy_flagForPhonecallFailsNoCategory()
throws InterruptedException {
+ if (FeatureUtil.isAutomotive()) {
+ // Automotive does not support notification bubbles.
+ return;
+ }
Intent serviceIntent = new Intent(mContext, BubblesTestService.class);
serviceIntent.putExtra(EXTRA_TEST_CASE, TEST_NO_CATEGORY);
try {
// turn on bubbles globally
toggleBubbleSetting(true);
+
+ setUpNotifListener();
+
mContext.startService(serviceIntent);
- if (!checkNotificationExistence(BUBBLE_NOTIF_ID,
- true /* shouldExist */, false /* shouldBeBubble */)) {
- fail("couldn't find posted notification with id=" + BUBBLE_NOTIF_ID
- + " or it was a bubble when it shouldn't be");
- }
+ verifyNotificationBubbleState(BUBBLE_NOTIF_ID, false /* shouldBeBubble */);
} finally {
mContext.stopService(serviceIntent);
}
@@ -2921,50 +2960,62 @@
public void testNotificationManagerBubblePolicy_flagForPhonecallFailsNoMetadata()
throws InterruptedException {
+ if (FeatureUtil.isAutomotive()) {
+ // Automotive does not support notification bubbles.
+ return;
+ }
Intent serviceIntent = new Intent(mContext, BubblesTestService.class);
serviceIntent.putExtra(EXTRA_TEST_CASE, TEST_NO_BUBBLE_METADATA);
try {
// turn on bubbles globally
toggleBubbleSetting(true);
+
+ setUpNotifListener();
+
mContext.startService(serviceIntent);
- if (!checkNotificationExistence(BUBBLE_NOTIF_ID,
- true /* shouldExist */, false /* shouldBeBubble */)) {
- fail("couldn't find posted notification with id=" + BUBBLE_NOTIF_ID
- + " or it was a bubble when it shouldn't be");
- }
+ verifyNotificationBubbleState(BUBBLE_NOTIF_ID, false /* shouldBeBubble */);
} finally {
mContext.stopService(serviceIntent);
}
}
public void testNotificationManagerBubblePolicy_flagForAppForeground_fails() throws Exception {
+ if (FeatureUtil.isAutomotive()) {
+ // Automotive does not support notification bubbles.
+ return;
+ }
try {
// turn on bubbles globally
toggleBubbleSetting(true);
+ setUpNotifListener();
+
// Start & get the activity
SendBubbleActivity a = startSendBubbleActivity();
// Send a bubble that doesn't fulfill policy from foreground
- a.sendInvalidBubble(4000, false /* autoExpand */);
+ a.sendInvalidBubble(false /* autoExpand */);
// Just because app is foreground, doesn't mean they get to bubble
- if (!checkNotificationExistence(BUBBLE_NOTIF_ID,
- true /* shouldExist */, false /* shouldBeBubble */)) {
- fail("couldn't find posted notification bubble with id=" + BUBBLE_NOTIF_ID);
- }
+ verifyNotificationBubbleState(BUBBLE_NOTIF_ID, false /* shouldBeBubble */);
} finally {
cleanupSendBubbleActivity();
}
}
public void testNotificationManagerBubble_ensureFlaggedDocumentLaunchMode() throws Exception {
+ if (FeatureUtil.isAutomotive()) {
+ // Automotive does not support notification bubbles.
+ return;
+ }
try {
// turn on bubbles globally
toggleBubbleSetting(true);
+ setUpNotifListener();
+
// make ourselves foreground so we can auto-expand the bubble & check the intent flags
SendBubbleActivity a = startSendBubbleActivity();
@@ -2979,10 +3030,7 @@
a.sendBubble(true /* autoExpand */, false /* suppressNotif */);
boolean shouldBeBubble = !mActivityManager.isLowRamDevice();
- if (!checkNotificationExistence(BUBBLE_NOTIF_ID,
- true /* shouldExist */, shouldBeBubble)) {
- fail("couldn't find posted notification bubble with id=" + BUBBLE_NOTIF_ID);
- }
+ verifyNotificationBubbleState(BUBBLE_NOTIF_ID, shouldBeBubble);
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
@@ -2996,6 +3044,10 @@
public void testNotificationManagerBubblePolicy_flagForShortcut_manifest_fails()
throws Exception {
+ if (FeatureUtil.isAutomotive()) {
+ // Automotive does not support notification bubbles.
+ return;
+ }
// turn on bubbles globally
toggleBubbleSetting(true);
@@ -3034,6 +3086,10 @@
public void testNotificationManagerBubblePolicy_flagForShortcut_dynamic_succeeds()
throws Exception {
+ if (FeatureUtil.isAutomotive()) {
+ // Automotive does not support notification bubbles.
+ return;
+ }
ShortcutManager scmanager = mContext.getSystemService(ShortcutManager.class);
@@ -3084,7 +3140,6 @@
boolean shouldBeBubble = !mActivityManager.isLowRamDevice();
sendAndVerifyBubble(1, nb, data, shouldBeBubble);
-
} finally {
// remove the shortcut
scmanager.removeAllDynamicShortcuts();
@@ -3093,6 +3148,10 @@
public void testNotificationManagerBubblePolicy_flagForShortcut_fails_invalidShortcut()
throws Exception {
+ if (FeatureUtil.isAutomotive()) {
+ // Automotive does not support notification bubbles.
+ return;
+ }
// turn on bubbles globally
toggleBubbleSetting(true);
@@ -3131,6 +3190,10 @@
public void testNotificationManagerBubblePolicy_flagForShortcut_fails_invalidNotif()
throws Exception {
+ if (FeatureUtil.isAutomotive()) {
+ // Automotive does not support notification bubbles.
+ return;
+ }
// turn on bubbles globally
toggleBubbleSetting(true);
@@ -3145,6 +3208,10 @@
public void testNotificationManagerBubblePolicy_noFlag_shortcutRemoved()
throws Exception {
+ if (FeatureUtil.isAutomotive()) {
+ // Automotive does not support notification bubbles.
+ return;
+ }
ShortcutManager scmanager = mContext.getSystemService(ShortcutManager.class);
@@ -3152,6 +3219,8 @@
// turn on bubbles globally
toggleBubbleSetting(true);
+ setUpNotifListener();
+
// Make dynamic shortcut
Intent shortcutIntent = new Intent(mContext, SendBubbleActivity.class);
shortcutIntent.setAction(Intent.ACTION_VIEW);
@@ -3196,12 +3265,13 @@
boolean shouldBeBubble = !mActivityManager.isLowRamDevice();
sendAndVerifyBubble(1, nb, data, shouldBeBubble);
+ mListener.resetData();
+
// Now lets delete the shortcut and make sure the notif has been updated to not
// be a bubble.
scmanager.removeAllDynamicShortcuts();
- checkNotificationExistence(1, true /* should exist */, false /* should be bubble */);
-
+ verifyNotificationBubbleState(1, false /* should be bubble */);
} finally {
// remove the shortcut
scmanager.removeAllDynamicShortcuts();
@@ -3209,18 +3279,26 @@
}
public void testNotificationManagerBubbleNotificationSuppression() throws Exception {
+ if (FeatureUtil.isAutomotive()) {
+ // Automotive does not support notification bubbles.
+ return;
+ }
try {
// turn on bubbles globally
toggleBubbleSetting(true);
+ setUpNotifListener();
+
// make ourselves foreground so we can specify suppress notification flag
SendBubbleActivity a = startSendBubbleActivity();
// send the bubble with notification suppressed
a.sendBubble(false /* autoExpand */, true /* suppressNotif */);
+ boolean shouldBeBubble = !mActivityManager.isLowRamDevice();
+ verifyNotificationBubbleState(BUBBLE_NOTIF_ID, shouldBeBubble);
// check for the notification
- StatusBarNotification sbnSuppressed = getNotification(BUBBLE_NOTIF_ID);
+ StatusBarNotification sbnSuppressed = mListener.mPosted.get(0);
assertNotNull(sbnSuppressed);
// check for suppression state
Notification.BubbleMetadata metadata =
@@ -3228,11 +3306,14 @@
assertNotNull(metadata);
assertTrue(metadata.isNotificationSuppressed());
+ mListener.resetData();
+
// send the bubble with notification NOT suppressed
a.sendBubble(false /* autoExpand */, false /* suppressNotif */);
+ verifyNotificationBubbleState(BUBBLE_NOTIF_ID, shouldBeBubble);
// check for the notification
- StatusBarNotification sbnNotSuppressed = getNotification(BUBBLE_NOTIF_ID);
+ StatusBarNotification sbnNotSuppressed = mListener.mPosted.get(0);
assertNotNull(sbnNotSuppressed);
// check for suppression state
metadata = sbnNotSuppressed.getNotification().getBubbleMetadata();
@@ -3243,6 +3324,8 @@
// turn off bubbles globally
toggleBubbleSetting(false);
+
+ mListener.resetData();
}
}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/CannedFillResponse.java b/tests/autofillservice/src/android/autofillservice/cts/CannedFillResponse.java
index cd099d7..aa751a2 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/CannedFillResponse.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/CannedFillResponse.java
@@ -596,7 +596,7 @@
final Dataset.Builder builder = mPresentation != null
? mInlinePresentation == null
? new Dataset.Builder(mPresentation)
- : new Dataset.Builder(mPresentation, mInlinePresentation)
+ : new Dataset.Builder(mPresentation).setInlinePresentation(mInlinePresentation)
: mInlinePresentation == null
? new Dataset.Builder()
: new Dataset.Builder(mInlinePresentation);
@@ -631,7 +631,7 @@
}
} else {
if (inlinePresentation != null) {
- builder.setInlinePresentation(autofillId, value,
+ builder.setFieldInlinePresentation(autofillId, value,
filter != null ? filter.second : null, inlinePresentation);
} else {
if (filter == null) {
diff --git a/tests/autofillservice/src/android/autofillservice/cts/DatasetTest.java b/tests/autofillservice/src/android/autofillservice/cts/DatasetTest.java
index c9434cb..43c8e06 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/DatasetTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/DatasetTest.java
@@ -58,22 +58,29 @@
@Test
public void testBuilder_nullPresentation() {
assertThrows(NullPointerException.class, () -> new Dataset.Builder((RemoteViews) null));
- assertThrows(NullPointerException.class, () -> new Dataset.Builder(null,
- mInlinePresentation));
}
@Test
public void testBuilder_nullInlinePresentation() {
assertThrows(NullPointerException.class,
() -> new Dataset.Builder((InlinePresentation) null));
- assertThrows(NullPointerException.class, () -> new Dataset.Builder(mPresentation, null));
}
@Test
public void testBuilder_validPresentations() {
assertThat(new Dataset.Builder(mPresentation)).isNotNull();
assertThat(new Dataset.Builder(mInlinePresentation)).isNotNull();
- assertThat(new Dataset.Builder(mPresentation, mInlinePresentation)).isNotNull();
+ }
+
+ @Test
+ public void testBuilder_setNullInlinePresentation() {
+ final Dataset.Builder builder = new Dataset.Builder(mPresentation);
+ assertThrows(NullPointerException.class, () -> builder.setInlinePresentation(null));
+ }
+
+ @Test
+ public void testBuilder_setInlinePresentation() {
+ assertThat(new Dataset.Builder().setInlinePresentation(mInlinePresentation)).isNotNull();
}
@Test
@@ -163,8 +170,8 @@
}
@Test
- public void testBuilder_setInlinePresentations() {
- assertThat(new Dataset.Builder().setInlinePresentation(mId, mValue, mFilter,
+ public void testBuilder_setFieldInlinePresentations() {
+ assertThat(new Dataset.Builder().setFieldInlinePresentation(mId, mValue, mFilter,
mInlinePresentation)).isNotNull();
}
@@ -180,6 +187,8 @@
builder.setValue(mId, mValue, mPresentation);
assertThat(builder.build()).isNotNull();
assertThrows(IllegalStateException.class, () -> builder.build());
+ assertThrows(IllegalStateException.class,
+ () -> builder.setInlinePresentation(mInlinePresentation));
assertThrows(IllegalStateException.class, () -> builder.setValue(mId, mValue));
assertThrows(IllegalStateException.class,
() -> builder.setValue(mId, mValue, mPresentation));
@@ -192,6 +201,7 @@
assertThrows(IllegalStateException.class,
() -> builder.setValue(mId, mValue, mFilter, mPresentation, mInlinePresentation));
assertThrows(IllegalStateException.class,
- () -> builder.setInlinePresentation(mId, mValue, mFilter, mInlinePresentation));
+ () -> builder.setFieldInlinePresentation(mId, mValue, mFilter,
+ mInlinePresentation));
}
}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/augmented/CannedAugmentedFillResponse.java b/tests/autofillservice/src/android/autofillservice/cts/augmented/CannedAugmentedFillResponse.java
index 580816d..5a312ef 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/augmented/CannedAugmentedFillResponse.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/augmented/CannedAugmentedFillResponse.java
@@ -177,7 +177,7 @@
new android.service.autofill.Dataset.Builder();
for (Pair<AutofillId, AutofillValue> pair : dataset.getValues()) {
final AutofillId id = pair.first;
- datasetBuilder.setInlinePresentation(id, pair.second, null,
+ datasetBuilder.setFieldInlinePresentation(id, pair.second, null,
dataset.mFieldPresentationById.get(id));
}
list.add(datasetBuilder.build());
diff --git a/tests/autofillservice/src/android/autofillservice/cts/inline/InlineFilteringTest.java b/tests/autofillservice/src/android/autofillservice/cts/inline/InlineFilteringTest.java
index 1e47dd0..67d7a35 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/inline/InlineFilteringTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/inline/InlineFilteringTest.java
@@ -99,6 +99,9 @@
mUiBot.assertSuggestionStrip(1);
mUiBot.selectSuggestion(0);
+ // TODO(b/151702075): Find a better way to wait for the views to update.
+ Thread.sleep(/* millis= */ 1000);
+ mUiBot.waitForIdle();
mActivity.assertAutoFilled();
}
}
diff --git a/tests/camera/src/android/hardware/camera2/cts/ConcurrentCameraTest.java b/tests/camera/src/android/hardware/camera2/cts/ConcurrentCameraTest.java
index 05118b1..ebff2dd 100644
--- a/tests/camera/src/android/hardware/camera2/cts/ConcurrentCameraTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/ConcurrentCameraTest.java
@@ -186,7 +186,7 @@
/**
* Generates a list of combinations used for mandatory stream combination testing.
* Each combination(GeneratedEntry) corresponds to a camera id advertised by
- * getConcurrentStreamingCameraIds().
+ * getConcurrentCameraIds().
*/
private List<HashMap<String, GeneratedEntry>> generateStreamSelections(
Set<String> cameraIdCombination) {
diff --git a/tests/camera/src/android/hardware/camera2/cts/PerformanceTest.java b/tests/camera/src/android/hardware/camera2/cts/PerformanceTest.java
index af254b1..4a02036 100644
--- a/tests/camera/src/android/hardware/camera2/cts/PerformanceTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/PerformanceTest.java
@@ -285,16 +285,18 @@
*/
@Test
public void testSingleCapture() throws Exception {
- int[] YUV_FORMAT = {ImageFormat.YUV_420_888};
- testSingleCaptureForFormat(YUV_FORMAT, null, /*addPreviewDelay*/ false);
- int[] PRIVATE_FORMAT = {ImageFormat.PRIVATE};
- testSingleCaptureForFormat(PRIVATE_FORMAT, "private", /*addPreviewDelay*/ true);
int[] JPEG_FORMAT = {ImageFormat.JPEG};
testSingleCaptureForFormat(JPEG_FORMAT, "jpeg", /*addPreviewDelay*/ true);
- int[] RAW_FORMAT = {ImageFormat.RAW_SENSOR};
- testSingleCaptureForFormat(RAW_FORMAT, "raw", /*addPreviewDelay*/ true);
- int[] RAW_JPEG_FORMATS = {ImageFormat.RAW_SENSOR, ImageFormat.JPEG};
- testSingleCaptureForFormat(RAW_JPEG_FORMATS, "raw_jpeg", /*addPreviewDelay*/ true);
+ if (!mTestRule.isPerfMeasure()) {
+ int[] YUV_FORMAT = {ImageFormat.YUV_420_888};
+ testSingleCaptureForFormat(YUV_FORMAT, null, /*addPreviewDelay*/ false);
+ int[] PRIVATE_FORMAT = {ImageFormat.PRIVATE};
+ testSingleCaptureForFormat(PRIVATE_FORMAT, "private", /*addPreviewDelay*/ true);
+ int[] RAW_FORMAT = {ImageFormat.RAW_SENSOR};
+ testSingleCaptureForFormat(RAW_FORMAT, "raw", /*addPreviewDelay*/ true);
+ int[] RAW_JPEG_FORMATS = {ImageFormat.RAW_SENSOR, ImageFormat.JPEG};
+ testSingleCaptureForFormat(RAW_JPEG_FORMATS, "raw_jpeg", /*addPreviewDelay*/ true);
+ }
}
private String appendFormatDescription(String message, String formatDescription) {
@@ -1551,4 +1553,4 @@
}
}
-}
\ No newline at end of file
+}
diff --git a/tests/camera/src/android/hardware/camera2/cts/RecordingTest.java b/tests/camera/src/android/hardware/camera2/cts/RecordingTest.java
index 30d1943..067104c 100644
--- a/tests/camera/src/android/hardware/camera2/cts/RecordingTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/RecordingTest.java
@@ -1168,8 +1168,13 @@
", num of frames produced: " + resultListener.getTotalNumFrames());
}
- // Validation.
- validateRecording(videoSz, durationMs, frameDurationMs, FRMDRP_RATE_TOLERANCE);
+ if (isPerfMeasure()) {
+ // Only measure the largest video recording size when measuring perf
+ break;
+ } else {
+ // Validation.
+ validateRecording(videoSz, durationMs, frameDurationMs, FRMDRP_RATE_TOLERANCE);
+ }
}
if (maxVideoFrameRate != -1) {
// At least one CamcorderProfile is present, check FPS
diff --git a/tests/camera/src/android/hardware/camera2/cts/testcases/Camera2AndroidTestRule.java b/tests/camera/src/android/hardware/camera2/cts/testcases/Camera2AndroidTestRule.java
index 13ce89a..f5dedba 100644
--- a/tests/camera/src/android/hardware/camera2/cts/testcases/Camera2AndroidTestRule.java
+++ b/tests/camera/src/android/hardware/camera2/cts/testcases/Camera2AndroidTestRule.java
@@ -91,8 +91,10 @@
private Context mContext;
private static final String CAMERA_ID_INSTR_ARG_KEY = "camera-id";
+ private static final String CAMERA_PERF_MEASURE = "perf-measure";
private static final Bundle mBundle = InstrumentationRegistry.getArguments();
private static final String mOverrideCameraId = mBundle.getString(CAMERA_ID_INSTR_ARG_KEY);
+ private static final String mPerfMeasure = mBundle.getString(CAMERA_PERF_MEASURE);
public Camera2AndroidTestRule(Context context) {
mContext = context;
@@ -182,6 +184,10 @@
return mCollector;
}
+ public boolean isPerfMeasure() {
+ return mPerfMeasure != null && mPerfMeasure.equals("on");
+ }
+
private String[] deriveCameraIdsUnderTest() throws Exception {
String[] idsUnderTest = mCameraManager.getCameraIdListNoLazy();
assertNotNull("Camera ids shouldn't be null", idsUnderTest);
diff --git a/tests/camera/src/android/hardware/camera2/cts/testcases/Camera2ConcurrentAndroidTestCase.java b/tests/camera/src/android/hardware/camera2/cts/testcases/Camera2ConcurrentAndroidTestCase.java
index 8877343..c35e8d5 100644
--- a/tests/camera/src/android/hardware/camera2/cts/testcases/Camera2ConcurrentAndroidTestCase.java
+++ b/tests/camera/src/android/hardware/camera2/cts/testcases/Camera2ConcurrentAndroidTestCase.java
@@ -124,7 +124,7 @@
}
}
mConcurrentCameraIdCombinations =
- CameraTestUtils.getConcurrentStreamingCameraIds(mCameraManager, mAdoptShellPerm);
+ CameraTestUtils.getConcurrentCameraIds(mCameraManager, mAdoptShellPerm);
assertNotNull("Unable to get concurrent camera combinations",
mConcurrentCameraIdCombinations);
mCameraTestInfos = new HashMap<String, CameraTestInfo>();
diff --git a/tests/camera/utils/src/android/hardware/camera2/cts/CameraTestUtils.java b/tests/camera/utils/src/android/hardware/camera2/cts/CameraTestUtils.java
index 4edd936..f64ff08 100644
--- a/tests/camera/utils/src/android/hardware/camera2/cts/CameraTestUtils.java
+++ b/tests/camera/utils/src/android/hardware/camera2/cts/CameraTestUtils.java
@@ -849,11 +849,11 @@
return idsForTesting.toArray(new String[idsForTesting.size()]);
}
- public static Set<Set<String>> getConcurrentStreamingCameraIds(CameraManager manager,
+ public static Set<Set<String>> getConcurrentCameraIds(CameraManager manager,
boolean getSystemCameras)
throws CameraAccessException {
Set<String> cameraIds = new HashSet<String>(Arrays.asList(getCameraIdListForTesting(manager, getSystemCameras)));
- Set<Set<String>> combinations = manager.getConcurrentStreamingCameraIds();
+ Set<Set<String>> combinations = manager.getConcurrentCameraIds();
Set<Set<String>> correctComb = new HashSet<Set<String>>();
for (Set<String> comb : combinations) {
Set<String> filteredIds = new HashSet<String>();
diff --git a/tests/camera/utils/src/android/hardware/cts/helpers/CameraParameterizedTestCase.java b/tests/camera/utils/src/android/hardware/cts/helpers/CameraParameterizedTestCase.java
index 047fba5..6a78d60 100644
--- a/tests/camera/utils/src/android/hardware/cts/helpers/CameraParameterizedTestCase.java
+++ b/tests/camera/utils/src/android/hardware/cts/helpers/CameraParameterizedTestCase.java
@@ -44,13 +44,22 @@
public boolean mAdoptShellPerm;
private static final String CAMERA_ID_INSTR_ARG_KEY = "camera-id";
+ private static final String CAMERA_PERF_MEASURE = "perf-measure";
private static final Bundle mBundle = InstrumentationRegistry.getArguments();
protected static final String mOverrideCameraId = mBundle.getString(CAMERA_ID_INSTR_ARG_KEY);
+ protected static final String mPerfMeasure = mBundle.getString(CAMERA_PERF_MEASURE);
+
+ public boolean isPerfMeasure() {
+ return mPerfMeasure != null && mPerfMeasure.equals("on");
+ }
@Parameters
public static Iterable<? extends Object> data() {
List<Boolean> adoptShellPerm = new ArrayList<Boolean>();
- adoptShellPerm.add(true);
+ // Only add adoptShellPerm(true) of camera id is not overridden.
+ if (mPerfMeasure == null || !mPerfMeasure.equals("on")) {
+ adoptShellPerm.add(true);
+ }
adoptShellPerm.add(false);
return adoptShellPerm;
}
diff --git a/tests/framework/base/windowmanager/app/AndroidManifest.xml b/tests/framework/base/windowmanager/app/AndroidManifest.xml
index b135615..67cae55 100755
--- a/tests/framework/base/windowmanager/app/AndroidManifest.xml
+++ b/tests/framework/base/windowmanager/app/AndroidManifest.xml
@@ -162,6 +162,16 @@
android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout"
android:exported="true"
/>
+ <activity android:name=".PipActivityWithMinimalSize"
+ android:resizeableActivity="false"
+ android:supportsPictureInPicture="true"
+ android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout"
+ android:exported="true"
+ android:taskAffinity="nobody.but.PipActivity">
+ <layout android:minWidth="100dp"
+ android:minHeight="80dp"
+ />
+ </activity>
<activity android:name=".FreeformActivity"
android:resizeableActivity="true"
android:taskAffinity="nobody.but.FreeformActivity"
diff --git a/tests/framework/base/windowmanager/app/src/android/server/wm/app/Components.java b/tests/framework/base/windowmanager/app/src/android/server/wm/app/Components.java
index f2be9c7..b5e8de2 100644
--- a/tests/framework/base/windowmanager/app/src/android/server/wm/app/Components.java
+++ b/tests/framework/base/windowmanager/app/src/android/server/wm/app/Components.java
@@ -77,6 +77,8 @@
public static final ComponentName PRESENTATION_ACTIVITY = component("PresentationActivity");
public static final ComponentName PIP_ACTIVITY = component("PipActivity");
public static final ComponentName PIP_ACTIVITY2 = component("PipActivity2");
+ public static final ComponentName PIP_ACTIVITY_WITH_MINIMAL_SIZE = component(
+ "PipActivityWithMinimalSize");
public static final ComponentName PIP_ACTIVITY_WITH_SAME_AFFINITY =
component("PipActivityWithSameAffinity");
public static final ComponentName PIP_ON_STOP_ACTIVITY = component("PipOnStopActivity");
diff --git a/apps/CtsVerifier/jni/audio_loopback/audio_utils/roundup.h b/tests/framework/base/windowmanager/app/src/android/server/wm/app/PipActivityWithMinimalSize.java
similarity index 61%
copy from apps/CtsVerifier/jni/audio_loopback/audio_utils/roundup.h
copy to tests/framework/base/windowmanager/app/src/android/server/wm/app/PipActivityWithMinimalSize.java
index ad34289..8c573c0 100644
--- a/apps/CtsVerifier/jni/audio_loopback/audio_utils/roundup.h
+++ b/tests/framework/base/windowmanager/app/src/android/server/wm/app/PipActivityWithMinimalSize.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -11,21 +11,14 @@
* 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.
+ * limitations under the License
*/
-#ifndef ANDROID_AUDIO_ROUNDUP_H
-#define ANDROID_AUDIO_ROUNDUP_H
+package android.server.wm.app;
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// Round up to the next highest power of 2
-unsigned roundup(unsigned v);
-
-#ifdef __cplusplus
+/**
+ * An activity that has the same behavior as {@link PipActivity} and specifies
+ * minimal dimension in its manifest.
+ */
+public class PipActivityWithMinimalSize extends PipActivity {
}
-#endif
-
-#endif // ANDROID_AUDIO_ROUNDUP_H
diff --git a/tests/framework/base/windowmanager/app/src/android/server/wm/app/RenderService.java b/tests/framework/base/windowmanager/app/src/android/server/wm/app/RenderService.java
index e1de5cd..58da2d4 100644
--- a/tests/framework/base/windowmanager/app/src/android/server/wm/app/RenderService.java
+++ b/tests/framework/base/windowmanager/app/src/android/server/wm/app/RenderService.java
@@ -76,7 +76,7 @@
WindowManager.LayoutParams lp = new WindowManager.LayoutParams(metrics.widthPixels,
metrics.heightPixels, TYPE_APPLICATION, 0,
PixelFormat.OPAQUE);
- surfaceControlViewHost.addView(embeddedView, lp);
+ surfaceControlViewHost.setView(embeddedView, lp);
return surfaceControlViewHost;
}
diff --git a/tests/framework/base/windowmanager/intent_tests/clearCases/clear-task_with_new-task.json b/tests/framework/base/windowmanager/intent_tests/clearCases/clear-task_with_new-task.json
index 09753b8..18bcd6f81 100644
--- a/tests/framework/base/windowmanager/intent_tests/clearCases/clear-task_with_new-task.json
+++ b/tests/framework/base/windowmanager/intent_tests/clearCases/clear-task_with_new-task.json
@@ -18,37 +18,27 @@
]
},
"initialState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity"
+ ]
}
]
},
"endState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity"
+ ]
}
]
}
-}
+}
\ No newline at end of file
diff --git a/tests/framework/base/windowmanager/intent_tests/clearCases/clear-task_without_new-task.json b/tests/framework/base/windowmanager/intent_tests/clearCases/clear-task_without_new-task.json
index da82d52..cd89b22 100644
--- a/tests/framework/base/windowmanager/intent_tests/clearCases/clear-task_without_new-task.json
+++ b/tests/framework/base/windowmanager/intent_tests/clearCases/clear-task_without_new-task.json
@@ -18,41 +18,31 @@
]
},
"initialState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity"
+ ]
}
]
},
"endState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "RESUMED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "RESUMED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "STOPPED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity"
+ ]
}
]
}
-}
+}
\ No newline at end of file
diff --git a/tests/framework/base/windowmanager/intent_tests/clearCases/test-1.json b/tests/framework/base/windowmanager/intent_tests/clearCases/test-1.json
index 0ee6cc8..8e477ed 100644
--- a/tests/framework/base/windowmanager/intent_tests/clearCases/test-1.json
+++ b/tests/framework/base/windowmanager/intent_tests/clearCases/test-1.json
@@ -18,37 +18,27 @@
]
},
"initialState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity"
+ ]
}
]
},
"endState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity"
+ ]
}
]
}
-}
+}
\ No newline at end of file
diff --git a/tests/framework/base/windowmanager/intent_tests/clearCases/test-2.json b/tests/framework/base/windowmanager/intent_tests/clearCases/test-2.json
index 35fadcc..15f0db4 100644
--- a/tests/framework/base/windowmanager/intent_tests/clearCases/test-2.json
+++ b/tests/framework/base/windowmanager/intent_tests/clearCases/test-2.json
@@ -24,45 +24,35 @@
]
},
"initialState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "RESUMED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "RESUMED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "STOPPED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity"
+ ]
}
]
},
"endState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "RESUMED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "RESUMED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "STOPPED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity"
+ ]
}
]
}
-}
+}
\ No newline at end of file
diff --git a/tests/framework/base/windowmanager/intent_tests/clearCases/test-3.json b/tests/framework/base/windowmanager/intent_tests/clearCases/test-3.json
index 42f1ffa..304dce9 100644
--- a/tests/framework/base/windowmanager/intent_tests/clearCases/test-3.json
+++ b/tests/framework/base/windowmanager/intent_tests/clearCases/test-3.json
@@ -24,45 +24,35 @@
]
},
"initialState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "RESUMED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "RESUMED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "STOPPED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity"
+ ]
}
]
},
"endState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "RESUMED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "RESUMED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "STOPPED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity"
+ ]
}
]
}
-}
+}
\ No newline at end of file
diff --git a/tests/framework/base/windowmanager/intent_tests/clearCases/test-4.json b/tests/framework/base/windowmanager/intent_tests/clearCases/test-4.json
index 5b52541..e73fc19 100644
--- a/tests/framework/base/windowmanager/intent_tests/clearCases/test-4.json
+++ b/tests/framework/base/windowmanager/intent_tests/clearCases/test-4.json
@@ -24,45 +24,35 @@
]
},
"initialState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "RESUMED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "RESUMED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "STOPPED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity"
+ ]
}
]
},
"endState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "RESUMED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "RESUMED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "STOPPED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity"
+ ]
}
]
}
-}
+}
\ No newline at end of file
diff --git a/tests/framework/base/windowmanager/intent_tests/clearCases/test-5.json b/tests/framework/base/windowmanager/intent_tests/clearCases/test-5.json
index 2f1def6..67fba8ac2 100644
--- a/tests/framework/base/windowmanager/intent_tests/clearCases/test-5.json
+++ b/tests/framework/base/windowmanager/intent_tests/clearCases/test-5.json
@@ -24,45 +24,35 @@
]
},
"initialState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "RESUMED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "RESUMED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "STOPPED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity"
+ ]
}
]
},
"endState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "RESUMED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "RESUMED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "STOPPED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity"
+ ]
}
]
}
-}
+}
\ No newline at end of file
diff --git a/tests/framework/base/windowmanager/intent_tests/clearCases/test-6.json b/tests/framework/base/windowmanager/intent_tests/clearCases/test-6.json
index dce5119..1a1471e 100644
--- a/tests/framework/base/windowmanager/intent_tests/clearCases/test-6.json
+++ b/tests/framework/base/windowmanager/intent_tests/clearCases/test-6.json
@@ -30,49 +30,39 @@
]
},
"initialState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "RESUMED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity",
- "state": "STOPPED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "RESUMED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1Activity",
+ "state": "STOPPED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "STOPPED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity"
+ ]
}
]
},
"endState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity",
- "state": "RESUMED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1Activity",
+ "state": "RESUMED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "STOPPED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity"
+ ]
}
]
}
-}
+}
\ No newline at end of file
diff --git a/tests/framework/base/windowmanager/intent_tests/forResult/test-1.json b/tests/framework/base/windowmanager/intent_tests/forResult/test-1.json
index f901ad1..b26456b 100644
--- a/tests/framework/base/windowmanager/intent_tests/forResult/test-1.json
+++ b/tests/framework/base/windowmanager/intent_tests/forResult/test-1.json
@@ -18,37 +18,27 @@
]
},
"initialState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity"
+ ]
}
]
},
"endState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity"
+ ]
}
]
}
-}
+}
\ No newline at end of file
diff --git a/tests/framework/base/windowmanager/intent_tests/forResult/test-2.json b/tests/framework/base/windowmanager/intent_tests/forResult/test-2.json
index 6e97377..c8bcea6 100644
--- a/tests/framework/base/windowmanager/intent_tests/forResult/test-2.json
+++ b/tests/framework/base/windowmanager/intent_tests/forResult/test-2.json
@@ -18,41 +18,31 @@
]
},
"initialState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity"
+ ]
}
]
},
"endState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "RESUMED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "RESUMED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "STOPPED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity"
+ ]
}
]
}
-}
+}
\ No newline at end of file
diff --git a/tests/framework/base/windowmanager/intent_tests/forResult/test-3.json b/tests/framework/base/windowmanager/intent_tests/forResult/test-3.json
index da3478d..7c2d5e9 100644
--- a/tests/framework/base/windowmanager/intent_tests/forResult/test-3.json
+++ b/tests/framework/base/windowmanager/intent_tests/forResult/test-3.json
@@ -18,37 +18,27 @@
]
},
"initialState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$SingleTopActivity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$SingleTopActivity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$SingleTopActivity"
+ ]
}
]
},
"endState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$SingleTopActivity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$SingleTopActivity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$SingleTopActivity"
+ ]
}
]
}
-}
+}
\ No newline at end of file
diff --git a/tests/framework/base/windowmanager/intent_tests/forResult/test-4.json b/tests/framework/base/windowmanager/intent_tests/forResult/test-4.json
index 2ed6023..487e287 100644
--- a/tests/framework/base/windowmanager/intent_tests/forResult/test-4.json
+++ b/tests/framework/base/windowmanager/intent_tests/forResult/test-4.json
@@ -18,41 +18,31 @@
]
},
"initialState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$SingleTopActivity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$SingleTopActivity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$SingleTopActivity"
+ ]
}
]
},
"endState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$SingleTopActivity",
- "state": "RESUMED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$SingleTopActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$SingleTopActivity",
+ "state": "RESUMED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$SingleTopActivity",
+ "state": "STOPPED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$SingleTopActivity"
+ ]
}
]
}
-}
+}
\ No newline at end of file
diff --git a/tests/framework/base/windowmanager/intent_tests/forResult/test-5.json b/tests/framework/base/windowmanager/intent_tests/forResult/test-5.json
index 0ee6cc8..8e477ed 100644
--- a/tests/framework/base/windowmanager/intent_tests/forResult/test-5.json
+++ b/tests/framework/base/windowmanager/intent_tests/forResult/test-5.json
@@ -18,37 +18,27 @@
]
},
"initialState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity"
+ ]
}
]
},
"endState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity"
+ ]
}
]
}
-}
+}
\ No newline at end of file
diff --git a/tests/framework/base/windowmanager/intent_tests/forResult/test-6.json b/tests/framework/base/windowmanager/intent_tests/forResult/test-6.json
index dca9dd2..dc2f620 100644
--- a/tests/framework/base/windowmanager/intent_tests/forResult/test-6.json
+++ b/tests/framework/base/windowmanager/intent_tests/forResult/test-6.json
@@ -18,37 +18,27 @@
]
},
"initialState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity"
+ ]
}
]
},
"endState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity"
+ ]
}
]
}
-}
+}
\ No newline at end of file
diff --git a/tests/framework/base/windowmanager/intent_tests/forResult/test-7.json b/tests/framework/base/windowmanager/intent_tests/forResult/test-7.json
index 4599e0f..95c2d0b 100644
--- a/tests/framework/base/windowmanager/intent_tests/forResult/test-7.json
+++ b/tests/framework/base/windowmanager/intent_tests/forResult/test-7.json
@@ -18,49 +18,35 @@
]
},
"initialState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity"
+ ]
}
]
},
"endState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity"
+ ]
},
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "STOPPED"
}
]
}
]
}
-}
+}
\ No newline at end of file
diff --git a/tests/framework/base/windowmanager/intent_tests/forResult/test-8.json b/tests/framework/base/windowmanager/intent_tests/forResult/test-8.json
index 22608c7..032558a 100644
--- a/tests/framework/base/windowmanager/intent_tests/forResult/test-8.json
+++ b/tests/framework/base/windowmanager/intent_tests/forResult/test-8.json
@@ -24,45 +24,35 @@
]
},
"initialState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity",
- "state": "RESUMED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1Activity",
+ "state": "RESUMED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "STOPPED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity"
+ ]
}
]
},
"endState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "RESUMED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "RESUMED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1Activity",
+ "state": "STOPPED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity"
+ ]
}
]
}
-}
+}
\ No newline at end of file
diff --git a/tests/framework/base/windowmanager/intent_tests/forResult/test-9.json b/tests/framework/base/windowmanager/intent_tests/forResult/test-9.json
index 3f2a71a..588a98d 100644
--- a/tests/framework/base/windowmanager/intent_tests/forResult/test-9.json
+++ b/tests/framework/base/windowmanager/intent_tests/forResult/test-9.json
@@ -24,45 +24,35 @@
]
},
"initialState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity",
- "state": "RESUMED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1Activity",
+ "state": "RESUMED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "STOPPED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity"
+ ]
}
]
},
"endState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "RESUMED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "RESUMED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1Activity",
+ "state": "STOPPED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity"
+ ]
}
]
}
-}
+}
\ No newline at end of file
diff --git a/tests/framework/base/windowmanager/intent_tests/newDocumentCases/test-1.json b/tests/framework/base/windowmanager/intent_tests/newDocumentCases/test-1.json
index e4accd3..c0c9af0 100644
--- a/tests/framework/base/windowmanager/intent_tests/newDocumentCases/test-1.json
+++ b/tests/framework/base/windowmanager/intent_tests/newDocumentCases/test-1.json
@@ -18,49 +18,35 @@
]
},
"initialState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity"
+ ]
}
]
},
"endState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$SingleInstanceActivity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$SingleInstanceActivity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$SingleInstanceActivity"
+ ]
},
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "STOPPED"
}
]
}
]
}
-}
+}
\ No newline at end of file
diff --git a/tests/framework/base/windowmanager/intent_tests/newDocumentCases/test-10.json b/tests/framework/base/windowmanager/intent_tests/newDocumentCases/test-10.json
index 0b5a0f5..1f9c91c 100644
--- a/tests/framework/base/windowmanager/intent_tests/newDocumentCases/test-10.json
+++ b/tests/framework/base/windowmanager/intent_tests/newDocumentCases/test-10.json
@@ -18,49 +18,35 @@
]
},
"initialState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity"
+ ]
}
]
},
"endState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity"
+ ]
},
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "STOPPED"
}
]
}
]
}
-}
+}
\ No newline at end of file
diff --git a/tests/framework/base/windowmanager/intent_tests/newDocumentCases/test-11.json b/tests/framework/base/windowmanager/intent_tests/newDocumentCases/test-11.json
index 3b782b0..64cc2c9 100644
--- a/tests/framework/base/windowmanager/intent_tests/newDocumentCases/test-11.json
+++ b/tests/framework/base/windowmanager/intent_tests/newDocumentCases/test-11.json
@@ -18,37 +18,27 @@
]
},
"initialState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$SingleInstanceActivity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$SingleInstanceActivity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$SingleInstanceActivity"
+ ]
}
]
},
"endState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$SingleInstanceActivity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$SingleInstanceActivity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$SingleInstanceActivity"
+ ]
}
]
}
-}
+}
\ No newline at end of file
diff --git a/tests/framework/base/windowmanager/intent_tests/newDocumentCases/test-12.json b/tests/framework/base/windowmanager/intent_tests/newDocumentCases/test-12.json
index 63f9948..ca2bb0f 100644
--- a/tests/framework/base/windowmanager/intent_tests/newDocumentCases/test-12.json
+++ b/tests/framework/base/windowmanager/intent_tests/newDocumentCases/test-12.json
@@ -18,37 +18,27 @@
]
},
"initialState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$SingleTaskActivity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$SingleTaskActivity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$SingleTaskActivity"
+ ]
}
]
},
"endState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$SingleTaskActivity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$SingleTaskActivity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$SingleTaskActivity"
+ ]
}
]
}
-}
+}
\ No newline at end of file
diff --git a/tests/framework/base/windowmanager/intent_tests/newDocumentCases/test-2.json b/tests/framework/base/windowmanager/intent_tests/newDocumentCases/test-2.json
index baa3996d..cb74d21 100644
--- a/tests/framework/base/windowmanager/intent_tests/newDocumentCases/test-2.json
+++ b/tests/framework/base/windowmanager/intent_tests/newDocumentCases/test-2.json
@@ -18,49 +18,35 @@
]
},
"initialState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity"
+ ]
}
]
},
"endState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$SingleInstanceActivity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$SingleInstanceActivity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$SingleInstanceActivity"
+ ]
},
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "STOPPED"
}
]
}
]
}
-}
+}
\ No newline at end of file
diff --git a/tests/framework/base/windowmanager/intent_tests/newDocumentCases/test-3.json b/tests/framework/base/windowmanager/intent_tests/newDocumentCases/test-3.json
index 53d01b1..fe88fad 100644
--- a/tests/framework/base/windowmanager/intent_tests/newDocumentCases/test-3.json
+++ b/tests/framework/base/windowmanager/intent_tests/newDocumentCases/test-3.json
@@ -18,41 +18,31 @@
]
},
"initialState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity"
+ ]
}
]
},
"endState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity",
- "state": "RESUMED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1Activity",
+ "state": "RESUMED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "STOPPED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity"
+ ]
}
]
}
-}
+}
\ No newline at end of file
diff --git a/tests/framework/base/windowmanager/intent_tests/newDocumentCases/test-4.json b/tests/framework/base/windowmanager/intent_tests/newDocumentCases/test-4.json
index 697703b..810f44d 100644
--- a/tests/framework/base/windowmanager/intent_tests/newDocumentCases/test-4.json
+++ b/tests/framework/base/windowmanager/intent_tests/newDocumentCases/test-4.json
@@ -18,49 +18,35 @@
]
},
"initialState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity"
+ ]
}
]
},
"endState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1Activity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity"
+ ]
},
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "STOPPED"
}
]
}
]
}
-}
+}
\ No newline at end of file
diff --git a/tests/framework/base/windowmanager/intent_tests/newDocumentCases/test-5.json b/tests/framework/base/windowmanager/intent_tests/newDocumentCases/test-5.json
index 2050021..8316f2d 100644
--- a/tests/framework/base/windowmanager/intent_tests/newDocumentCases/test-5.json
+++ b/tests/framework/base/windowmanager/intent_tests/newDocumentCases/test-5.json
@@ -18,37 +18,27 @@
]
},
"initialState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity"
+ ]
}
]
},
"endState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity"
+ ]
}
]
}
-}
+}
\ No newline at end of file
diff --git a/tests/framework/base/windowmanager/intent_tests/newDocumentCases/test-6.json b/tests/framework/base/windowmanager/intent_tests/newDocumentCases/test-6.json
index 07e05bc..2957f18 100644
--- a/tests/framework/base/windowmanager/intent_tests/newDocumentCases/test-6.json
+++ b/tests/framework/base/windowmanager/intent_tests/newDocumentCases/test-6.json
@@ -18,49 +18,35 @@
]
},
"initialState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity"
+ ]
}
]
},
"endState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$SingleTopActivity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$SingleTopActivity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$SingleTopActivity"
+ ]
},
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "STOPPED"
}
]
}
]
}
-}
+}
\ No newline at end of file
diff --git a/tests/framework/base/windowmanager/intent_tests/newDocumentCases/test-7.json b/tests/framework/base/windowmanager/intent_tests/newDocumentCases/test-7.json
index b6354b5..dab125d 100644
--- a/tests/framework/base/windowmanager/intent_tests/newDocumentCases/test-7.json
+++ b/tests/framework/base/windowmanager/intent_tests/newDocumentCases/test-7.json
@@ -30,69 +30,51 @@
]
},
"initialState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1Activity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity"
+ ]
},
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "STOPPED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "STOPPED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1Activity",
+ "state": "STOPPED"
}
]
}
]
},
"endState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1Activity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity"
+ ]
},
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "STOPPED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "STOPPED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1Activity",
+ "state": "STOPPED"
}
]
}
]
}
-}
+}
\ No newline at end of file
diff --git a/tests/framework/base/windowmanager/intent_tests/newDocumentCases/test-8.json b/tests/framework/base/windowmanager/intent_tests/newDocumentCases/test-8.json
index c8ef9f8..67f9f6f 100644
--- a/tests/framework/base/windowmanager/intent_tests/newDocumentCases/test-8.json
+++ b/tests/framework/base/windowmanager/intent_tests/newDocumentCases/test-8.json
@@ -36,69 +36,51 @@
]
},
"initialState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity",
- "state": "RESUMED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1Activity",
+ "state": "RESUMED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "STOPPED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity"
+ ]
},
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "STOPPED"
}
]
}
]
},
"endState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity",
- "state": "RESUMED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1Activity",
+ "state": "RESUMED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "STOPPED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity"
+ ]
},
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "STOPPED"
}
]
}
]
}
-}
+}
\ No newline at end of file
diff --git a/tests/framework/base/windowmanager/intent_tests/newDocumentCases/test-9.json b/tests/framework/base/windowmanager/intent_tests/newDocumentCases/test-9.json
index 296475f..cd1973a 100644
--- a/tests/framework/base/windowmanager/intent_tests/newDocumentCases/test-9.json
+++ b/tests/framework/base/windowmanager/intent_tests/newDocumentCases/test-9.json
@@ -36,81 +36,59 @@
]
},
"initialState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity",
- "state": "RESUMED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1Activity",
+ "state": "RESUMED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "STOPPED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity"
+ ]
},
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "STOPPED"
}
]
}
]
},
"endState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity2",
- "state": "RESUMED"
- }
- ]
- }
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity2"
- },
- {
- "tasks": [
- {
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity",
- "state": "STOPPED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1Activity2",
+ "state": "RESUMED"
}
]
},
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1Activity",
+ "state": "STOPPED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "STOPPED"
+ }
+ ]
+ },
+ {
+ "activities": [
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "STOPPED"
}
]
}
]
}
-}
+}
\ No newline at end of file
diff --git a/tests/framework/base/windowmanager/intent_tests/newTask/request_new_task_different_affinity-new_task.json b/tests/framework/base/windowmanager/intent_tests/newTask/request_new_task_different_affinity-new_task.json
index 9d878d8..99b4046 100644
--- a/tests/framework/base/windowmanager/intent_tests/newTask/request_new_task_different_affinity-new_task.json
+++ b/tests/framework/base/windowmanager/intent_tests/newTask/request_new_task_different_affinity-new_task.json
@@ -18,49 +18,35 @@
]
},
"initialState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1Activity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity"
+ ]
}
]
},
"endState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity"
+ ]
},
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1Activity",
+ "state": "STOPPED"
}
]
}
]
}
-}
+}
\ No newline at end of file
diff --git a/tests/framework/base/windowmanager/intent_tests/newTask/request_new_task_same_affinity-same_task.json b/tests/framework/base/windowmanager/intent_tests/newTask/request_new_task_same_affinity-same_task.json
index 6944973..3635017 100644
--- a/tests/framework/base/windowmanager/intent_tests/newTask/request_new_task_same_affinity-same_task.json
+++ b/tests/framework/base/windowmanager/intent_tests/newTask/request_new_task_same_affinity-same_task.json
@@ -18,41 +18,31 @@
]
},
"initialState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1Activity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity"
+ ]
}
]
},
"endState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity2",
- "state": "RESUMED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1Activity2",
+ "state": "RESUMED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1Activity",
+ "state": "STOPPED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity2"
+ ]
}
]
}
-}
+}
\ No newline at end of file
diff --git a/tests/framework/base/windowmanager/intent_tests/newTask/request_same_task_different_affinity-same_task.json b/tests/framework/base/windowmanager/intent_tests/newTask/request_same_task_different_affinity-same_task.json
index a444299..52470c0 100644
--- a/tests/framework/base/windowmanager/intent_tests/newTask/request_same_task_different_affinity-same_task.json
+++ b/tests/framework/base/windowmanager/intent_tests/newTask/request_same_task_different_affinity-same_task.json
@@ -18,41 +18,31 @@
]
},
"initialState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1Activity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity"
+ ]
}
]
},
"endState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "RESUMED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "RESUMED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1Activity",
+ "state": "STOPPED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity"
+ ]
}
]
}
-}
+}
\ No newline at end of file
diff --git a/tests/framework/base/windowmanager/intent_tests/newTask/test-1.json b/tests/framework/base/windowmanager/intent_tests/newTask/test-1.json
index e4accd3..c0c9af0 100644
--- a/tests/framework/base/windowmanager/intent_tests/newTask/test-1.json
+++ b/tests/framework/base/windowmanager/intent_tests/newTask/test-1.json
@@ -18,49 +18,35 @@
]
},
"initialState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity"
+ ]
}
]
},
"endState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$SingleInstanceActivity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$SingleInstanceActivity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$SingleInstanceActivity"
+ ]
},
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "STOPPED"
}
]
}
]
}
-}
+}
\ No newline at end of file
diff --git a/tests/framework/base/windowmanager/intent_tests/newTask/test-10.json b/tests/framework/base/windowmanager/intent_tests/newTask/test-10.json
index 55c049a..06e5363 100644
--- a/tests/framework/base/windowmanager/intent_tests/newTask/test-10.json
+++ b/tests/framework/base/windowmanager/intent_tests/newTask/test-10.json
@@ -18,49 +18,35 @@
]
},
"initialState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity"
+ ]
}
]
},
"endState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity"
+ ]
},
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "STOPPED"
}
]
}
]
}
-}
+}
\ No newline at end of file
diff --git a/tests/framework/base/windowmanager/intent_tests/newTask/test-11.json b/tests/framework/base/windowmanager/intent_tests/newTask/test-11.json
index 7e3ab21..6e93afb 100644
--- a/tests/framework/base/windowmanager/intent_tests/newTask/test-11.json
+++ b/tests/framework/base/windowmanager/intent_tests/newTask/test-11.json
@@ -18,37 +18,27 @@
]
},
"initialState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$SingleInstanceActivity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$SingleInstanceActivity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$SingleInstanceActivity"
+ ]
}
]
},
"endState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$SingleInstanceActivity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$SingleInstanceActivity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$SingleInstanceActivity"
+ ]
}
]
}
-}
+}
\ No newline at end of file
diff --git a/tests/framework/base/windowmanager/intent_tests/newTask/test-12.json b/tests/framework/base/windowmanager/intent_tests/newTask/test-12.json
index 563683f..769a9b8 100644
--- a/tests/framework/base/windowmanager/intent_tests/newTask/test-12.json
+++ b/tests/framework/base/windowmanager/intent_tests/newTask/test-12.json
@@ -18,37 +18,27 @@
]
},
"initialState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$SingleTaskActivity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$SingleTaskActivity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$SingleTaskActivity"
+ ]
}
]
},
"endState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$SingleTaskActivity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$SingleTaskActivity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$SingleTaskActivity"
+ ]
}
]
}
-}
+}
\ No newline at end of file
diff --git a/tests/framework/base/windowmanager/intent_tests/newTask/test-13.json b/tests/framework/base/windowmanager/intent_tests/newTask/test-13.json
index 0d6fc3d..4f4f738 100644
--- a/tests/framework/base/windowmanager/intent_tests/newTask/test-13.json
+++ b/tests/framework/base/windowmanager/intent_tests/newTask/test-13.json
@@ -18,49 +18,35 @@
]
},
"initialState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$SingleInstanceActivity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$SingleInstanceActivity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$SingleInstanceActivity"
+ ]
}
]
},
"endState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity"
+ ]
},
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$SingleInstanceActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$SingleInstanceActivity",
+ "state": "STOPPED"
}
]
}
]
}
-}
+}
\ No newline at end of file
diff --git a/tests/framework/base/windowmanager/intent_tests/newTask/test-14.json b/tests/framework/base/windowmanager/intent_tests/newTask/test-14.json
index b430952..4f3c581 100644
--- a/tests/framework/base/windowmanager/intent_tests/newTask/test-14.json
+++ b/tests/framework/base/windowmanager/intent_tests/newTask/test-14.json
@@ -18,41 +18,31 @@
]
},
"initialState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$SingleTaskActivity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$SingleTaskActivity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$SingleTaskActivity"
+ ]
}
]
},
"endState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "RESUMED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$SingleTaskActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "RESUMED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$SingleTaskActivity",
+ "state": "STOPPED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity"
+ ]
}
]
}
-}
+}
\ No newline at end of file
diff --git a/tests/framework/base/windowmanager/intent_tests/newTask/test-15.json b/tests/framework/base/windowmanager/intent_tests/newTask/test-15.json
index 33419d6..b0f1b08 100644
--- a/tests/framework/base/windowmanager/intent_tests/newTask/test-15.json
+++ b/tests/framework/base/windowmanager/intent_tests/newTask/test-15.json
@@ -18,41 +18,31 @@
]
},
"initialState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$SingleInstanceActivity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$SingleInstanceActivity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$SingleInstanceActivity"
+ ]
}
]
},
"endState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "RESUMED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$SingleInstanceActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "RESUMED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$SingleInstanceActivity",
+ "state": "STOPPED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity"
+ ]
}
]
}
-}
+}
\ No newline at end of file
diff --git a/tests/framework/base/windowmanager/intent_tests/newTask/test-16.json b/tests/framework/base/windowmanager/intent_tests/newTask/test-16.json
index d6eac92..d579057 100644
--- a/tests/framework/base/windowmanager/intent_tests/newTask/test-16.json
+++ b/tests/framework/base/windowmanager/intent_tests/newTask/test-16.json
@@ -24,61 +24,43 @@
]
},
"initialState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$SingleInstanceActivity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$SingleInstanceActivity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$SingleInstanceActivity"
+ ]
},
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "STOPPED"
}
]
}
]
},
"endState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity"
+ ]
},
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$SingleInstanceActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$SingleInstanceActivity",
+ "state": "STOPPED"
}
]
}
]
}
-}
+}
\ No newline at end of file
diff --git a/tests/framework/base/windowmanager/intent_tests/newTask/test-2.json b/tests/framework/base/windowmanager/intent_tests/newTask/test-2.json
index b9acd47..8441735 100644
--- a/tests/framework/base/windowmanager/intent_tests/newTask/test-2.json
+++ b/tests/framework/base/windowmanager/intent_tests/newTask/test-2.json
@@ -18,49 +18,35 @@
]
},
"initialState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity"
+ ]
}
]
},
"endState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$SingleInstanceActivity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$SingleInstanceActivity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$SingleInstanceActivity"
+ ]
},
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "STOPPED"
}
]
}
]
}
-}
+}
\ No newline at end of file
diff --git a/tests/framework/base/windowmanager/intent_tests/newTask/test-3.json b/tests/framework/base/windowmanager/intent_tests/newTask/test-3.json
index 53d01b1..fe88fad 100644
--- a/tests/framework/base/windowmanager/intent_tests/newTask/test-3.json
+++ b/tests/framework/base/windowmanager/intent_tests/newTask/test-3.json
@@ -18,41 +18,31 @@
]
},
"initialState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity"
+ ]
}
]
},
"endState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity",
- "state": "RESUMED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1Activity",
+ "state": "RESUMED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "STOPPED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity"
+ ]
}
]
}
-}
+}
\ No newline at end of file
diff --git a/tests/framework/base/windowmanager/intent_tests/newTask/test-4.json b/tests/framework/base/windowmanager/intent_tests/newTask/test-4.json
index a394a58..6168dac 100644
--- a/tests/framework/base/windowmanager/intent_tests/newTask/test-4.json
+++ b/tests/framework/base/windowmanager/intent_tests/newTask/test-4.json
@@ -18,49 +18,35 @@
]
},
"initialState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity"
+ ]
}
]
},
"endState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1Activity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity"
+ ]
},
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "STOPPED"
}
]
}
]
}
-}
+}
\ No newline at end of file
diff --git a/tests/framework/base/windowmanager/intent_tests/newTask/test-5.json b/tests/framework/base/windowmanager/intent_tests/newTask/test-5.json
index 38d86eb..1769784 100644
--- a/tests/framework/base/windowmanager/intent_tests/newTask/test-5.json
+++ b/tests/framework/base/windowmanager/intent_tests/newTask/test-5.json
@@ -18,37 +18,27 @@
]
},
"initialState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity"
+ ]
}
]
},
"endState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity"
+ ]
}
]
}
-}
+}
\ No newline at end of file
diff --git a/tests/framework/base/windowmanager/intent_tests/newTask/test-6.json b/tests/framework/base/windowmanager/intent_tests/newTask/test-6.json
index e279673..94104ee 100644
--- a/tests/framework/base/windowmanager/intent_tests/newTask/test-6.json
+++ b/tests/framework/base/windowmanager/intent_tests/newTask/test-6.json
@@ -18,41 +18,31 @@
]
},
"initialState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity"
+ ]
}
]
},
"endState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$SingleTopActivity",
- "state": "RESUMED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$SingleTopActivity",
+ "state": "RESUMED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "STOPPED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$SingleTopActivity"
+ ]
}
]
}
-}
+}
\ No newline at end of file
diff --git a/tests/framework/base/windowmanager/intent_tests/newTask/test-7.json b/tests/framework/base/windowmanager/intent_tests/newTask/test-7.json
index a7a8232..7209c12 100644
--- a/tests/framework/base/windowmanager/intent_tests/newTask/test-7.json
+++ b/tests/framework/base/windowmanager/intent_tests/newTask/test-7.json
@@ -30,69 +30,51 @@
]
},
"initialState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1Activity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity"
+ ]
},
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "STOPPED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "STOPPED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1Activity",
+ "state": "STOPPED"
}
]
}
]
},
"endState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1Activity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity"
+ ]
},
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "STOPPED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "STOPPED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1Activity",
+ "state": "STOPPED"
}
]
}
]
}
-}
+}
\ No newline at end of file
diff --git a/tests/framework/base/windowmanager/intent_tests/newTask/test-8.json b/tests/framework/base/windowmanager/intent_tests/newTask/test-8.json
index bf57d0c..91f8229 100644
--- a/tests/framework/base/windowmanager/intent_tests/newTask/test-8.json
+++ b/tests/framework/base/windowmanager/intent_tests/newTask/test-8.json
@@ -36,69 +36,51 @@
]
},
"initialState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity",
- "state": "RESUMED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1Activity",
+ "state": "RESUMED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "STOPPED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity"
+ ]
},
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "STOPPED"
}
]
}
]
},
"endState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity",
- "state": "RESUMED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1Activity",
+ "state": "RESUMED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "STOPPED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity"
+ ]
},
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "STOPPED"
}
]
}
]
}
-}
+}
\ No newline at end of file
diff --git a/tests/framework/base/windowmanager/intent_tests/newTask/test-9.json b/tests/framework/base/windowmanager/intent_tests/newTask/test-9.json
index 5c1bd4e..a257933 100644
--- a/tests/framework/base/windowmanager/intent_tests/newTask/test-9.json
+++ b/tests/framework/base/windowmanager/intent_tests/newTask/test-9.json
@@ -36,73 +36,55 @@
]
},
"initialState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity",
- "state": "RESUMED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1Activity",
+ "state": "RESUMED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "STOPPED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity"
+ ]
},
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "STOPPED"
}
]
}
]
},
"endState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity2",
- "state": "RESUMED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity",
- "state": "STOPPED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1Activity2",
+ "state": "RESUMED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1Activity",
+ "state": "STOPPED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "STOPPED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity2"
+ ]
},
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "STOPPED"
}
]
}
]
}
-}
+}
\ No newline at end of file
diff --git a/tests/framework/base/windowmanager/intent_tests/relinquishTaskIdentity/keep_affinity-request_new_task_with_same_affinity-same_task.json b/tests/framework/base/windowmanager/intent_tests/relinquishTaskIdentity/keep_affinity-request_new_task_with_same_affinity-same_task.json
index 3dd2c99..924e7e2 100644
--- a/tests/framework/base/windowmanager/intent_tests/relinquishTaskIdentity/keep_affinity-request_new_task_with_same_affinity-same_task.json
+++ b/tests/framework/base/windowmanager/intent_tests/relinquishTaskIdentity/keep_affinity-request_new_task_with_same_affinity-same_task.json
@@ -24,49 +24,39 @@
]
},
"initialState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity",
- "state": "RESUMED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1RelinquishTaskIdentityActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1Activity",
+ "state": "RESUMED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1RelinquishTaskIdentityActivity",
+ "state": "STOPPED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity"
+ ]
}
]
},
"endState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity2",
- "state": "RESUMED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity",
- "state": "STOPPED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1RelinquishTaskIdentityActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1Activity2",
+ "state": "RESUMED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1Activity",
+ "state": "STOPPED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1RelinquishTaskIdentityActivity",
+ "state": "STOPPED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity2"
+ ]
}
]
}
-}
+}
\ No newline at end of file
diff --git a/tests/framework/base/windowmanager/intent_tests/relinquishTaskIdentity/request_change_affinity-request_new_task_with_changed_affinity-new_task.json b/tests/framework/base/windowmanager/intent_tests/relinquishTaskIdentity/request_change_affinity-request_new_task_with_changed_affinity-new_task.json
index 53f01b5..3b8ecb2 100644
--- a/tests/framework/base/windowmanager/intent_tests/relinquishTaskIdentity/request_change_affinity-request_new_task_with_changed_affinity-new_task.json
+++ b/tests/framework/base/windowmanager/intent_tests/relinquishTaskIdentity/request_change_affinity-request_new_task_with_changed_affinity-new_task.json
@@ -25,57 +25,43 @@
]
},
"initialState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity",
- "state": "RESUMED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RelinquishTaskIdentityActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1Activity",
+ "state": "RESUMED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RelinquishTaskIdentityActivity",
+ "state": "STOPPED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity"
+ ]
}
]
},
"endState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity2",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1Activity2",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity2"
+ ]
},
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity",
- "state": "STOPPED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RelinquishTaskIdentityActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1Activity",
+ "state": "STOPPED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RelinquishTaskIdentityActivity",
+ "state": "STOPPED"
}
]
}
]
}
-}
+}
\ No newline at end of file
diff --git a/tests/framework/base/windowmanager/intent_tests/relinquishTaskIdentity/request_change_affinity-request_new_task_with_old_affinity-same_task.json b/tests/framework/base/windowmanager/intent_tests/relinquishTaskIdentity/request_change_affinity-request_new_task_with_old_affinity-same_task.json
index 2ec6f78..f8ec310b 100644
--- a/tests/framework/base/windowmanager/intent_tests/relinquishTaskIdentity/request_change_affinity-request_new_task_with_old_affinity-same_task.json
+++ b/tests/framework/base/windowmanager/intent_tests/relinquishTaskIdentity/request_change_affinity-request_new_task_with_old_affinity-same_task.json
@@ -25,49 +25,39 @@
]
},
"initialState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity",
- "state": "RESUMED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RelinquishTaskIdentityActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1Activity",
+ "state": "RESUMED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RelinquishTaskIdentityActivity",
+ "state": "STOPPED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity"
+ ]
}
]
},
"endState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "RESUMED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity",
- "state": "STOPPED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RelinquishTaskIdentityActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "RESUMED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1Activity",
+ "state": "STOPPED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RelinquishTaskIdentityActivity",
+ "state": "STOPPED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity"
+ ]
}
]
}
-}
+}
\ No newline at end of file
diff --git a/tests/framework/base/windowmanager/intent_tests/relinquishTaskIdentity/request_change_affinity-request_same_task_with_changed_affinity-same_task.json b/tests/framework/base/windowmanager/intent_tests/relinquishTaskIdentity/request_change_affinity-request_same_task_with_changed_affinity-same_task.json
index 7e31db4..fe0c8b1 100644
--- a/tests/framework/base/windowmanager/intent_tests/relinquishTaskIdentity/request_change_affinity-request_same_task_with_changed_affinity-same_task.json
+++ b/tests/framework/base/windowmanager/intent_tests/relinquishTaskIdentity/request_change_affinity-request_same_task_with_changed_affinity-same_task.json
@@ -25,49 +25,39 @@
]
},
"initialState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity",
- "state": "RESUMED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RelinquishTaskIdentityActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1Activity",
+ "state": "RESUMED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RelinquishTaskIdentityActivity",
+ "state": "STOPPED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity"
+ ]
}
]
},
"endState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity2",
- "state": "RESUMED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity",
- "state": "STOPPED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RelinquishTaskIdentityActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1Activity2",
+ "state": "RESUMED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1Activity",
+ "state": "STOPPED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RelinquishTaskIdentityActivity",
+ "state": "STOPPED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity2"
+ ]
}
]
}
-}
+}
\ No newline at end of file
diff --git a/tests/framework/base/windowmanager/intent_tests/relinquishTaskIdentity/request_change_affinity-request_same_task_with_old_affinity-same_task.json b/tests/framework/base/windowmanager/intent_tests/relinquishTaskIdentity/request_change_affinity-request_same_task_with_old_affinity-same_task.json
index afd155a..0d6d344 100644
--- a/tests/framework/base/windowmanager/intent_tests/relinquishTaskIdentity/request_change_affinity-request_same_task_with_old_affinity-same_task.json
+++ b/tests/framework/base/windowmanager/intent_tests/relinquishTaskIdentity/request_change_affinity-request_same_task_with_old_affinity-same_task.json
@@ -25,49 +25,39 @@
]
},
"initialState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity",
- "state": "RESUMED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RelinquishTaskIdentityActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1Activity",
+ "state": "RESUMED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RelinquishTaskIdentityActivity",
+ "state": "STOPPED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity"
+ ]
}
]
},
"endState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "RESUMED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity",
- "state": "STOPPED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RelinquishTaskIdentityActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "RESUMED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1Activity",
+ "state": "STOPPED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RelinquishTaskIdentityActivity",
+ "state": "STOPPED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity"
+ ]
}
]
}
-}
+}
\ No newline at end of file
diff --git a/tests/framework/base/windowmanager/intent_tests/relinquishTaskIdentity/request_new_task_with_different_affinity-new_task.json b/tests/framework/base/windowmanager/intent_tests/relinquishTaskIdentity/request_new_task_with_different_affinity-new_task.json
index cd6a3a4..e1905d9 100644
--- a/tests/framework/base/windowmanager/intent_tests/relinquishTaskIdentity/request_new_task_with_different_affinity-new_task.json
+++ b/tests/framework/base/windowmanager/intent_tests/relinquishTaskIdentity/request_new_task_with_different_affinity-new_task.json
@@ -18,49 +18,35 @@
]
},
"initialState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1RelinquishTaskIdentityActivity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1RelinquishTaskIdentityActivity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1RelinquishTaskIdentityActivity"
+ ]
}
]
},
"endState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity"
+ ]
},
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1RelinquishTaskIdentityActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1RelinquishTaskIdentityActivity",
+ "state": "STOPPED"
}
]
}
]
}
-}
+}
\ No newline at end of file
diff --git a/tests/framework/base/windowmanager/intent_tests/relinquishTaskIdentity/request_new_task_with_same_affinity-same_task.json b/tests/framework/base/windowmanager/intent_tests/relinquishTaskIdentity/request_new_task_with_same_affinity-same_task.json
index 999ee82..78ac855 100644
--- a/tests/framework/base/windowmanager/intent_tests/relinquishTaskIdentity/request_new_task_with_same_affinity-same_task.json
+++ b/tests/framework/base/windowmanager/intent_tests/relinquishTaskIdentity/request_new_task_with_same_affinity-same_task.json
@@ -18,41 +18,31 @@
]
},
"initialState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1RelinquishTaskIdentityActivity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1RelinquishTaskIdentityActivity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1RelinquishTaskIdentityActivity"
+ ]
}
]
},
"endState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity",
- "state": "RESUMED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1RelinquishTaskIdentityActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1Activity",
+ "state": "RESUMED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1RelinquishTaskIdentityActivity",
+ "state": "STOPPED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity"
+ ]
}
]
}
-}
+}
\ No newline at end of file
diff --git a/tests/framework/base/windowmanager/intent_tests/relinquishTaskIdentity/request_same_task_with_different_affinity-same_task.json b/tests/framework/base/windowmanager/intent_tests/relinquishTaskIdentity/request_same_task_with_different_affinity-same_task.json
index d0ec60c..ed2dfe2 100644
--- a/tests/framework/base/windowmanager/intent_tests/relinquishTaskIdentity/request_same_task_with_different_affinity-same_task.json
+++ b/tests/framework/base/windowmanager/intent_tests/relinquishTaskIdentity/request_same_task_with_different_affinity-same_task.json
@@ -18,41 +18,31 @@
]
},
"initialState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1RelinquishTaskIdentityActivity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1RelinquishTaskIdentityActivity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1RelinquishTaskIdentityActivity"
+ ]
}
]
},
"endState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "RESUMED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1RelinquishTaskIdentityActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "RESUMED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1RelinquishTaskIdentityActivity",
+ "state": "STOPPED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity"
+ ]
}
]
}
-}
+}
\ No newline at end of file
diff --git a/tests/framework/base/windowmanager/intent_tests/reorderToFront/reorder-to-front.json b/tests/framework/base/windowmanager/intent_tests/reorderToFront/reorder-to-front.json
index 9daaa0f..5e3de96 100644
--- a/tests/framework/base/windowmanager/intent_tests/reorderToFront/reorder-to-front.json
+++ b/tests/framework/base/windowmanager/intent_tests/reorderToFront/reorder-to-front.json
@@ -36,61 +36,51 @@
]
},
"initialState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "RESUMED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity2Activity",
- "state": "STOPPED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity",
- "state": "STOPPED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "RESUMED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity2Activity",
+ "state": "STOPPED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1Activity",
+ "state": "STOPPED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "STOPPED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity"
+ ]
}
]
},
"endState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity",
- "state": "RESUMED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "STOPPED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity2Activity",
- "state": "STOPPED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1Activity",
+ "state": "RESUMED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "STOPPED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity2Activity",
+ "state": "STOPPED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "STOPPED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity"
+ ]
}
]
}
-}
+}
\ No newline at end of file
diff --git a/tests/framework/base/windowmanager/intent_tests/reorderToFront/reorder-to-front_with_new-task_on_different_affinity.json b/tests/framework/base/windowmanager/intent_tests/reorderToFront/reorder-to-front_with_new-task_on_different_affinity.json
index ab9ae9b..c783577 100644
--- a/tests/framework/base/windowmanager/intent_tests/reorderToFront/reorder-to-front_with_new-task_on_different_affinity.json
+++ b/tests/framework/base/windowmanager/intent_tests/reorderToFront/reorder-to-front_with_new-task_on_different_affinity.json
@@ -31,65 +31,51 @@
]
},
"initialState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity2Activity",
- "state": "RESUMED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity",
- "state": "STOPPED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity2Activity",
+ "state": "RESUMED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1Activity",
+ "state": "STOPPED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "STOPPED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity2Activity"
+ ]
}
]
},
"endState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1Activity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity"
+ ]
},
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity2Activity",
- "state": "STOPPED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity",
- "state": "STOPPED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity2Activity",
+ "state": "STOPPED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1Activity",
+ "state": "STOPPED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "STOPPED"
}
]
}
]
}
-}
+}
\ No newline at end of file
diff --git a/tests/framework/base/windowmanager/intent_tests/resetTaskIfNeeded/reset-task.json b/tests/framework/base/windowmanager/intent_tests/resetTaskIfNeeded/reset-task.json
index 5d5aae5..d306d86 100644
--- a/tests/framework/base/windowmanager/intent_tests/resetTaskIfNeeded/reset-task.json
+++ b/tests/framework/base/windowmanager/intent_tests/resetTaskIfNeeded/reset-task.json
@@ -18,41 +18,31 @@
]
},
"initialState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity"
+ ]
}
]
},
"endState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$NoHistoryActivity",
- "state": "RESUMED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$NoHistoryActivity",
+ "state": "RESUMED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "STOPPED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$NoHistoryActivity"
+ ]
}
]
}
-}
+}
\ No newline at end of file
diff --git a/tests/framework/base/windowmanager/intent_tests/resetTaskIfNeeded/reset-task_reparent_affinity_in.json b/tests/framework/base/windowmanager/intent_tests/resetTaskIfNeeded/reset-task_reparent_affinity_in.json
index a4d1b7f..691d002 100644
--- a/tests/framework/base/windowmanager/intent_tests/resetTaskIfNeeded/reset-task_reparent_affinity_in.json
+++ b/tests/framework/base/windowmanager/intent_tests/resetTaskIfNeeded/reset-task_reparent_affinity_in.json
@@ -24,57 +24,43 @@
]
},
"initialState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity",
- "state": "RESUMED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1Activity",
+ "state": "RESUMED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "STOPPED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity"
+ ]
}
]
},
"endState": {
- "stacks": [
- {
- "tasks": [
+ "tasks": [
+ {
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity",
- "state": "RESUMED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity2",
- "state": "INITIALIZING"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1Activity",
+ "state": "RESUMED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1Activity2",
+ "state": "INITIALIZING"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity"
+ ]
},
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "STOPPED"
}
]
}
- ]
+ ]
}
-}
+}
\ No newline at end of file
diff --git a/tests/framework/base/windowmanager/intent_tests/resetTaskIfNeeded/reset-task_reparent_affinity_in_and_out.json b/tests/framework/base/windowmanager/intent_tests/resetTaskIfNeeded/reset-task_reparent_affinity_in_and_out.json
index 86e0f65..a709c0d 100644
--- a/tests/framework/base/windowmanager/intent_tests/resetTaskIfNeeded/reset-task_reparent_affinity_in_and_out.json
+++ b/tests/framework/base/windowmanager/intent_tests/resetTaskIfNeeded/reset-task_reparent_affinity_in_and_out.json
@@ -36,85 +36,63 @@
]
},
"initialState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity2",
- "state": "RESUMED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1Activity2",
+ "state": "RESUMED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "STOPPED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity2"
+ ]
},
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity2Activity",
- "state": "STOPPED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity2Activity",
+ "state": "STOPPED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1Activity",
+ "state": "STOPPED"
}
]
}
]
},
"endState": {
- "stacks": [
- {
- "tasks": [
- {
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity2",
- "state": "RESUMED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity",
- "state": "STOPPED"
- }
- ]
- }
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity2"
- },
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1Activity2",
+ "state": "RESUMED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1Activity",
+ "state": "STOPPED"
}
]
},
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity2Activity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "STOPPED"
+ }
+ ]
+ },
+ {
+ "activities": [
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity2Activity",
+ "state": "STOPPED"
}
]
}
- ]
+ ]
}
-}
+}
\ No newline at end of file
diff --git a/tests/framework/base/windowmanager/intent_tests/resetTaskIfNeeded/reset-task_with_new-task.json b/tests/framework/base/windowmanager/intent_tests/resetTaskIfNeeded/reset-task_with_new-task.json
index c059027..21ea454 100644
--- a/tests/framework/base/windowmanager/intent_tests/resetTaskIfNeeded/reset-task_with_new-task.json
+++ b/tests/framework/base/windowmanager/intent_tests/resetTaskIfNeeded/reset-task_with_new-task.json
@@ -18,37 +18,27 @@
]
},
"initialState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity"
+ ]
}
]
},
"endState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity"
+ ]
}
]
}
-}
+}
\ No newline at end of file
diff --git a/tests/framework/base/windowmanager/intent_tests/resetTaskIfNeeded/reset-task_with_new-task_new_document.json b/tests/framework/base/windowmanager/intent_tests/resetTaskIfNeeded/reset-task_with_new-task_new_document.json
index 27931ba..a5d5e5e 100644
--- a/tests/framework/base/windowmanager/intent_tests/resetTaskIfNeeded/reset-task_with_new-task_new_document.json
+++ b/tests/framework/base/windowmanager/intent_tests/resetTaskIfNeeded/reset-task_with_new-task_new_document.json
@@ -18,49 +18,35 @@
]
},
"initialState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity"
+ ]
}
]
},
"endState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$NoHistoryActivity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$NoHistoryActivity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$NoHistoryActivity"
+ ]
},
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "STOPPED"
}
]
}
]
}
-}
+}
\ No newline at end of file
diff --git a/tests/framework/base/windowmanager/intent_tests/resetTaskIfNeeded/test-1.json b/tests/framework/base/windowmanager/intent_tests/resetTaskIfNeeded/test-1.json
index 2cf1652..418ea7f 100644
--- a/tests/framework/base/windowmanager/intent_tests/resetTaskIfNeeded/test-1.json
+++ b/tests/framework/base/windowmanager/intent_tests/resetTaskIfNeeded/test-1.json
@@ -24,53 +24,39 @@
]
},
"initialState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity",
- "state": "RESUMED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1Activity",
+ "state": "RESUMED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "STOPPED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity"
+ ]
}
]
},
"endState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity"
+ ]
},
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1Activity",
+ "state": "STOPPED"
}
]
}
]
}
-}
+}
\ No newline at end of file
diff --git a/tests/framework/base/windowmanager/intent_tests/resetTaskIfNeeded/test-2.json b/tests/framework/base/windowmanager/intent_tests/resetTaskIfNeeded/test-2.json
index fc3634c..333cfbc 100644
--- a/tests/framework/base/windowmanager/intent_tests/resetTaskIfNeeded/test-2.json
+++ b/tests/framework/base/windowmanager/intent_tests/resetTaskIfNeeded/test-2.json
@@ -24,45 +24,35 @@
]
},
"initialState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity",
- "state": "RESUMED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1Activity",
+ "state": "RESUMED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "STOPPED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity"
+ ]
}
]
},
"endState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity",
- "state": "RESUMED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1Activity",
+ "state": "RESUMED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "STOPPED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity"
+ ]
}
]
}
-}
+}
\ No newline at end of file
diff --git a/tests/framework/base/windowmanager/intent_tests/resetTaskIfNeeded/test-3.json b/tests/framework/base/windowmanager/intent_tests/resetTaskIfNeeded/test-3.json
index c89cdd3..ac7cbbe 100644
--- a/tests/framework/base/windowmanager/intent_tests/resetTaskIfNeeded/test-3.json
+++ b/tests/framework/base/windowmanager/intent_tests/resetTaskIfNeeded/test-3.json
@@ -30,77 +30,55 @@
]
},
"initialState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1Activity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity"
+ ]
},
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity",
- "state": "STOPPED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1Activity",
+ "state": "STOPPED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "STOPPED"
}
]
}
]
},
"endState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "RESUMED"
- }
- ]
- }
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity"
- },
- {
- "tasks": [
- {
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "RESUMED"
}
]
},
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1Activity",
+ "state": "STOPPED"
+ }
+ ]
+ },
+ {
+ "activities": [
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1Activity",
+ "state": "STOPPED"
}
]
}
]
}
-}
+}
\ No newline at end of file
diff --git a/tests/framework/base/windowmanager/intent_tests/resetTaskIfNeeded/test-4.json b/tests/framework/base/windowmanager/intent_tests/resetTaskIfNeeded/test-4.json
index d8f3f7f..27f84bb 100644
--- a/tests/framework/base/windowmanager/intent_tests/resetTaskIfNeeded/test-4.json
+++ b/tests/framework/base/windowmanager/intent_tests/resetTaskIfNeeded/test-4.json
@@ -30,61 +30,47 @@
]
},
"initialState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity2",
- "state": "RESUMED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity",
- "state": "STOPPED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1Activity2",
+ "state": "RESUMED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1Activity",
+ "state": "STOPPED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "STOPPED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity2"
+ ]
}
]
},
"endState": {
- "stacks": [
+ "tasks": [
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity",
- "state": "RESUMED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$RegularActivity",
+ "state": "RESUMED"
}
- ],
- "resumedActivity": "android.server.wm.cts\/android.server.wm.intent.Activities$RegularActivity"
+ ]
},
{
- "tasks": [
+ "activities": [
{
- "activities": [
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity2",
- "state": "STOPPED"
- },
- {
- "name": "android.server.wm.cts\/android.server.wm.intent.Activities$TaskAffinity1Activity",
- "state": "STOPPED"
- }
- ]
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1Activity2",
+ "state": "STOPPED"
+ },
+ {
+ "name": "android.server.wm.cts/android.server.wm.intent.Activities$TaskAffinity1Activity",
+ "state": "STOPPED"
}
]
}
]
}
-}
+}
\ No newline at end of file
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/AppConfigurationTests.java b/tests/framework/base/windowmanager/src/android/server/wm/AppConfigurationTests.java
index 16268d7..27d8121 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/AppConfigurationTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/AppConfigurationTests.java
@@ -21,8 +21,10 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
+import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
+import static android.server.wm.CommandSession.ActivityCallback.ON_CONFIGURATION_CHANGED;
import static android.server.wm.ComponentNameUtils.getWindowName;
import static android.server.wm.StateLogger.logE;
import static android.server.wm.WindowManagerState.STATE_RESUMED;
@@ -32,6 +34,7 @@
import static android.server.wm.app.Components.LANDSCAPE_ORIENTATION_ACTIVITY;
import static android.server.wm.app.Components.LAUNCHING_ACTIVITY;
import static android.server.wm.app.Components.NIGHT_MODE_ACTIVITY;
+import static android.server.wm.app.Components.NO_RELAUNCH_ACTIVITY;
import static android.server.wm.app.Components.PORTRAIT_ORIENTATION_ACTIVITY;
import static android.server.wm.app.Components.RESIZEABLE_ACTIVITY;
import static android.server.wm.app.Components.TEST_ACTIVITY;
@@ -953,4 +956,58 @@
private SizeInfo getAppSizeInfo(ActivitySession activitySession) {
return activitySession.getAppConfigInfo().sizeInfo;
}
+
+ /**
+ * Verify that reported display sizes are different for multiple activities with different
+ * configurations running in the same process.
+ */
+ @Test
+ public void testDisplaySizeInSplitScreen() {
+ assumeTrue("Skipping test: no multi-window support", supportsSplitScreenMultiWindow());
+
+ // Launch two activities in split-screen
+ final ActivitySession primaryActivitySession = createManagedActivityClientSession()
+ .startActivity(getLaunchActivityBuilder()
+ .setUseInstrumentation()
+ .setTargetActivity(RESIZEABLE_ACTIVITY)
+ .setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY)
+ .setWaitForLaunched(true));
+
+ final ActivitySession secondaryActivitySession = createManagedActivityClientSession()
+ .startActivity(getLaunchActivityBuilder()
+ .setUseInstrumentation()
+ .setNewTask(true)
+ .setMultipleTask(true)
+ .setTargetActivity(NO_RELAUNCH_ACTIVITY)
+ .setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY)
+ .setWaitForLaunched(true));
+
+ // Resize split-screen to make sure that sizes are not the same.
+ separateTestJournal();
+ final int STACK_SIZE = 400;
+ resizeDockedStack(STACK_SIZE, STACK_SIZE, STACK_SIZE, STACK_SIZE);
+
+ waitForOrFail("Activity must receive a configuration change",
+ () -> hasConfigChanged(primaryActivitySession));
+ waitForOrFail("Activity must receive a configuration change",
+ () -> hasConfigChanged(secondaryActivitySession));
+
+ // Check if the sizes reported to activities are different.
+ final SizeInfo primarySizeInfo = primaryActivitySession.getConfigInfo().sizeInfo;
+ final SizeInfo secondarySizeInfo = secondaryActivitySession.getConfigInfo().sizeInfo;
+ final SizeInfo appSizeInfo = secondaryActivitySession.getAppConfigInfo().sizeInfo;
+ // Second activity size info should match the application, since the process is tracking the
+ // configuration of the activity that was added last.
+ assertSizesAreSame(secondarySizeInfo, appSizeInfo);
+ // Primary and secondary activity sizes must be different, since the sizes of the windows
+ // after resize are different.
+ assertNotEquals(primarySizeInfo.displayWidth, secondarySizeInfo.displayWidth);
+ assertNotEquals(primarySizeInfo.displayHeight, secondarySizeInfo.displayHeight);
+ }
+
+ private boolean hasConfigChanged(ActivitySession activitySession) {
+ final List<CommandSession.ActivityCallback> callbackHistory =
+ activitySession.takeCallbackHistory();
+ return callbackHistory != null && callbackHistory.contains(ON_CONFIGURATION_CHANGED);
+ }
}
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/MinimalPostProcessingTests.java b/tests/framework/base/windowmanager/src/android/server/wm/MinimalPostProcessingTests.java
index cc49cf4..1c9f174 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/MinimalPostProcessingTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/MinimalPostProcessingTests.java
@@ -35,7 +35,6 @@
import org.junit.Test;
@Presubmit
-@FlakyTest(detail = "Promote once confirmed non-flaky")
public class MinimalPostProcessingTests extends ActivityManagerTestBase {
private static final boolean PREFER_MPP = true;
private static final boolean NOT_PREFER_MPP = false;
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 7f5f871..cf1b454 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayLockedKeyguardTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplayLockedKeyguardTests.java
@@ -135,7 +135,6 @@
mWmState.assertVisibility(DISMISS_KEYGUARD_ACTIVITY, true);
}
- @FlakyTest(bugId = 141674516)
@Test
public void testDismissKeyguard_whileOccluded_secondaryDisplay() {
final LockScreenSession lockScreenSession =
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/PinnedStackTests.java b/tests/framework/base/windowmanager/src/android/server/wm/PinnedStackTests.java
index 0b44b01..1f24b6b 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/PinnedStackTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/PinnedStackTests.java
@@ -36,6 +36,7 @@
import static android.server.wm.app.Components.NON_RESIZEABLE_ACTIVITY;
import static android.server.wm.app.Components.PIP_ACTIVITY;
import static android.server.wm.app.Components.PIP_ACTIVITY2;
+import static android.server.wm.app.Components.PIP_ACTIVITY_WITH_MINIMAL_SIZE;
import static android.server.wm.app.Components.PIP_ACTIVITY_WITH_SAME_AFFINITY;
import static android.server.wm.app.Components.PIP_ON_STOP_ACTIVITY;
import static android.server.wm.app.Components.PipActivity.ACTION_ENTER_PIP;
@@ -81,6 +82,8 @@
import android.content.ComponentName;
import android.content.Context;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.database.ContentObserver;
import android.graphics.Rect;
@@ -120,9 +123,7 @@
private static final String TAG = PinnedStackTests.class.getSimpleName();
private static final String APP_OPS_OP_ENTER_PICTURE_IN_PICTURE = "PICTURE_IN_PICTURE";
- private static final int APP_OPS_MODE_ALLOWED = 0;
private static final int APP_OPS_MODE_IGNORED = 1;
- private static final int APP_OPS_MODE_ERRORED = 2;
private static final int ROTATION_0 = 0;
private static final int ROTATION_90 = 1;
@@ -247,6 +248,31 @@
assertPinnedStackActivityIsInDisplayBounds(PIP_ACTIVITY);
}
+ // TODO: launch/size pip to a size smaller than limitation and verify the minWidth/minHeight
+ // is respected after b/149338177.
+ @Test
+ public void testEnterPipWithMinimalSize() throws Exception {
+ // Launch a PiP activity with minimal size specified
+ launchActivity(PIP_ACTIVITY_WITH_MINIMAL_SIZE, EXTRA_ENTER_PIP, "true");
+ // Wait for animation complete since we are comparing size
+ waitForEnterPipAnimationComplete(PIP_ACTIVITY_WITH_MINIMAL_SIZE);
+ assertPinnedStackExists();
+
+ // query the minimal size
+ final PackageManager pm = getInstrumentation().getTargetContext().getPackageManager();
+ final ActivityInfo info = pm.getActivityInfo(
+ PIP_ACTIVITY_WITH_MINIMAL_SIZE, 0 /* flags */);
+ final Size minSize = new Size(info.windowLayout.minWidth, info.windowLayout.minHeight);
+
+ // compare the bounds with minimal size
+ final Rect pipBounds = getPinnedStackBounds();
+ assertTrue("Pinned stack bounds is no smaller than minimal",
+ (pipBounds.width() == minSize.getWidth()
+ && pipBounds.height() >= minSize.getHeight())
+ || (pipBounds.height() == minSize.getHeight()
+ && pipBounds.width() >= minSize.getWidth()));
+ }
+
@Test
public void testEnterPipAspectRatioMin() throws Exception {
testEnterPipAspectRatio(MIN_ASPECT_RATIO_NUMERATOR, MIN_ASPECT_RATIO_DENOMINATOR);
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/StartActivityAsUserActivity.java b/tests/framework/base/windowmanager/src/android/server/wm/StartActivityAsUserActivity.java
index cb279219..a73521b 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/StartActivityAsUserActivity.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/StartActivityAsUserActivity.java
@@ -23,6 +23,7 @@
import android.app.Activity;
import android.os.Bundle;
import android.os.RemoteCallback;
+import android.os.UserHandle;
import android.util.Log;
public class StartActivityAsUserActivity extends Activity {
@@ -35,10 +36,10 @@
RemoteCallback cb = (RemoteCallback) extra.get(EXTRA_CALLBACK);
if (cb != null) {
Bundle result = new Bundle();
- result.putInt(KEY_USER_ID, getUserId());
+ result.putInt(KEY_USER_ID, UserHandle.myUserId());
cb.sendResult(result);
}
- Log.i(LOG_TAG, "Second activity started with user " + getUserId());
+ Log.i(LOG_TAG, "Second activity started with user " + UserHandle.myUserId());
finish();
}
}
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/SurfaceControlViewHostTests.java b/tests/framework/base/windowmanager/src/android/server/wm/SurfaceControlViewHostTests.java
index 7f8aa01..5506e85 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/SurfaceControlViewHostTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/SurfaceControlViewHostTests.java
@@ -61,7 +61,6 @@
* atest CtsWindowManagerDeviceTestCases:SurfaceControlViewHostTests
*/
@Presubmit
-@FlakyTest
public class SurfaceControlViewHostTests implements SurfaceHolder.Callback {
private final ActivityTestRule<Activity> mActivityRule = new ActivityTestRule<>(Activity.class);
@@ -117,7 +116,7 @@
mEmbeddedLayoutParams = new WindowManager.LayoutParams(width, height,
WindowManager.LayoutParams.TYPE_APPLICATION, 0, PixelFormat.OPAQUE);
- mVr.addView(v, mEmbeddedLayoutParams);
+ mVr.setView(v, mEmbeddedLayoutParams);
}
@Override
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/intent/LaunchRunner.java b/tests/framework/base/windowmanager/src/android/server/wm/intent/LaunchRunner.java
index 9e1d67a..badb526 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/intent/LaunchRunner.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/intent/LaunchRunner.java
@@ -20,7 +20,7 @@
import static android.server.wm.intent.StateComparisonException.assertEndStatesEqual;
import static android.server.wm.intent.StateComparisonException.assertInitialStateEqual;
-import static androidx.test.InstrumentationRegistry.getInstrumentation;
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
import static com.google.common.collect.Iterables.getLast;
@@ -71,11 +71,11 @@
* The activities that were already present in the system when the test started.
* So they can be removed form the outputs, otherwise our tests would be system dependent.
*/
- private List<WindowManagerState.ActivityTask> mBaseStacks;
+ private List<WindowManagerState.ActivityTask> mBaseTasks;
public LaunchRunner(IntentTestBase testBase) {
mTestBase = testBase;
- mBaseStacks = getBaseStacks();
+ mBaseTasks = getBaseTasks();
}
/**
@@ -106,7 +106,7 @@
// assert that the state after setup is the same this time as the recorded state.
StateDump setupStateDump = waitDumpAndTrimForVerification(getLast(activityLog),
- testCase.getEndState());
+ testCase.getInitialState());
assertInitialStateEqual(testCase.getInitialState(), setupStateDump);
// apply all the intents in the act stage
@@ -281,8 +281,8 @@
/**
* After the last activity has been launched we wait for a valid state + an extra three seconds
- * so have a stable state of the system. Also all previously known stacks in
- * {@link LaunchRunner#mBaseStacks} is excluded from the output.
+ * so have a stable state of the system. Also all previously known tasks in
+ * {@link LaunchRunner#mBaseTasks} is excluded from the output.
*
* @param activity The last activity to be launched before dumping the state.
* @return A stable {@link StateDump}, meaning no more {@link android.app.Activity} is in a
@@ -294,9 +294,9 @@
// lifecycle state. wait an extra 3 seconds for it to settle
SystemClock.sleep(BEFORE_DUMP_TIMEOUT);
mTestBase.getWmState().computeState(activity.getComponentName());
- List<WindowManagerState.ActivityTask> endStateStacks =
+ List<WindowManagerState.ActivityTask> endStateTasks =
mTestBase.getWmState().getRootTasks();
- return StateDump.fromStacks(endStateStacks, mBaseStacks);
+ return StateDump.fromTasks(endStateTasks, mBaseTasks);
}
/**
@@ -312,21 +312,18 @@
*/
public StateDump waitDumpAndTrimForVerification(Activity activity, StateDump expected) {
mTestBase.getWmState().waitForValidState(activity.getComponentName());
- // The last activity that was launched before the dump could still be in an intermediate
- // lifecycle state. wait an extra 3 seconds for it to settle
- SystemClock.sleep(BEFORE_DUMP_TIMEOUT);
mTestBase.getWmState().waitForWithAmState(
- am -> StateDump.fromStacks(am.getRootTasks(), mBaseStacks).equals(expected),
+ am -> StateDump.fromTasks(am.getRootTasks(), mBaseTasks).equals(expected),
"the activity states match up with what we recorded");
mTestBase.getWmState().computeState(activity.getComponentName());
- List<WindowManagerState.ActivityTask> endStateStacks =
+ List<WindowManagerState.ActivityTask> endStateTasks =
mTestBase.getWmState().getRootTasks();
- return StateDump.fromStacks(endStateStacks, mBaseStacks);
+ return StateDump.fromTasks(endStateTasks, mBaseTasks);
}
- private List<WindowManagerState.ActivityTask> getBaseStacks() {
+ private List<WindowManagerState.ActivityTask> getBaseTasks() {
WindowManagerStateHelper amWmState = mTestBase.getWmState();
amWmState.computeState(new ComponentName[]{});
return amWmState.getRootTasks();
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/intent/Persistence.java b/tests/framework/base/windowmanager/src/android/server/wm/intent/Persistence.java
index f3ab41a..5d80e32 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/intent/Persistence.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/intent/Persistence.java
@@ -440,54 +440,57 @@
}
public static class StateDump {
- final List<StackState> mStacks;
+ private static final String TASKS_KEY = "tasks";
- public static StateDump fromStacks(List<WindowManagerState.ActivityTask> activityTasks,
+ /**
+ * The Tasks in this stack ordered from most recent to least recent.
+ */
+ private final List<TaskState> mTasks;
+
+ public static StateDump fromTasks(List<WindowManagerState.ActivityTask> activityTasks,
List<WindowManagerState.ActivityTask> baseStacks) {
- List<StackState> stacks = new ArrayList<>();
- for (WindowManagerState.ActivityTask stack : trimStacks(activityTasks,
- baseStacks)) {
- stacks.add(new StackState(stack));
+ List<TaskState> tasks = new ArrayList<>();
+ for (WindowManagerState.ActivityTask task : trimTasks(activityTasks, baseStacks)) {
+ tasks.add(new TaskState(task));
}
-
- return new StateDump(stacks);
+ return new StateDump(tasks);
}
- public StateDump(List<StackState> stacks) {
- mStacks = stacks;
+ private StateDump(List<TaskState> tasks) {
+ mTasks = tasks;
}
JSONObject toJson() throws JSONException {
- JSONArray stacks = new JSONArray();
- for (StackState stack : mStacks) {
- stacks.put(stack.toJson());
+ JSONArray tasks = new JSONArray();
+ for (TaskState task : mTasks) {
+ tasks.put(task.toJson());
}
- return new JSONObject().put("stacks", stacks);
+ return new JSONObject().put(TASKS_KEY, tasks);
}
static StateDump fromJson(JSONObject object) throws JSONException {
- JSONArray jsonTasks = object.getJSONArray("stacks");
- List<StackState> stacks = new ArrayList<>();
+ JSONArray jsonTasks = object.getJSONArray(TASKS_KEY);
+ List<TaskState> tasks = new ArrayList<>();
for (int i = 0; i < jsonTasks.length(); i++) {
- stacks.add(StackState.fromJson((JSONObject) jsonTasks.get(i)));
+ tasks.add(TaskState.fromJson((JSONObject) jsonTasks.get(i)));
}
- return new StateDump(stacks);
+ return new StateDump(tasks);
}
/**
- * To make the state dump non device specific we remove every stack that was present
- * in the system before recording, by their ID. For example a stack containing the launcher
+ * To make the state dump non device specific we remove every task that was present
+ * in the system before recording, by their ID. For example a task containing the launcher
* activity.
*/
- public static List<WindowManagerState.ActivityTask> trimStacks(
+ public static List<WindowManagerState.ActivityTask> trimTasks(
List<WindowManagerState.ActivityTask> toTrim,
List<WindowManagerState.ActivityTask> trimFrom) {
- for (WindowManagerState.ActivityTask stack : trimFrom) {
- toTrim.removeIf(t -> t.getRootTaskId() == stack.getRootTaskId());
+ for (WindowManagerState.ActivityTask task : trimFrom) {
+ toTrim.removeIf(t -> t.getRootTaskId() == task.getRootTaskId());
}
return toTrim;
@@ -498,103 +501,49 @@
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
StateDump stateDump = (StateDump) o;
- return Objects.equals(mStacks, stateDump.mStacks);
+ return Objects.equals(mTasks, stateDump.mTasks);
}
@Override
public int hashCode() {
- return Objects.hash(mStacks);
- }
- }
-
- /**
- * A simplified JSON version of the information in {@link WindowManagerState.ActivityTask}
- */
- public static class StackState {
- private static final String TASKS_KEY = "tasks";
- private static final String RESUMED_ACTIVITY_KEY = "resumedActivity";
-
- /**
- * The component name of the resumedActivity in this Stack, empty string if there is none.
- */
- private final String mResumedActivity;
- /**
- * The Tasks in this stack ordered from most recent to least recent.
- */
- private final List<TaskState> mTasks;
-
- public StackState(String resumedActivity, List<TaskState> tasks) {
- mResumedActivity = resumedActivity;
- mTasks = tasks;
- }
-
- public StackState(WindowManagerState.ActivityTask stack) {
- this.mResumedActivity = stack.getResumedActivity();
- mTasks = new ArrayList<>();
- for (WindowManagerState.ActivityTask task : stack.getTasks()) {
- this.mTasks.add(new TaskState(task));
- }
- }
-
- JSONObject toJson() throws JSONException {
- JSONArray jsonTasks = new JSONArray();
-
- for (TaskState task : mTasks) {
- jsonTasks.put(task.toJson());
- }
-
- return new JSONObject()
- .put(TASKS_KEY, jsonTasks)
- .put(RESUMED_ACTIVITY_KEY, mResumedActivity);
- }
-
- static StackState fromJson(JSONObject object) throws JSONException {
- JSONArray jsonTasks = object.getJSONArray(TASKS_KEY);
- List<TaskState> tasks = new ArrayList<>();
-
- for (int i = 0; i < jsonTasks.length(); i++) {
- tasks.add(TaskState.fromJson((JSONObject) jsonTasks.get(i)));
- }
-
- return new StackState(object.optString(RESUMED_ACTIVITY_KEY, ""), tasks);
- }
-
- public String getResumedActivity() {
- return mResumedActivity;
- }
-
- public List<TaskState> getTasks() {
- return mTasks;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
- StackState stack = (StackState) o;
- return Objects.equals(mTasks, stack.mTasks);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(mResumedActivity, mTasks);
+ return Objects.hash(mTasks);
}
}
public static class TaskState {
+ private static final String STATE_RESUMED = "RESUMED";
private static final String ACTIVITIES_KEY = "activities";
/**
+ * The component name of the resumedActivity in this state, empty string if there is none.
+ */
+ private final String mResumedActivity;
+
+ /**
* The activities in this task ordered from most recent to least recent.
*/
- private List<ActivityState> mActivities = new ArrayList<>();
+ private final List<ActivityState> mActivities = new ArrayList<>();
- public TaskState(List<ActivityState> activities) {
- mActivities = activities;
+ private TaskState(JSONArray jsonActivities) throws JSONException {
+ String resumedActivity = "";
+ for (int i = 0; i < jsonActivities.length(); i++) {
+ final ActivityState activity =
+ ActivityState.fromJson((JSONObject) jsonActivities.get(i));
+ // The json file shouldn't define multiple resumed activities, but it is fine that
+ // the test will fail when comparing to the real state.
+ if (STATE_RESUMED.equals(activity.getState())) {
+ resumedActivity = activity.getName();
+ }
+ mActivities.add(activity);
+ }
+
+ mResumedActivity = resumedActivity;
}
public TaskState(WindowManagerState.ActivityTask state) {
+ final String resumedActivity = state.getResumedActivity();
+ mResumedActivity = resumedActivity != null ? resumedActivity : "";
for (WindowManagerState.Activity activity : state.getActivities()) {
this.mActivities.add(new ActivityState(activity));
}
@@ -612,14 +561,7 @@
}
static TaskState fromJson(JSONObject object) throws JSONException {
- JSONArray jsonActivities = object.getJSONArray(ACTIVITIES_KEY);
- List<ActivityState> activities = new ArrayList<>();
-
- for (int i = 0; i < jsonActivities.length(); i++) {
- activities.add(ActivityState.fromJson((JSONObject) jsonActivities.get(i)));
- }
-
- return new TaskState(activities);
+ return new TaskState(object.getJSONArray(ACTIVITIES_KEY));
}
public List<ActivityState> getActivities() {
@@ -631,12 +573,13 @@
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
TaskState task = (TaskState) o;
- return Objects.equals(mActivities, task.mActivities);
+ return Objects.equals(mResumedActivity, task.mResumedActivity)
+ && Objects.equals(mActivities, task.mActivities);
}
@Override
public int hashCode() {
- return Objects.hash(mActivities);
+ return Objects.hash(mResumedActivity, mActivities);
}
}
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 8fbb635..e1ecc13 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
@@ -546,26 +546,25 @@
}
/**
- * Move around center of the specific display to ensures the display to be focused without
- * triggering potential clicked event to impact the test environment.
+ * Insert an input event (ACTION_DOWN -> ACTION_CANCEL) to ensures the display to be focused
+ * without triggering potential clicked to impact the test environment.
* (e.g: Keyguard credential activated unexpectedly.)
*
* @param displayId the display ID to gain focused by inject swipe action
*/
- protected void moveAroundCenterSync(int displayId) {
+ protected void touchAndCancelOnDisplayCenterSync(int displayId) {
final Rect bounds = mWmState.getDisplay(displayId).getDisplayRect();
+ final int x = bounds.left + bounds.width() / 2;
+ final int y = bounds.top + bounds.height() / 2;
final long downTime = SystemClock.uptimeMillis();
+ injectMotion(downTime, downTime, MotionEvent.ACTION_DOWN, x, y, displayId, true /* sync */);
+
+ final long eventTime = SystemClock.uptimeMillis();
final int touchSlop = ViewConfiguration.get(mContext).getScaledTouchSlop();
- final int downX = bounds.left + bounds.width() / 2;
- final int downY = bounds.top + bounds.height() / 2;
- injectMotion(downTime, downTime, MotionEvent.ACTION_DOWN, downX, downY, displayId, true);
-
- final int moveX = downX + Float.floatToIntBits(touchSlop / 2.0f);
- final int moveY = downY + Float.floatToIntBits(touchSlop / 2.0f);
- injectMotion(downTime, downTime, MotionEvent.ACTION_MOVE, moveX, moveY, displayId, true);
-
- final long upTime = SystemClock.uptimeMillis();
- injectMotion(downTime, upTime, MotionEvent.ACTION_UP, moveX, moveY, displayId, true);
+ final int tapX = x + Math.round(touchSlop / 2.0f);
+ final int tapY = y + Math.round(touchSlop / 2.0f);
+ injectMotion(downTime, eventTime, MotionEvent.ACTION_CANCEL, tapX, tapY, displayId,
+ true /* sync */);
}
protected void tapOnDisplaySync(int x, int y, int displayId) {
@@ -1238,7 +1237,7 @@
public LockScreenSession enterAndConfirmLockCredential() {
// Ensure focus will switch to default display. Meanwhile we cannot tap on center area,
// which may tap on input credential area.
- moveAroundCenterSync(DEFAULT_DISPLAY);
+ touchAndCancelOnDisplayCenterSync(DEFAULT_DISPLAY);
waitForDeviceIdle(3000);
SystemUtil.runWithShellPermissionIdentity(() ->
@@ -1280,7 +1279,7 @@
LockScreenSession unlockDevice() {
// Make sure the unlock button event is send to the default display.
- moveAroundCenterSync(DEFAULT_DISPLAY);
+ touchAndCancelOnDisplayCenterSync(DEFAULT_DISPLAY);
pressUnlockButton();
return this;
diff --git a/tests/inputmethod/mockime/src/com/android/cts/mockime/MockIme.java b/tests/inputmethod/mockime/src/com/android/cts/mockime/MockIme.java
index 6142b9e..9a73722 100644
--- a/tests/inputmethod/mockime/src/com/android/cts/mockime/MockIme.java
+++ b/tests/inputmethod/mockime/src/com/android/cts/mockime/MockIme.java
@@ -286,6 +286,8 @@
case "getDisplayId":
return getSystemService(WindowManager.class)
.getDefaultDisplay().getDisplayId();
+ case "verifyLayoutInflaterContext":
+ return getLayoutInflater().getContext() == this;
}
}
return ImeEvent.RETURN_VALUE_UNAVAILABLE;
diff --git a/tests/inputmethod/mockime/src/com/android/cts/mockime/MockImeSession.java b/tests/inputmethod/mockime/src/com/android/cts/mockime/MockImeSession.java
index 5e653c6..a407a28 100644
--- a/tests/inputmethod/mockime/src/com/android/cts/mockime/MockImeSession.java
+++ b/tests/inputmethod/mockime/src/com/android/cts/mockime/MockImeSession.java
@@ -982,4 +982,18 @@
final Bundle params = new Bundle();
return callCommandInternal("getDisplayId", params);
}
+
+ /**
+ * Verifies {@code InputMethodService.getLayoutInflater().getContext()} is equal to
+ * {@code InputMethodService.this}.
+ *
+ * @return {@link ImeCommand} object that can be passed to
+ * {@link ImeEventStreamTestUtils#expectCommand(ImeEventStream, ImeCommand, long)} to
+ * wait until this event is handled by {@link MockIme}
+ */
+ @NonNull
+ public ImeCommand verifyLayoutInflaterContext() {
+ final Bundle params = new Bundle();
+ return callCommandInternal("verifyLayoutInflaterContext", params);
+ }
}
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/InputMethodServiceTest.java b/tests/inputmethod/src/android/view/inputmethod/cts/InputMethodServiceTest.java
index 0b20b85..1a2561a 100644
--- a/tests/inputmethod/src/android/view/inputmethod/cts/InputMethodServiceTest.java
+++ b/tests/inputmethod/src/android/view/inputmethod/cts/InputMethodServiceTest.java
@@ -116,6 +116,24 @@
});
}
+ @Test
+ public void verifyLayoutInflaterContext() throws Exception {
+ try (MockImeSession imeSession = MockImeSession.create(
+ InstrumentationRegistry.getContext(),
+ InstrumentationRegistry.getInstrumentation().getUiAutomation(),
+ new ImeSettings.Builder())) {
+ final ImeEventStream stream = imeSession.openEventStream();
+
+ createTestActivity(SOFT_INPUT_STATE_ALWAYS_VISIBLE);
+ expectEvent(stream, event -> "onStartInputView".equals(event.getEventName()), TIMEOUT);
+
+ final ImeCommand command = imeSession.verifyLayoutInflaterContext();
+ assertTrue("InputMethodService.getLayoutInflater().getContext() must be equal to"
+ + " InputMethodService.this",
+ expectCommand(stream, command, TIMEOUT).getReturnBooleanValue());
+ }
+ }
+
private void verifyImeConsumesBackButton(int backDisposition) throws Exception {
try (MockImeSession imeSession = MockImeSession.create(
InstrumentationRegistry.getContext(),
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/SearchViewTest.java b/tests/inputmethod/src/android/view/inputmethod/cts/SearchViewTest.java
index 5cf8fd0..2b327f5 100644
--- a/tests/inputmethod/src/android/view/inputmethod/cts/SearchViewTest.java
+++ b/tests/inputmethod/src/android/view/inputmethod/cts/SearchViewTest.java
@@ -19,15 +19,20 @@
import static com.android.cts.mockime.ImeEventStreamTestUtils.EventFilterMode.CHECK_EXIT_EVENT_ONLY;
import static com.android.cts.mockime.ImeEventStreamTestUtils.expectBindInput;
import static com.android.cts.mockime.ImeEventStreamTestUtils.expectEvent;
+import static com.android.cts.mockime.ImeEventStreamTestUtils.notExpectEvent;
import android.os.Process;
import android.text.InputType;
+import android.view.View;
+import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.view.inputmethod.cts.util.EndToEndImeTestBase;
import android.view.inputmethod.cts.util.TestActivity;
+import android.widget.BaseAdapter;
import android.widget.EditText;
import android.widget.LinearLayout;
+import android.widget.ListView;
import android.widget.SearchView;
import androidx.test.InstrumentationRegistry;
@@ -49,6 +54,7 @@
@RunWith(AndroidJUnit4.class)
public class SearchViewTest extends EndToEndImeTestBase {
static final long TIMEOUT = TimeUnit.SECONDS.toMillis(5);
+ static final long NOT_EXPECT_TIMEOUT = TimeUnit.SECONDS.toMillis(2);
public SearchView launchTestActivity(boolean requestFocus) {
final AtomicReference<SearchView> searchViewRef = new AtomicReference<>();
@@ -77,6 +83,32 @@
return searchViewRef.get();
}
+ private SearchView launchTestActivityWithListView(boolean requestFocus) {
+ final AtomicReference<SearchView> searchViewRef = new AtomicReference<>();
+ TestActivity.startSync(activity -> {
+ final LinearLayout layout = new LinearLayout(activity);
+ layout.setOrientation(LinearLayout.VERTICAL);
+
+ final ListView listView = new ListView(activity);
+ layout.addView(listView);
+
+ final SearchView searchView = new SearchView(activity);
+ searchViewRef.set(searchView);
+ listView.setAdapter(new SingleItemAdapter(searchView));
+
+ searchView.setQueryHint("hint");
+ searchView.setIconifiedByDefault(false);
+ searchView.setInputType(InputType.TYPE_TEXT_FLAG_CAP_SENTENCES);
+ searchView.setImeOptions(EditorInfo.IME_ACTION_DONE);
+ if (requestFocus) {
+ searchView.requestFocus();
+ }
+
+ return layout;
+ });
+ return searchViewRef.get();
+ }
+
@Test
public void testTapThenSetQuery() throws Exception {
try (MockImeSession imeSession = MockImeSession.create(
@@ -132,4 +164,60 @@
CHECK_EXIT_EVENT_ONLY, TIMEOUT);
}
}
+
+ @Test
+ public void testShowImeWhenSearchViewFocusInListView() throws Exception {
+ try (MockImeSession imeSession = MockImeSession.create(
+ InstrumentationRegistry.getContext(),
+ InstrumentationRegistry.getInstrumentation().getUiAutomation(),
+ new ImeSettings.Builder())) {
+ final ImeEventStream stream = imeSession.openEventStream();
+
+ final SearchView searchView = launchTestActivityWithListView(true /* requestFocus */);
+
+ // Emulate tap event on SearchView
+ CtsTouchUtils.emulateTapOnViewCenter(
+ InstrumentationRegistry.getInstrumentation(), null, searchView);
+
+ // Expect input to bind since EditText is focused.
+ expectBindInput(stream, Process.myPid(), TIMEOUT);
+
+ // Wait until "showSoftInput" gets called with a real InputConnection
+ expectEvent(stream, event ->
+ "showSoftInput".equals(event.getEventName())
+ && !event.getExitState().hasDummyInputConnection(),
+ CHECK_EXIT_EVENT_ONLY, TIMEOUT);
+
+ notExpectEvent(stream, event -> "hideSoftInput".equals(event.getEventName()),
+ NOT_EXPECT_TIMEOUT);
+ }
+ }
+
+ static final class SingleItemAdapter extends BaseAdapter {
+ private final SearchView mSearchView;
+
+ SingleItemAdapter(SearchView searchView) {
+ mSearchView = searchView;
+ }
+
+ @Override
+ public int getCount() {
+ return 1;
+ }
+
+ @Override
+ public Object getItem(int i) {
+ return mSearchView;
+ }
+
+ @Override
+ public long getItemId(int i) {
+ return 0;
+ }
+
+ @Override
+ public View getView(int i, View view, ViewGroup viewGroup) {
+ return mSearchView;
+ }
+ }
}
diff --git a/tests/location/location_fine/src/android/location/cts/fine/GnssMeasurementTest.java b/tests/location/location_fine/src/android/location/cts/fine/GnssMeasurementTest.java
index dccf022..2536890 100644
--- a/tests/location/location_fine/src/android/location/cts/fine/GnssMeasurementTest.java
+++ b/tests/location/location_fine/src/android/location/cts/fine/GnssMeasurementTest.java
@@ -100,13 +100,13 @@
measurement.resetBasebandCn0DbHz();
assertFalse(measurement.hasBasebandCn0DbHz());
- assertTrue(measurement.hasReceiverInterSignalBiasNanos());
- measurement.resetReceiverInterSignalBiasNanos();
- assertFalse(measurement.hasReceiverInterSignalBiasNanos());
+ assertTrue(measurement.hasFullInterSignalBiasNanos());
+ measurement.resetFullInterSignalBiasNanos();
+ assertFalse(measurement.hasFullInterSignalBiasNanos());
- assertTrue(measurement.hasReceiverInterSignalBiasUncertaintyNanos());
- measurement.resetReceiverInterSignalBiasUncertaintyNanos();
- assertFalse(measurement.hasReceiverInterSignalBiasUncertaintyNanos());
+ assertTrue(measurement.hasFullInterSignalBiasUncertaintyNanos());
+ measurement.resetFullInterSignalBiasUncertaintyNanos();
+ assertFalse(measurement.hasFullInterSignalBiasUncertaintyNanos());
assertTrue(measurement.hasSatelliteInterSignalBiasNanos());
measurement.resetSatelliteInterSignalBiasNanos();
@@ -134,8 +134,8 @@
measurement.setPseudorangeRateUncertaintyMetersPerSecond(10.0);
measurement.setReceivedSvTimeNanos(11);
measurement.setReceivedSvTimeUncertaintyNanos(12);
- measurement.setReceiverInterSignalBiasNanos(1.3);
- measurement.setReceiverInterSignalBiasUncertaintyNanos(2.5);
+ measurement.setFullInterSignalBiasNanos(1.3);
+ measurement.setFullInterSignalBiasUncertaintyNanos(2.5);
measurement.setSatelliteInterSignalBiasNanos(5.4);
measurement.setSatelliteInterSignalBiasUncertaintyNanos(10.0);
measurement.setSnrInDb(13.0);
@@ -162,8 +162,8 @@
assertEquals(10.0, measurement.getPseudorangeRateUncertaintyMetersPerSecond(), DELTA);
assertEquals(11, measurement.getReceivedSvTimeNanos());
assertEquals(12, measurement.getReceivedSvTimeUncertaintyNanos());
- assertEquals(1.3, measurement.getReceiverInterSignalBiasNanos(), DELTA);
- assertEquals(2.5, measurement.getReceiverInterSignalBiasUncertaintyNanos(), DELTA);
+ assertEquals(1.3, measurement.getFullInterSignalBiasNanos(), DELTA);
+ assertEquals(2.5, measurement.getFullInterSignalBiasUncertaintyNanos(), DELTA);
assertEquals(5.4, measurement.getSatelliteInterSignalBiasNanos(), DELTA);
assertEquals(10.0, measurement.getSatelliteInterSignalBiasUncertaintyNanos(), DELTA);
assertEquals(13.0, measurement.getSnrInDb(), DELTA);
diff --git a/tests/quickaccesswallet/AndroidManifest.xml b/tests/quickaccesswallet/AndroidManifest.xml
index 3d2ad69..4ad90ab 100755
--- a/tests/quickaccesswallet/AndroidManifest.xml
+++ b/tests/quickaccesswallet/AndroidManifest.xml
@@ -24,10 +24,6 @@
<uses-permission android:name="android.permission.NFC"/>
<!-- Required to test QuickAccessWalletClient feature availability -->
<uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
- <uses-permission android:name="android.permission.MANAGE_USERS" />
- <uses-permission android:name="android.permission.CREATE_USERS" />
- <!-- Required to bind to the QuickAccessWalletService -->
- <uses-permission android:name="android.permission.BIND_QUICK_ACCESS_WALLET_SERVICE" />
<application>
<uses-library android:name="android.test.runner" />
diff --git a/tests/tests/app.usage/src/android/app/usage/cts/UsageStatsTest.java b/tests/tests/app.usage/src/android/app/usage/cts/UsageStatsTest.java
index 0ca1fc9..0d834cd 100644
--- a/tests/tests/app.usage/src/android/app/usage/cts/UsageStatsTest.java
+++ b/tests/tests/app.usage/src/android/app/usage/cts/UsageStatsTest.java
@@ -687,6 +687,8 @@
mUsageStatsManager.getAppStandbyBucket(mTargetPackage));
}
+ // TODO(148887416): get this test to work for instant apps
+ @AppModeFull(reason = "Test APK Activity not found when installed as an instant app")
@Test
public void testIsAppInactive_Charging() throws Exception {
setStandByBucket(TEST_APP_PKG, "rare");
diff --git a/tests/tests/appop/AndroidManifest.xml b/tests/tests/appop/AndroidManifest.xml
index ab36586..0c89b6e 100644
--- a/tests/tests/appop/AndroidManifest.xml
+++ b/tests/tests/appop/AndroidManifest.xml
@@ -19,11 +19,11 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="android.app.appops.cts"
android:targetSandboxVersion="2">
- <feature android:featureId="testFeature" android:label="@string/dummyLabel" />
- <feature android:featureId="firstFeature" android:label="@string/dummyLabel" />
- <feature android:featureId="secondFeature" android:label="@string/dummyLabel" />
- <feature android:featureId="firstProxyFeature" android:label="@string/dummyLabel" />
- <feature android:featureId="secondProxyFeature" android:label="@string/dummyLabel" />
+ <attribution android:tag="testAttribution" android:label="@string/dummyLabel" />
+ <attribution android:tag="firstAttribution" android:label="@string/dummyLabel" />
+ <attribution android:tag="secondAttribution" android:label="@string/dummyLabel" />
+ <attribution android:tag="firstProxyAttribution" android:label="@string/dummyLabel" />
+ <attribution android:tag="secondProxyAttribution" android:label="@string/dummyLabel" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
diff --git a/tests/tests/appop/AndroidTest.xml b/tests/tests/appop/AndroidTest.xml
index a911b20..386feb4 100644
--- a/tests/tests/appop/AndroidTest.xml
+++ b/tests/tests/appop/AndroidTest.xml
@@ -37,12 +37,12 @@
<option name="push-file" key="CtsAppToBlame1.apk" value="/data/local/tmp/cts/appops/CtsAppToBlame1.apk" />
<option name="push-file" key="CtsAppToBlame2.apk" value="/data/local/tmp/cts/appops/CtsAppToBlame2.apk" />
<option name="push-file" key="CtsAppToCollect.apk" value="/data/local/tmp/cts/appops/CtsAppToCollect.apk" />
- <option name="push-file" key="AppWithDuplicateFeature.apk" value="/data/local/tmp/cts/appops/AppWithDuplicateFeature.apk" />
- <option name="push-file" key="AppWithFeatureInheritingFromExisting.apk" value="/data/local/tmp/cts/appops/AppWithFeatureInheritingFromExisting.apk" />
- <option name="push-file" key="AppWithFeatureInheritingFromSameAsOther.apk" value="/data/local/tmp/cts/appops/AppWithFeatureInheritingFromSameAsOther.apk" />
- <option name="push-file" key="AppWithFeatureInheritingFromSelf.apk" value="/data/local/tmp/cts/appops/AppWithFeatureInheritingFromSelf.apk" />
- <option name="push-file" key="AppWithLongFeatureIdFeature.apk" value="/data/local/tmp/cts/appops/AppWithLongFeatureIdFeature.apk" />
- <option name="push-file" key="AppWithTooManyFeatures.apk" value="/data/local/tmp/cts/appops/AppWithTooManyFeatures.apk" />
+ <option name="push-file" key="AppWithDuplicateAttribution.apk" value="/data/local/tmp/cts/appops/AppWithDuplicateAttribution.apk" />
+ <option name="push-file" key="AppWithAttributionInheritingFromExisting.apk" value="/data/local/tmp/cts/appops/AppWithAttributionInheritingFromExisting.apk" />
+ <option name="push-file" key="AppWithAttributionInheritingFromSameAsOther.apk" value="/data/local/tmp/cts/appops/AppWithAttributionInheritingFromSameAsOther.apk" />
+ <option name="push-file" key="AppWithAttributionInheritingFromSelf.apk" value="/data/local/tmp/cts/appops/AppWithAttributionInheritingFromSelf.apk" />
+ <option name="push-file" key="AppWithLongAttributionTag.apk" value="/data/local/tmp/cts/appops/AppWithLongAttributionTag.apk" />
+ <option name="push-file" key="AppWithTooManyAttributions.apk" value="/data/local/tmp/cts/appops/AppWithTooManyAttributions.apk" />
</target_preparer>
<!-- Remove additional apps if installed -->
diff --git a/tests/tests/appop/AppThatUsesAppOps/AndroidManifest.xml b/tests/tests/appop/AppThatUsesAppOps/AndroidManifest.xml
index e3e4937..df614d8 100644
--- a/tests/tests/appop/AppThatUsesAppOps/AndroidManifest.xml
+++ b/tests/tests/appop/AppThatUsesAppOps/AndroidManifest.xml
@@ -18,7 +18,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="android.app.appops.cts.appthatusesappops">
- <feature android:featureId="testFeature" android:label="@string/dummyLabel" />
+ <attribution android:tag="testAttribution" android:label="@string/dummyLabel" />
<application>
<service android:name=".AppOpsUserService" android:exported="true" />
diff --git a/tests/tests/appop/AppThatUsesAppOps/res/values/strings.xml b/tests/tests/appop/AppThatUsesAppOps/res/values/strings.xml
index 2d02f14..37d548d 100644
--- a/tests/tests/appop/AppThatUsesAppOps/res/values/strings.xml
+++ b/tests/tests/appop/AppThatUsesAppOps/res/values/strings.xml
@@ -16,5 +16,5 @@
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="dummyLabel">A feature</string>
+ <string name="dummyLabel">An attribution</string>
</resources>
diff --git a/tests/tests/appop/AppThatUsesAppOps/src/android/app/appops/cts/appthatusesappops/AppOpsUserService.kt b/tests/tests/appop/AppThatUsesAppOps/src/android/app/appops/cts/appthatusesappops/AppOpsUserService.kt
index fb87058..ba98da1 100644
--- a/tests/tests/appop/AppThatUsesAppOps/src/android/app/appops/cts/appthatusesappops/AppOpsUserService.kt
+++ b/tests/tests/appop/AppThatUsesAppOps/src/android/app/appops/cts/appthatusesappops/AppOpsUserService.kt
@@ -25,7 +25,7 @@
import android.app.SyncNotedAppOp
import android.app.appops.cts.IAppOpsUserClient
import android.app.appops.cts.IAppOpsUserService
-import android.app.appops.cts.TEST_FEATURE_ID
+import android.app.appops.cts.TEST_ATTRIBUTION_TAG
import android.app.appops.cts.eventually
import android.content.Intent
import android.os.IBinder
@@ -136,7 +136,7 @@
forwardThrowableFrom {
client.noteSyncOp()
- assertThat(noted.map { it.first.featureId to it.first.op })
+ assertThat(noted.map { it.first.attributionTag to it.first.op })
.containsExactly(null to OPSTR_COARSE_LOCATION)
assertThat(noted[0].second.map { it.methodName })
.contains("callApiThatNotesSyncOpAndCheckLog")
@@ -159,11 +159,14 @@
}
}
- override fun callApiThatNotesSyncOpWithFeatureAndCheckLog(client: IAppOpsUserClient) {
+ override fun callApiThatNotesSyncOpWithAttributionAndCheckLog(
+ client: IAppOpsUserClient
+ ) {
forwardThrowableFrom {
- client.noteSyncOpWithFeature(TEST_FEATURE_ID)
+ client.noteSyncOpWithAttribution(TEST_ATTRIBUTION_TAG)
- assertThat(noted.map { it.first.featureId }).containsExactly(TEST_FEATURE_ID)
+ assertThat(noted.map { it.first.attributionTag })
+ .containsExactly(TEST_ATTRIBUTION_TAG)
}
}
@@ -340,7 +343,7 @@
client.noteAsyncOp()
eventually {
- assertThat(asyncNoted.map { it.featureId to it.op })
+ assertThat(asyncNoted.map { it.attributionTag to it.op })
.containsExactly(null to OPSTR_COARSE_LOCATION)
}
assertThat(noted).isEmpty()
@@ -348,15 +351,15 @@
}
}
- override fun callApiThatNotesAsyncOpWithFeatureAndCheckLog(
+ override fun callApiThatNotesAsyncOpWithAttributionAndCheckLog(
client: IAppOpsUserClient
) {
forwardThrowableFrom {
- client.noteAsyncOpWithFeature(TEST_FEATURE_ID)
+ client.noteAsyncOpWithAttribution(TEST_ATTRIBUTION_TAG)
eventually {
- assertThat(asyncNoted.map { it.featureId })
- .containsExactly(TEST_FEATURE_ID)
+ assertThat(asyncNoted.map { it.attributionTag })
+ .containsExactly(TEST_ATTRIBUTION_TAG)
}
}
}
diff --git a/tests/tests/appop/AppToBlame1/AndroidManifest.xml b/tests/tests/appop/AppToBlame1/AndroidManifest.xml
index 55db16b..a8d3638 100644
--- a/tests/tests/appop/AppToBlame1/AndroidManifest.xml
+++ b/tests/tests/appop/AppToBlame1/AndroidManifest.xml
@@ -19,11 +19,11 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="android.app.appops.cts.apptoblame"
android:version="1">
- <feature android:featureId="feature1" android:label="@string/dummyLabel" />
- <feature android:featureId="feature2" android:label="@string/dummyLabel" />
- <feature android:featureId="feature3" android:label="@string/dummyLabel" />
- <feature android:featureId="feature4" android:label="@string/dummyLabel" />
- <feature android:featureId="feature5" android:label="@string/dummyLabel" />
+ <attribution android:tag="attribution1" android:label="@string/dummyLabel" />
+ <attribution android:tag="attribution2" android:label="@string/dummyLabel" />
+ <attribution android:tag="attribution3" android:label="@string/dummyLabel" />
+ <attribution android:tag="attribution4" android:label="@string/dummyLabel" />
+ <attribution android:tag="attribution5" android:label="@string/dummyLabel" />
<application />
diff --git a/tests/tests/appop/AppToBlame2/AndroidManifest.xml b/tests/tests/appop/AppToBlame2/AndroidManifest.xml
index 96a490c..ba13fd6 100644
--- a/tests/tests/appop/AppToBlame2/AndroidManifest.xml
+++ b/tests/tests/appop/AppToBlame2/AndroidManifest.xml
@@ -19,14 +19,14 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="android.app.appops.cts.apptoblame"
android:version="2">
- <feature android:featureId="feature1" android:label="@string/dummyLabel" />
- <feature android:featureId="feature6" android:label="@string/dummyLabel">
- <inherit-from android:featureId="feature2" />
- </feature>
- <feature android:featureId="feature7" android:label="@string/dummyLabel">
- <inherit-from android:featureId="feature4" />
- <inherit-from android:featureId="feature5" />
- </feature>
+ <attribution android:tag="attribution1" android:label="@string/dummyLabel" />
+ <attribution android:tag="attribution6" android:label="@string/dummyLabel">
+ <inherit-from android:tag="attribution2" />
+ </attribution>
+ <attribution android:tag="attribution7" android:label="@string/dummyLabel">
+ <inherit-from android:tag="attribution4" />
+ <inherit-from android:tag="attribution5" />
+ </attribution>
<application />
diff --git a/tests/tests/appop/AppToCollect/AndroidManifest.xml b/tests/tests/appop/AppToCollect/AndroidManifest.xml
index e67cb57..2a0d18d 100644
--- a/tests/tests/appop/AppToCollect/AndroidManifest.xml
+++ b/tests/tests/appop/AppToCollect/AndroidManifest.xml
@@ -19,7 +19,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="android.app.appops.cts.apptocollect"
android:version="1">
- <feature android:featureId="testFeature" android:label="@string/dummyLabel" />
+ <attribution android:tag="testAttribution" android:label="@string/dummyLabel" />
<uses-permission android:name="android.permission.READ_CONTACTS"></uses-permission>
diff --git a/tests/tests/appop/AppWithDuplicateFeature/Android.bp b/tests/tests/appop/AppWithAttributionInheritingFromExisting/Android.bp
similarity index 92%
copy from tests/tests/appop/AppWithDuplicateFeature/Android.bp
copy to tests/tests/appop/AppWithAttributionInheritingFromExisting/Android.bp
index a27dacb..2b07c3b 100644
--- a/tests/tests/appop/AppWithDuplicateFeature/Android.bp
+++ b/tests/tests/appop/AppWithAttributionInheritingFromExisting/Android.bp
@@ -13,7 +13,7 @@
// limitations under the License.
android_test_helper_app {
- name: "AppWithDuplicateFeature",
+ name: "AppWithAttributionInheritingFromExisting",
test_suites: [
"cts",
diff --git a/tests/tests/appop/AppWithFeatureInheritingFromExisting/AndroidManifest.xml b/tests/tests/appop/AppWithAttributionInheritingFromExisting/AndroidManifest.xml
similarity index 72%
rename from tests/tests/appop/AppWithFeatureInheritingFromExisting/AndroidManifest.xml
rename to tests/tests/appop/AppWithAttributionInheritingFromExisting/AndroidManifest.xml
index eb097ef..6b1798b 100644
--- a/tests/tests/appop/AppWithFeatureInheritingFromExisting/AndroidManifest.xml
+++ b/tests/tests/appop/AppWithAttributionInheritingFromExisting/AndroidManifest.xml
@@ -17,11 +17,11 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.app.appops.cts.appwithfeatureinheritingfromexisting">
- <feature android:featureId="feature1" android:label="@string/dummyLabel" />
- <feature android:featureId="feature2" android:label="@string/dummyLabel">
- <inherit-from android:featureId="feature1" />
- </feature>
+ package="android.app.appops.cts.appwithattributioninheritingfromexisting">
+ <attribution android:tag="attribution" android:label="@string/dummyLabel" />
+ <attribution android:tag="attribution2" android:label="@string/dummyLabel">
+ <inherit-from android:tag="attribution" />
+ </attribution>
<application />
diff --git a/tests/tests/appop/AppWithFeatureInheritingFromExisting/res/values/strings.xml b/tests/tests/appop/AppWithAttributionInheritingFromExisting/res/values/strings.xml
similarity index 100%
rename from tests/tests/appop/AppWithFeatureInheritingFromExisting/res/values/strings.xml
rename to tests/tests/appop/AppWithAttributionInheritingFromExisting/res/values/strings.xml
diff --git a/tests/tests/appop/AppWithDuplicateFeature/Android.bp b/tests/tests/appop/AppWithAttributionInheritingFromSameAsOther/Android.bp
similarity index 92%
copy from tests/tests/appop/AppWithDuplicateFeature/Android.bp
copy to tests/tests/appop/AppWithAttributionInheritingFromSameAsOther/Android.bp
index a27dacb..7de79e5 100644
--- a/tests/tests/appop/AppWithDuplicateFeature/Android.bp
+++ b/tests/tests/appop/AppWithAttributionInheritingFromSameAsOther/Android.bp
@@ -13,7 +13,7 @@
// limitations under the License.
android_test_helper_app {
- name: "AppWithDuplicateFeature",
+ name: "AppWithAttributionInheritingFromSameAsOther",
test_suites: [
"cts",
diff --git a/tests/tests/appop/AppWithDuplicateFeature/AndroidManifest.xml b/tests/tests/appop/AppWithAttributionInheritingFromSameAsOther/AndroidManifest.xml
similarity index 67%
copy from tests/tests/appop/AppWithDuplicateFeature/AndroidManifest.xml
copy to tests/tests/appop/AppWithAttributionInheritingFromSameAsOther/AndroidManifest.xml
index b7b5297..fcf47a5 100644
--- a/tests/tests/appop/AppWithDuplicateFeature/AndroidManifest.xml
+++ b/tests/tests/appop/AppWithAttributionInheritingFromSameAsOther/AndroidManifest.xml
@@ -17,9 +17,13 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.app.appops.cts.appwithduplicatefeature">
- <feature android:featureId="feature1" android:label="@string/dummyLabel" />
- <feature android:featureId="feature1" android:label="@string/dummyLabel" />
+ package="android.app.appops.cts.appwithattributioninheritingfromsameasother">
+ <attribution android:tag="attribution1" android:label="@string/dummyLabel">
+ <inherit-from android:tag="attribution3" />
+ </attribution>
+ <attribution android:tag="attribution2" android:label="@string/dummyLabel">
+ <inherit-from android:tag="attribution3" />
+ </attribution>
<application />
diff --git a/tests/tests/appop/AppWithFeatureInheritingFromSameAsOther/res/values/strings.xml b/tests/tests/appop/AppWithAttributionInheritingFromSameAsOther/res/values/strings.xml
similarity index 100%
rename from tests/tests/appop/AppWithFeatureInheritingFromSameAsOther/res/values/strings.xml
rename to tests/tests/appop/AppWithAttributionInheritingFromSameAsOther/res/values/strings.xml
diff --git a/tests/tests/appop/AppWithDuplicateFeature/Android.bp b/tests/tests/appop/AppWithAttributionInheritingFromSelf/Android.bp
similarity index 93%
copy from tests/tests/appop/AppWithDuplicateFeature/Android.bp
copy to tests/tests/appop/AppWithAttributionInheritingFromSelf/Android.bp
index a27dacb..4a6e524 100644
--- a/tests/tests/appop/AppWithDuplicateFeature/Android.bp
+++ b/tests/tests/appop/AppWithAttributionInheritingFromSelf/Android.bp
@@ -13,7 +13,7 @@
// limitations under the License.
android_test_helper_app {
- name: "AppWithDuplicateFeature",
+ name: "AppWithAttributionInheritingFromSelf",
test_suites: [
"cts",
diff --git a/tests/tests/appop/AppWithDuplicateFeature/AndroidManifest.xml b/tests/tests/appop/AppWithAttributionInheritingFromSelf/AndroidManifest.xml
similarity index 77%
copy from tests/tests/appop/AppWithDuplicateFeature/AndroidManifest.xml
copy to tests/tests/appop/AppWithAttributionInheritingFromSelf/AndroidManifest.xml
index b7b5297..3cb4712 100644
--- a/tests/tests/appop/AppWithDuplicateFeature/AndroidManifest.xml
+++ b/tests/tests/appop/AppWithAttributionInheritingFromSelf/AndroidManifest.xml
@@ -17,9 +17,10 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.app.appops.cts.appwithduplicatefeature">
- <feature android:featureId="feature1" android:label="@string/dummyLabel" />
- <feature android:featureId="feature1" android:label="@string/dummyLabel" />
+ package="android.app.appops.cts.appwithattributioninheritingfromself">
+ <attribution android:tag="attribution1" android:label="@string/dummyLabel">
+ <inherit-from android:tag="attribution1" />
+ </attribution>
<application />
diff --git a/tests/tests/appop/AppWithFeatureInheritingFromSelf/res/values/strings.xml b/tests/tests/appop/AppWithAttributionInheritingFromSelf/res/values/strings.xml
similarity index 100%
rename from tests/tests/appop/AppWithFeatureInheritingFromSelf/res/values/strings.xml
rename to tests/tests/appop/AppWithAttributionInheritingFromSelf/res/values/strings.xml
diff --git a/tests/tests/appop/AppWithDuplicateFeature/Android.bp b/tests/tests/appop/AppWithDuplicateAttribution/Android.bp
similarity index 94%
rename from tests/tests/appop/AppWithDuplicateFeature/Android.bp
rename to tests/tests/appop/AppWithDuplicateAttribution/Android.bp
index a27dacb..a4b1272 100644
--- a/tests/tests/appop/AppWithDuplicateFeature/Android.bp
+++ b/tests/tests/appop/AppWithDuplicateAttribution/Android.bp
@@ -13,7 +13,7 @@
// limitations under the License.
android_test_helper_app {
- name: "AppWithDuplicateFeature",
+ name: "AppWithDuplicateAttribution",
test_suites: [
"cts",
diff --git a/tests/tests/appop/AppWithDuplicateFeature/AndroidManifest.xml b/tests/tests/appop/AppWithDuplicateAttribution/AndroidManifest.xml
similarity index 77%
rename from tests/tests/appop/AppWithDuplicateFeature/AndroidManifest.xml
rename to tests/tests/appop/AppWithDuplicateAttribution/AndroidManifest.xml
index b7b5297..55b0ddb 100644
--- a/tests/tests/appop/AppWithDuplicateFeature/AndroidManifest.xml
+++ b/tests/tests/appop/AppWithDuplicateAttribution/AndroidManifest.xml
@@ -17,9 +17,9 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.app.appops.cts.appwithduplicatefeature">
- <feature android:featureId="feature1" android:label="@string/dummyLabel" />
- <feature android:featureId="feature1" android:label="@string/dummyLabel" />
+ package="android.app.appops.cts.appwithduplicateattribution">
+ <attribution android:tag="attribution1" android:label="@string/dummyLabel" />
+ <attribution android:tag="attribution1" android:label="@string/dummyLabel" />
<application />
diff --git a/tests/tests/appop/AppWithDuplicateFeature/res/values/strings.xml b/tests/tests/appop/AppWithDuplicateAttribution/res/values/strings.xml
similarity index 100%
rename from tests/tests/appop/AppWithDuplicateFeature/res/values/strings.xml
rename to tests/tests/appop/AppWithDuplicateAttribution/res/values/strings.xml
diff --git a/tests/tests/appop/AppWithFeatureInheritingFromExisting/Android.bp b/tests/tests/appop/AppWithFeatureInheritingFromExisting/Android.bp
deleted file mode 100644
index fd498d7..0000000
--- a/tests/tests/appop/AppWithFeatureInheritingFromExisting/Android.bp
+++ /dev/null
@@ -1,23 +0,0 @@
-// 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_helper_app {
- name: "AppWithFeatureInheritingFromExisting",
-
- test_suites: [
- "cts",
- "vts",
- "general-tests",
- ]
-}
\ No newline at end of file
diff --git a/tests/tests/appop/AppWithFeatureInheritingFromSameAsOther/Android.bp b/tests/tests/appop/AppWithFeatureInheritingFromSameAsOther/Android.bp
deleted file mode 100644
index d358ae34..0000000
--- a/tests/tests/appop/AppWithFeatureInheritingFromSameAsOther/Android.bp
+++ /dev/null
@@ -1,23 +0,0 @@
-// 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_helper_app {
- name: "AppWithFeatureInheritingFromSameAsOther",
-
- test_suites: [
- "cts",
- "vts",
- "general-tests",
- ]
-}
\ No newline at end of file
diff --git a/tests/tests/appop/AppWithFeatureInheritingFromSameAsOther/AndroidManifest.xml b/tests/tests/appop/AppWithFeatureInheritingFromSameAsOther/AndroidManifest.xml
deleted file mode 100644
index 5af9edc..0000000
--- a/tests/tests/appop/AppWithFeatureInheritingFromSameAsOther/AndroidManifest.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?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.app.appops.cts.appwithfeatureinheritingfromsameasother">
- <feature android:featureId="feature1" android:label="@string/dummyLabel">
- <inherit-from android:featureId="feature3" />
- </feature>
- <feature android:featureId="feature2" android:label="@string/dummyLabel">
- <inherit-from android:featureId="feature3" />
- </feature>
-
- <application />
-
-</manifest>
diff --git a/tests/tests/appop/AppWithFeatureInheritingFromSelf/Android.bp b/tests/tests/appop/AppWithFeatureInheritingFromSelf/Android.bp
deleted file mode 100644
index 4c47869..0000000
--- a/tests/tests/appop/AppWithFeatureInheritingFromSelf/Android.bp
+++ /dev/null
@@ -1,23 +0,0 @@
-// 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_helper_app {
- name: "AppWithFeatureInheritingFromSelf",
-
- test_suites: [
- "cts",
- "vts",
- "general-tests",
- ]
-}
\ No newline at end of file
diff --git a/tests/tests/appop/AppWithFeatureInheritingFromSelf/AndroidManifest.xml b/tests/tests/appop/AppWithFeatureInheritingFromSelf/AndroidManifest.xml
deleted file mode 100644
index ff7e198..0000000
--- a/tests/tests/appop/AppWithFeatureInheritingFromSelf/AndroidManifest.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?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.app.appops.cts.appwithfeatureinheritingfromself">
- <feature android:featureId="feature1" android:label="@string/dummyLabel">
- <inherit-from android:featureId="feature1" />
- </feature>
-
- <application />
-
-</manifest>
diff --git a/tests/tests/appop/AppWithLongFeatureId/Android.bp b/tests/tests/appop/AppWithLongAttributionTag/Android.bp
similarity index 94%
copy from tests/tests/appop/AppWithLongFeatureId/Android.bp
copy to tests/tests/appop/AppWithLongAttributionTag/Android.bp
index e0034f0..5ee3f02 100644
--- a/tests/tests/appop/AppWithLongFeatureId/Android.bp
+++ b/tests/tests/appop/AppWithLongAttributionTag/Android.bp
@@ -13,7 +13,7 @@
// limitations under the License.
android_test_helper_app {
- name: "AppWithLongFeatureIdFeature",
+ name: "AppWithLongAttributionTag",
test_suites: [
"cts",
diff --git a/tests/tests/appop/AppWithLongFeatureId/AndroidManifest.xml b/tests/tests/appop/AppWithLongAttributionTag/AndroidManifest.xml
similarity index 80%
rename from tests/tests/appop/AppWithLongFeatureId/AndroidManifest.xml
rename to tests/tests/appop/AppWithLongAttributionTag/AndroidManifest.xml
index 17d10e9..e08a32d 100644
--- a/tests/tests/appop/AppWithLongFeatureId/AndroidManifest.xml
+++ b/tests/tests/appop/AppWithLongAttributionTag/AndroidManifest.xml
@@ -17,8 +17,8 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.app.appops.cts.appwithlongfeatureId">
- <feature android:featureId="1xxxx_xxxx2xxxx_xxxx3xxxx_xxxx4xxxx_xxxx5xxxx_xxxxB" android:label="@string/dummyLabel" />
+ package="android.app.appops.cts.appwithlongattributiontag">
+ <attribution android:tag="1xxxx_xxxx2xxxx_xxxx3xxxx_xxxx4xxxx_xxxx5xxxx_xxxxB" android:label="@string/dummyLabel" />
<application />
diff --git a/tests/tests/appop/AppWithLongFeatureId/res/values/strings.xml b/tests/tests/appop/AppWithLongAttributionTag/res/values/strings.xml
similarity index 100%
rename from tests/tests/appop/AppWithLongFeatureId/res/values/strings.xml
rename to tests/tests/appop/AppWithLongAttributionTag/res/values/strings.xml
diff --git a/tests/tests/appop/AppWithLongFeatureId/Android.bp b/tests/tests/appop/AppWithTooManyAttributions/Android.bp
similarity index 94%
rename from tests/tests/appop/AppWithLongFeatureId/Android.bp
rename to tests/tests/appop/AppWithTooManyAttributions/Android.bp
index e0034f0..80b1bd3 100644
--- a/tests/tests/appop/AppWithLongFeatureId/Android.bp
+++ b/tests/tests/appop/AppWithTooManyAttributions/Android.bp
@@ -13,7 +13,7 @@
// limitations under the License.
android_test_helper_app {
- name: "AppWithLongFeatureIdFeature",
+ name: "AppWithTooManyAttributions",
test_suites: [
"cts",
diff --git a/tests/tests/appop/AppWithTooManyAttributions/AndroidManifest.xml b/tests/tests/appop/AppWithTooManyAttributions/AndroidManifest.xml
new file mode 100644
index 0000000..debdb8e
--- /dev/null
+++ b/tests/tests/appop/AppWithTooManyAttributions/AndroidManifest.xml
@@ -0,0 +1,1028 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ ~ Copyright (C) 2020 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.app.appops.cts.appwithtoomanyattributions">
+
+ <!-- 1000 attributions are allowed -->
+ <attribution android:tag="f0" android:label="@string/dummyLabel" />
+ <attribution android:tag="f1" android:label="@string/dummyLabel" />
+ <attribution android:tag="f2" android:label="@string/dummyLabel" />
+ <attribution android:tag="f3" android:label="@string/dummyLabel" />
+ <attribution android:tag="f4" android:label="@string/dummyLabel" />
+ <attribution android:tag="f5" android:label="@string/dummyLabel" />
+ <attribution android:tag="f6" android:label="@string/dummyLabel" />
+ <attribution android:tag="f7" android:label="@string/dummyLabel" />
+ <attribution android:tag="f8" android:label="@string/dummyLabel" />
+ <attribution android:tag="f9" android:label="@string/dummyLabel" />
+ <attribution android:tag="f10" android:label="@string/dummyLabel" />
+ <attribution android:tag="f11" android:label="@string/dummyLabel" />
+ <attribution android:tag="f12" android:label="@string/dummyLabel" />
+ <attribution android:tag="f13" android:label="@string/dummyLabel" />
+ <attribution android:tag="f14" android:label="@string/dummyLabel" />
+ <attribution android:tag="f15" android:label="@string/dummyLabel" />
+ <attribution android:tag="f16" android:label="@string/dummyLabel" />
+ <attribution android:tag="f17" android:label="@string/dummyLabel" />
+ <attribution android:tag="f18" android:label="@string/dummyLabel" />
+ <attribution android:tag="f19" android:label="@string/dummyLabel" />
+ <attribution android:tag="f20" android:label="@string/dummyLabel" />
+ <attribution android:tag="f21" android:label="@string/dummyLabel" />
+ <attribution android:tag="f22" android:label="@string/dummyLabel" />
+ <attribution android:tag="f23" android:label="@string/dummyLabel" />
+ <attribution android:tag="f24" android:label="@string/dummyLabel" />
+ <attribution android:tag="f25" android:label="@string/dummyLabel" />
+ <attribution android:tag="f26" android:label="@string/dummyLabel" />
+ <attribution android:tag="f27" android:label="@string/dummyLabel" />
+ <attribution android:tag="f28" android:label="@string/dummyLabel" />
+ <attribution android:tag="f29" android:label="@string/dummyLabel" />
+ <attribution android:tag="f30" android:label="@string/dummyLabel" />
+ <attribution android:tag="f31" android:label="@string/dummyLabel" />
+ <attribution android:tag="f32" android:label="@string/dummyLabel" />
+ <attribution android:tag="f33" android:label="@string/dummyLabel" />
+ <attribution android:tag="f34" android:label="@string/dummyLabel" />
+ <attribution android:tag="f35" android:label="@string/dummyLabel" />
+ <attribution android:tag="f36" android:label="@string/dummyLabel" />
+ <attribution android:tag="f37" android:label="@string/dummyLabel" />
+ <attribution android:tag="f38" android:label="@string/dummyLabel" />
+ <attribution android:tag="f39" android:label="@string/dummyLabel" />
+ <attribution android:tag="f40" android:label="@string/dummyLabel" />
+ <attribution android:tag="f41" android:label="@string/dummyLabel" />
+ <attribution android:tag="f42" android:label="@string/dummyLabel" />
+ <attribution android:tag="f43" android:label="@string/dummyLabel" />
+ <attribution android:tag="f44" android:label="@string/dummyLabel" />
+ <attribution android:tag="f45" android:label="@string/dummyLabel" />
+ <attribution android:tag="f46" android:label="@string/dummyLabel" />
+ <attribution android:tag="f47" android:label="@string/dummyLabel" />
+ <attribution android:tag="f48" android:label="@string/dummyLabel" />
+ <attribution android:tag="f49" android:label="@string/dummyLabel" />
+ <attribution android:tag="f50" android:label="@string/dummyLabel" />
+ <attribution android:tag="f51" android:label="@string/dummyLabel" />
+ <attribution android:tag="f52" android:label="@string/dummyLabel" />
+ <attribution android:tag="f53" android:label="@string/dummyLabel" />
+ <attribution android:tag="f54" android:label="@string/dummyLabel" />
+ <attribution android:tag="f55" android:label="@string/dummyLabel" />
+ <attribution android:tag="f56" android:label="@string/dummyLabel" />
+ <attribution android:tag="f57" android:label="@string/dummyLabel" />
+ <attribution android:tag="f58" android:label="@string/dummyLabel" />
+ <attribution android:tag="f59" android:label="@string/dummyLabel" />
+ <attribution android:tag="f60" android:label="@string/dummyLabel" />
+ <attribution android:tag="f61" android:label="@string/dummyLabel" />
+ <attribution android:tag="f62" android:label="@string/dummyLabel" />
+ <attribution android:tag="f63" android:label="@string/dummyLabel" />
+ <attribution android:tag="f64" android:label="@string/dummyLabel" />
+ <attribution android:tag="f65" android:label="@string/dummyLabel" />
+ <attribution android:tag="f66" android:label="@string/dummyLabel" />
+ <attribution android:tag="f67" android:label="@string/dummyLabel" />
+ <attribution android:tag="f68" android:label="@string/dummyLabel" />
+ <attribution android:tag="f69" android:label="@string/dummyLabel" />
+ <attribution android:tag="f70" android:label="@string/dummyLabel" />
+ <attribution android:tag="f71" android:label="@string/dummyLabel" />
+ <attribution android:tag="f72" android:label="@string/dummyLabel" />
+ <attribution android:tag="f73" android:label="@string/dummyLabel" />
+ <attribution android:tag="f74" android:label="@string/dummyLabel" />
+ <attribution android:tag="f75" android:label="@string/dummyLabel" />
+ <attribution android:tag="f76" android:label="@string/dummyLabel" />
+ <attribution android:tag="f77" android:label="@string/dummyLabel" />
+ <attribution android:tag="f78" android:label="@string/dummyLabel" />
+ <attribution android:tag="f79" android:label="@string/dummyLabel" />
+ <attribution android:tag="f80" android:label="@string/dummyLabel" />
+ <attribution android:tag="f81" android:label="@string/dummyLabel" />
+ <attribution android:tag="f82" android:label="@string/dummyLabel" />
+ <attribution android:tag="f83" android:label="@string/dummyLabel" />
+ <attribution android:tag="f84" android:label="@string/dummyLabel" />
+ <attribution android:tag="f85" android:label="@string/dummyLabel" />
+ <attribution android:tag="f86" android:label="@string/dummyLabel" />
+ <attribution android:tag="f87" android:label="@string/dummyLabel" />
+ <attribution android:tag="f88" android:label="@string/dummyLabel" />
+ <attribution android:tag="f89" android:label="@string/dummyLabel" />
+ <attribution android:tag="f90" android:label="@string/dummyLabel" />
+ <attribution android:tag="f91" android:label="@string/dummyLabel" />
+ <attribution android:tag="f92" android:label="@string/dummyLabel" />
+ <attribution android:tag="f93" android:label="@string/dummyLabel" />
+ <attribution android:tag="f94" android:label="@string/dummyLabel" />
+ <attribution android:tag="f95" android:label="@string/dummyLabel" />
+ <attribution android:tag="f96" android:label="@string/dummyLabel" />
+ <attribution android:tag="f97" android:label="@string/dummyLabel" />
+ <attribution android:tag="f98" android:label="@string/dummyLabel" />
+ <attribution android:tag="f99" android:label="@string/dummyLabel" />
+ <attribution android:tag="f100" android:label="@string/dummyLabel" />
+ <attribution android:tag="f101" android:label="@string/dummyLabel" />
+ <attribution android:tag="f102" android:label="@string/dummyLabel" />
+ <attribution android:tag="f103" android:label="@string/dummyLabel" />
+ <attribution android:tag="f104" android:label="@string/dummyLabel" />
+ <attribution android:tag="f105" android:label="@string/dummyLabel" />
+ <attribution android:tag="f106" android:label="@string/dummyLabel" />
+ <attribution android:tag="f107" android:label="@string/dummyLabel" />
+ <attribution android:tag="f108" android:label="@string/dummyLabel" />
+ <attribution android:tag="f109" android:label="@string/dummyLabel" />
+ <attribution android:tag="f110" android:label="@string/dummyLabel" />
+ <attribution android:tag="f111" android:label="@string/dummyLabel" />
+ <attribution android:tag="f112" android:label="@string/dummyLabel" />
+ <attribution android:tag="f113" android:label="@string/dummyLabel" />
+ <attribution android:tag="f114" android:label="@string/dummyLabel" />
+ <attribution android:tag="f115" android:label="@string/dummyLabel" />
+ <attribution android:tag="f116" android:label="@string/dummyLabel" />
+ <attribution android:tag="f117" android:label="@string/dummyLabel" />
+ <attribution android:tag="f118" android:label="@string/dummyLabel" />
+ <attribution android:tag="f119" android:label="@string/dummyLabel" />
+ <attribution android:tag="f120" android:label="@string/dummyLabel" />
+ <attribution android:tag="f121" android:label="@string/dummyLabel" />
+ <attribution android:tag="f122" android:label="@string/dummyLabel" />
+ <attribution android:tag="f123" android:label="@string/dummyLabel" />
+ <attribution android:tag="f124" android:label="@string/dummyLabel" />
+ <attribution android:tag="f125" android:label="@string/dummyLabel" />
+ <attribution android:tag="f126" android:label="@string/dummyLabel" />
+ <attribution android:tag="f127" android:label="@string/dummyLabel" />
+ <attribution android:tag="f128" android:label="@string/dummyLabel" />
+ <attribution android:tag="f129" android:label="@string/dummyLabel" />
+ <attribution android:tag="f130" android:label="@string/dummyLabel" />
+ <attribution android:tag="f131" android:label="@string/dummyLabel" />
+ <attribution android:tag="f132" android:label="@string/dummyLabel" />
+ <attribution android:tag="f133" android:label="@string/dummyLabel" />
+ <attribution android:tag="f134" android:label="@string/dummyLabel" />
+ <attribution android:tag="f135" android:label="@string/dummyLabel" />
+ <attribution android:tag="f136" android:label="@string/dummyLabel" />
+ <attribution android:tag="f137" android:label="@string/dummyLabel" />
+ <attribution android:tag="f138" android:label="@string/dummyLabel" />
+ <attribution android:tag="f139" android:label="@string/dummyLabel" />
+ <attribution android:tag="f140" android:label="@string/dummyLabel" />
+ <attribution android:tag="f141" android:label="@string/dummyLabel" />
+ <attribution android:tag="f142" android:label="@string/dummyLabel" />
+ <attribution android:tag="f143" android:label="@string/dummyLabel" />
+ <attribution android:tag="f144" android:label="@string/dummyLabel" />
+ <attribution android:tag="f145" android:label="@string/dummyLabel" />
+ <attribution android:tag="f146" android:label="@string/dummyLabel" />
+ <attribution android:tag="f147" android:label="@string/dummyLabel" />
+ <attribution android:tag="f148" android:label="@string/dummyLabel" />
+ <attribution android:tag="f149" android:label="@string/dummyLabel" />
+ <attribution android:tag="f150" android:label="@string/dummyLabel" />
+ <attribution android:tag="f151" android:label="@string/dummyLabel" />
+ <attribution android:tag="f152" android:label="@string/dummyLabel" />
+ <attribution android:tag="f153" android:label="@string/dummyLabel" />
+ <attribution android:tag="f154" android:label="@string/dummyLabel" />
+ <attribution android:tag="f155" android:label="@string/dummyLabel" />
+ <attribution android:tag="f156" android:label="@string/dummyLabel" />
+ <attribution android:tag="f157" android:label="@string/dummyLabel" />
+ <attribution android:tag="f158" android:label="@string/dummyLabel" />
+ <attribution android:tag="f159" android:label="@string/dummyLabel" />
+ <attribution android:tag="f160" android:label="@string/dummyLabel" />
+ <attribution android:tag="f161" android:label="@string/dummyLabel" />
+ <attribution android:tag="f162" android:label="@string/dummyLabel" />
+ <attribution android:tag="f163" android:label="@string/dummyLabel" />
+ <attribution android:tag="f164" android:label="@string/dummyLabel" />
+ <attribution android:tag="f165" android:label="@string/dummyLabel" />
+ <attribution android:tag="f166" android:label="@string/dummyLabel" />
+ <attribution android:tag="f167" android:label="@string/dummyLabel" />
+ <attribution android:tag="f168" android:label="@string/dummyLabel" />
+ <attribution android:tag="f169" android:label="@string/dummyLabel" />
+ <attribution android:tag="f170" android:label="@string/dummyLabel" />
+ <attribution android:tag="f171" android:label="@string/dummyLabel" />
+ <attribution android:tag="f172" android:label="@string/dummyLabel" />
+ <attribution android:tag="f173" android:label="@string/dummyLabel" />
+ <attribution android:tag="f174" android:label="@string/dummyLabel" />
+ <attribution android:tag="f175" android:label="@string/dummyLabel" />
+ <attribution android:tag="f176" android:label="@string/dummyLabel" />
+ <attribution android:tag="f177" android:label="@string/dummyLabel" />
+ <attribution android:tag="f178" android:label="@string/dummyLabel" />
+ <attribution android:tag="f179" android:label="@string/dummyLabel" />
+ <attribution android:tag="f180" android:label="@string/dummyLabel" />
+ <attribution android:tag="f181" android:label="@string/dummyLabel" />
+ <attribution android:tag="f182" android:label="@string/dummyLabel" />
+ <attribution android:tag="f183" android:label="@string/dummyLabel" />
+ <attribution android:tag="f184" android:label="@string/dummyLabel" />
+ <attribution android:tag="f185" android:label="@string/dummyLabel" />
+ <attribution android:tag="f186" android:label="@string/dummyLabel" />
+ <attribution android:tag="f187" android:label="@string/dummyLabel" />
+ <attribution android:tag="f188" android:label="@string/dummyLabel" />
+ <attribution android:tag="f189" android:label="@string/dummyLabel" />
+ <attribution android:tag="f190" android:label="@string/dummyLabel" />
+ <attribution android:tag="f191" android:label="@string/dummyLabel" />
+ <attribution android:tag="f192" android:label="@string/dummyLabel" />
+ <attribution android:tag="f193" android:label="@string/dummyLabel" />
+ <attribution android:tag="f194" android:label="@string/dummyLabel" />
+ <attribution android:tag="f195" android:label="@string/dummyLabel" />
+ <attribution android:tag="f196" android:label="@string/dummyLabel" />
+ <attribution android:tag="f197" android:label="@string/dummyLabel" />
+ <attribution android:tag="f198" android:label="@string/dummyLabel" />
+ <attribution android:tag="f199" android:label="@string/dummyLabel" />
+ <attribution android:tag="f200" android:label="@string/dummyLabel" />
+ <attribution android:tag="f201" android:label="@string/dummyLabel" />
+ <attribution android:tag="f202" android:label="@string/dummyLabel" />
+ <attribution android:tag="f203" android:label="@string/dummyLabel" />
+ <attribution android:tag="f204" android:label="@string/dummyLabel" />
+ <attribution android:tag="f205" android:label="@string/dummyLabel" />
+ <attribution android:tag="f206" android:label="@string/dummyLabel" />
+ <attribution android:tag="f207" android:label="@string/dummyLabel" />
+ <attribution android:tag="f208" android:label="@string/dummyLabel" />
+ <attribution android:tag="f209" android:label="@string/dummyLabel" />
+ <attribution android:tag="f210" android:label="@string/dummyLabel" />
+ <attribution android:tag="f211" android:label="@string/dummyLabel" />
+ <attribution android:tag="f212" android:label="@string/dummyLabel" />
+ <attribution android:tag="f213" android:label="@string/dummyLabel" />
+ <attribution android:tag="f214" android:label="@string/dummyLabel" />
+ <attribution android:tag="f215" android:label="@string/dummyLabel" />
+ <attribution android:tag="f216" android:label="@string/dummyLabel" />
+ <attribution android:tag="f217" android:label="@string/dummyLabel" />
+ <attribution android:tag="f218" android:label="@string/dummyLabel" />
+ <attribution android:tag="f219" android:label="@string/dummyLabel" />
+ <attribution android:tag="f220" android:label="@string/dummyLabel" />
+ <attribution android:tag="f221" android:label="@string/dummyLabel" />
+ <attribution android:tag="f222" android:label="@string/dummyLabel" />
+ <attribution android:tag="f223" android:label="@string/dummyLabel" />
+ <attribution android:tag="f224" android:label="@string/dummyLabel" />
+ <attribution android:tag="f225" android:label="@string/dummyLabel" />
+ <attribution android:tag="f226" android:label="@string/dummyLabel" />
+ <attribution android:tag="f227" android:label="@string/dummyLabel" />
+ <attribution android:tag="f228" android:label="@string/dummyLabel" />
+ <attribution android:tag="f229" android:label="@string/dummyLabel" />
+ <attribution android:tag="f230" android:label="@string/dummyLabel" />
+ <attribution android:tag="f231" android:label="@string/dummyLabel" />
+ <attribution android:tag="f232" android:label="@string/dummyLabel" />
+ <attribution android:tag="f233" android:label="@string/dummyLabel" />
+ <attribution android:tag="f234" android:label="@string/dummyLabel" />
+ <attribution android:tag="f235" android:label="@string/dummyLabel" />
+ <attribution android:tag="f236" android:label="@string/dummyLabel" />
+ <attribution android:tag="f237" android:label="@string/dummyLabel" />
+ <attribution android:tag="f238" android:label="@string/dummyLabel" />
+ <attribution android:tag="f239" android:label="@string/dummyLabel" />
+ <attribution android:tag="f240" android:label="@string/dummyLabel" />
+ <attribution android:tag="f241" android:label="@string/dummyLabel" />
+ <attribution android:tag="f242" android:label="@string/dummyLabel" />
+ <attribution android:tag="f243" android:label="@string/dummyLabel" />
+ <attribution android:tag="f244" android:label="@string/dummyLabel" />
+ <attribution android:tag="f245" android:label="@string/dummyLabel" />
+ <attribution android:tag="f246" android:label="@string/dummyLabel" />
+ <attribution android:tag="f247" android:label="@string/dummyLabel" />
+ <attribution android:tag="f248" android:label="@string/dummyLabel" />
+ <attribution android:tag="f249" android:label="@string/dummyLabel" />
+ <attribution android:tag="f250" android:label="@string/dummyLabel" />
+ <attribution android:tag="f251" android:label="@string/dummyLabel" />
+ <attribution android:tag="f252" android:label="@string/dummyLabel" />
+ <attribution android:tag="f253" android:label="@string/dummyLabel" />
+ <attribution android:tag="f254" android:label="@string/dummyLabel" />
+ <attribution android:tag="f255" android:label="@string/dummyLabel" />
+ <attribution android:tag="f256" android:label="@string/dummyLabel" />
+ <attribution android:tag="f257" android:label="@string/dummyLabel" />
+ <attribution android:tag="f258" android:label="@string/dummyLabel" />
+ <attribution android:tag="f259" android:label="@string/dummyLabel" />
+ <attribution android:tag="f260" android:label="@string/dummyLabel" />
+ <attribution android:tag="f261" android:label="@string/dummyLabel" />
+ <attribution android:tag="f262" android:label="@string/dummyLabel" />
+ <attribution android:tag="f263" android:label="@string/dummyLabel" />
+ <attribution android:tag="f264" android:label="@string/dummyLabel" />
+ <attribution android:tag="f265" android:label="@string/dummyLabel" />
+ <attribution android:tag="f266" android:label="@string/dummyLabel" />
+ <attribution android:tag="f267" android:label="@string/dummyLabel" />
+ <attribution android:tag="f268" android:label="@string/dummyLabel" />
+ <attribution android:tag="f269" android:label="@string/dummyLabel" />
+ <attribution android:tag="f270" android:label="@string/dummyLabel" />
+ <attribution android:tag="f271" android:label="@string/dummyLabel" />
+ <attribution android:tag="f272" android:label="@string/dummyLabel" />
+ <attribution android:tag="f273" android:label="@string/dummyLabel" />
+ <attribution android:tag="f274" android:label="@string/dummyLabel" />
+ <attribution android:tag="f275" android:label="@string/dummyLabel" />
+ <attribution android:tag="f276" android:label="@string/dummyLabel" />
+ <attribution android:tag="f277" android:label="@string/dummyLabel" />
+ <attribution android:tag="f278" android:label="@string/dummyLabel" />
+ <attribution android:tag="f279" android:label="@string/dummyLabel" />
+ <attribution android:tag="f280" android:label="@string/dummyLabel" />
+ <attribution android:tag="f281" android:label="@string/dummyLabel" />
+ <attribution android:tag="f282" android:label="@string/dummyLabel" />
+ <attribution android:tag="f283" android:label="@string/dummyLabel" />
+ <attribution android:tag="f284" android:label="@string/dummyLabel" />
+ <attribution android:tag="f285" android:label="@string/dummyLabel" />
+ <attribution android:tag="f286" android:label="@string/dummyLabel" />
+ <attribution android:tag="f287" android:label="@string/dummyLabel" />
+ <attribution android:tag="f288" android:label="@string/dummyLabel" />
+ <attribution android:tag="f289" android:label="@string/dummyLabel" />
+ <attribution android:tag="f290" android:label="@string/dummyLabel" />
+ <attribution android:tag="f291" android:label="@string/dummyLabel" />
+ <attribution android:tag="f292" android:label="@string/dummyLabel" />
+ <attribution android:tag="f293" android:label="@string/dummyLabel" />
+ <attribution android:tag="f294" android:label="@string/dummyLabel" />
+ <attribution android:tag="f295" android:label="@string/dummyLabel" />
+ <attribution android:tag="f296" android:label="@string/dummyLabel" />
+ <attribution android:tag="f297" android:label="@string/dummyLabel" />
+ <attribution android:tag="f298" android:label="@string/dummyLabel" />
+ <attribution android:tag="f299" android:label="@string/dummyLabel" />
+ <attribution android:tag="f300" android:label="@string/dummyLabel" />
+ <attribution android:tag="f301" android:label="@string/dummyLabel" />
+ <attribution android:tag="f302" android:label="@string/dummyLabel" />
+ <attribution android:tag="f303" android:label="@string/dummyLabel" />
+ <attribution android:tag="f304" android:label="@string/dummyLabel" />
+ <attribution android:tag="f305" android:label="@string/dummyLabel" />
+ <attribution android:tag="f306" android:label="@string/dummyLabel" />
+ <attribution android:tag="f307" android:label="@string/dummyLabel" />
+ <attribution android:tag="f308" android:label="@string/dummyLabel" />
+ <attribution android:tag="f309" android:label="@string/dummyLabel" />
+ <attribution android:tag="f310" android:label="@string/dummyLabel" />
+ <attribution android:tag="f311" android:label="@string/dummyLabel" />
+ <attribution android:tag="f312" android:label="@string/dummyLabel" />
+ <attribution android:tag="f313" android:label="@string/dummyLabel" />
+ <attribution android:tag="f314" android:label="@string/dummyLabel" />
+ <attribution android:tag="f315" android:label="@string/dummyLabel" />
+ <attribution android:tag="f316" android:label="@string/dummyLabel" />
+ <attribution android:tag="f317" android:label="@string/dummyLabel" />
+ <attribution android:tag="f318" android:label="@string/dummyLabel" />
+ <attribution android:tag="f319" android:label="@string/dummyLabel" />
+ <attribution android:tag="f320" android:label="@string/dummyLabel" />
+ <attribution android:tag="f321" android:label="@string/dummyLabel" />
+ <attribution android:tag="f322" android:label="@string/dummyLabel" />
+ <attribution android:tag="f323" android:label="@string/dummyLabel" />
+ <attribution android:tag="f324" android:label="@string/dummyLabel" />
+ <attribution android:tag="f325" android:label="@string/dummyLabel" />
+ <attribution android:tag="f326" android:label="@string/dummyLabel" />
+ <attribution android:tag="f327" android:label="@string/dummyLabel" />
+ <attribution android:tag="f328" android:label="@string/dummyLabel" />
+ <attribution android:tag="f329" android:label="@string/dummyLabel" />
+ <attribution android:tag="f330" android:label="@string/dummyLabel" />
+ <attribution android:tag="f331" android:label="@string/dummyLabel" />
+ <attribution android:tag="f332" android:label="@string/dummyLabel" />
+ <attribution android:tag="f333" android:label="@string/dummyLabel" />
+ <attribution android:tag="f334" android:label="@string/dummyLabel" />
+ <attribution android:tag="f335" android:label="@string/dummyLabel" />
+ <attribution android:tag="f336" android:label="@string/dummyLabel" />
+ <attribution android:tag="f337" android:label="@string/dummyLabel" />
+ <attribution android:tag="f338" android:label="@string/dummyLabel" />
+ <attribution android:tag="f339" android:label="@string/dummyLabel" />
+ <attribution android:tag="f340" android:label="@string/dummyLabel" />
+ <attribution android:tag="f341" android:label="@string/dummyLabel" />
+ <attribution android:tag="f342" android:label="@string/dummyLabel" />
+ <attribution android:tag="f343" android:label="@string/dummyLabel" />
+ <attribution android:tag="f344" android:label="@string/dummyLabel" />
+ <attribution android:tag="f345" android:label="@string/dummyLabel" />
+ <attribution android:tag="f346" android:label="@string/dummyLabel" />
+ <attribution android:tag="f347" android:label="@string/dummyLabel" />
+ <attribution android:tag="f348" android:label="@string/dummyLabel" />
+ <attribution android:tag="f349" android:label="@string/dummyLabel" />
+ <attribution android:tag="f350" android:label="@string/dummyLabel" />
+ <attribution android:tag="f351" android:label="@string/dummyLabel" />
+ <attribution android:tag="f352" android:label="@string/dummyLabel" />
+ <attribution android:tag="f353" android:label="@string/dummyLabel" />
+ <attribution android:tag="f354" android:label="@string/dummyLabel" />
+ <attribution android:tag="f355" android:label="@string/dummyLabel" />
+ <attribution android:tag="f356" android:label="@string/dummyLabel" />
+ <attribution android:tag="f357" android:label="@string/dummyLabel" />
+ <attribution android:tag="f358" android:label="@string/dummyLabel" />
+ <attribution android:tag="f359" android:label="@string/dummyLabel" />
+ <attribution android:tag="f360" android:label="@string/dummyLabel" />
+ <attribution android:tag="f361" android:label="@string/dummyLabel" />
+ <attribution android:tag="f362" android:label="@string/dummyLabel" />
+ <attribution android:tag="f363" android:label="@string/dummyLabel" />
+ <attribution android:tag="f364" android:label="@string/dummyLabel" />
+ <attribution android:tag="f365" android:label="@string/dummyLabel" />
+ <attribution android:tag="f366" android:label="@string/dummyLabel" />
+ <attribution android:tag="f367" android:label="@string/dummyLabel" />
+ <attribution android:tag="f368" android:label="@string/dummyLabel" />
+ <attribution android:tag="f369" android:label="@string/dummyLabel" />
+ <attribution android:tag="f370" android:label="@string/dummyLabel" />
+ <attribution android:tag="f371" android:label="@string/dummyLabel" />
+ <attribution android:tag="f372" android:label="@string/dummyLabel" />
+ <attribution android:tag="f373" android:label="@string/dummyLabel" />
+ <attribution android:tag="f374" android:label="@string/dummyLabel" />
+ <attribution android:tag="f375" android:label="@string/dummyLabel" />
+ <attribution android:tag="f376" android:label="@string/dummyLabel" />
+ <attribution android:tag="f377" android:label="@string/dummyLabel" />
+ <attribution android:tag="f378" android:label="@string/dummyLabel" />
+ <attribution android:tag="f379" android:label="@string/dummyLabel" />
+ <attribution android:tag="f380" android:label="@string/dummyLabel" />
+ <attribution android:tag="f381" android:label="@string/dummyLabel" />
+ <attribution android:tag="f382" android:label="@string/dummyLabel" />
+ <attribution android:tag="f383" android:label="@string/dummyLabel" />
+ <attribution android:tag="f384" android:label="@string/dummyLabel" />
+ <attribution android:tag="f385" android:label="@string/dummyLabel" />
+ <attribution android:tag="f386" android:label="@string/dummyLabel" />
+ <attribution android:tag="f387" android:label="@string/dummyLabel" />
+ <attribution android:tag="f388" android:label="@string/dummyLabel" />
+ <attribution android:tag="f389" android:label="@string/dummyLabel" />
+ <attribution android:tag="f390" android:label="@string/dummyLabel" />
+ <attribution android:tag="f391" android:label="@string/dummyLabel" />
+ <attribution android:tag="f392" android:label="@string/dummyLabel" />
+ <attribution android:tag="f393" android:label="@string/dummyLabel" />
+ <attribution android:tag="f394" android:label="@string/dummyLabel" />
+ <attribution android:tag="f395" android:label="@string/dummyLabel" />
+ <attribution android:tag="f396" android:label="@string/dummyLabel" />
+ <attribution android:tag="f397" android:label="@string/dummyLabel" />
+ <attribution android:tag="f398" android:label="@string/dummyLabel" />
+ <attribution android:tag="f399" android:label="@string/dummyLabel" />
+ <attribution android:tag="f400" android:label="@string/dummyLabel" />
+ <attribution android:tag="f401" android:label="@string/dummyLabel" />
+ <attribution android:tag="f402" android:label="@string/dummyLabel" />
+ <attribution android:tag="f403" android:label="@string/dummyLabel" />
+ <attribution android:tag="f404" android:label="@string/dummyLabel" />
+ <attribution android:tag="f405" android:label="@string/dummyLabel" />
+ <attribution android:tag="f406" android:label="@string/dummyLabel" />
+ <attribution android:tag="f407" android:label="@string/dummyLabel" />
+ <attribution android:tag="f408" android:label="@string/dummyLabel" />
+ <attribution android:tag="f409" android:label="@string/dummyLabel" />
+ <attribution android:tag="f410" android:label="@string/dummyLabel" />
+ <attribution android:tag="f411" android:label="@string/dummyLabel" />
+ <attribution android:tag="f412" android:label="@string/dummyLabel" />
+ <attribution android:tag="f413" android:label="@string/dummyLabel" />
+ <attribution android:tag="f414" android:label="@string/dummyLabel" />
+ <attribution android:tag="f415" android:label="@string/dummyLabel" />
+ <attribution android:tag="f416" android:label="@string/dummyLabel" />
+ <attribution android:tag="f417" android:label="@string/dummyLabel" />
+ <attribution android:tag="f418" android:label="@string/dummyLabel" />
+ <attribution android:tag="f419" android:label="@string/dummyLabel" />
+ <attribution android:tag="f420" android:label="@string/dummyLabel" />
+ <attribution android:tag="f421" android:label="@string/dummyLabel" />
+ <attribution android:tag="f422" android:label="@string/dummyLabel" />
+ <attribution android:tag="f423" android:label="@string/dummyLabel" />
+ <attribution android:tag="f424" android:label="@string/dummyLabel" />
+ <attribution android:tag="f425" android:label="@string/dummyLabel" />
+ <attribution android:tag="f426" android:label="@string/dummyLabel" />
+ <attribution android:tag="f427" android:label="@string/dummyLabel" />
+ <attribution android:tag="f428" android:label="@string/dummyLabel" />
+ <attribution android:tag="f429" android:label="@string/dummyLabel" />
+ <attribution android:tag="f430" android:label="@string/dummyLabel" />
+ <attribution android:tag="f431" android:label="@string/dummyLabel" />
+ <attribution android:tag="f432" android:label="@string/dummyLabel" />
+ <attribution android:tag="f433" android:label="@string/dummyLabel" />
+ <attribution android:tag="f434" android:label="@string/dummyLabel" />
+ <attribution android:tag="f435" android:label="@string/dummyLabel" />
+ <attribution android:tag="f436" android:label="@string/dummyLabel" />
+ <attribution android:tag="f437" android:label="@string/dummyLabel" />
+ <attribution android:tag="f438" android:label="@string/dummyLabel" />
+ <attribution android:tag="f439" android:label="@string/dummyLabel" />
+ <attribution android:tag="f440" android:label="@string/dummyLabel" />
+ <attribution android:tag="f441" android:label="@string/dummyLabel" />
+ <attribution android:tag="f442" android:label="@string/dummyLabel" />
+ <attribution android:tag="f443" android:label="@string/dummyLabel" />
+ <attribution android:tag="f444" android:label="@string/dummyLabel" />
+ <attribution android:tag="f445" android:label="@string/dummyLabel" />
+ <attribution android:tag="f446" android:label="@string/dummyLabel" />
+ <attribution android:tag="f447" android:label="@string/dummyLabel" />
+ <attribution android:tag="f448" android:label="@string/dummyLabel" />
+ <attribution android:tag="f449" android:label="@string/dummyLabel" />
+ <attribution android:tag="f450" android:label="@string/dummyLabel" />
+ <attribution android:tag="f451" android:label="@string/dummyLabel" />
+ <attribution android:tag="f452" android:label="@string/dummyLabel" />
+ <attribution android:tag="f453" android:label="@string/dummyLabel" />
+ <attribution android:tag="f454" android:label="@string/dummyLabel" />
+ <attribution android:tag="f455" android:label="@string/dummyLabel" />
+ <attribution android:tag="f456" android:label="@string/dummyLabel" />
+ <attribution android:tag="f457" android:label="@string/dummyLabel" />
+ <attribution android:tag="f458" android:label="@string/dummyLabel" />
+ <attribution android:tag="f459" android:label="@string/dummyLabel" />
+ <attribution android:tag="f460" android:label="@string/dummyLabel" />
+ <attribution android:tag="f461" android:label="@string/dummyLabel" />
+ <attribution android:tag="f462" android:label="@string/dummyLabel" />
+ <attribution android:tag="f463" android:label="@string/dummyLabel" />
+ <attribution android:tag="f464" android:label="@string/dummyLabel" />
+ <attribution android:tag="f465" android:label="@string/dummyLabel" />
+ <attribution android:tag="f466" android:label="@string/dummyLabel" />
+ <attribution android:tag="f467" android:label="@string/dummyLabel" />
+ <attribution android:tag="f468" android:label="@string/dummyLabel" />
+ <attribution android:tag="f469" android:label="@string/dummyLabel" />
+ <attribution android:tag="f470" android:label="@string/dummyLabel" />
+ <attribution android:tag="f471" android:label="@string/dummyLabel" />
+ <attribution android:tag="f472" android:label="@string/dummyLabel" />
+ <attribution android:tag="f473" android:label="@string/dummyLabel" />
+ <attribution android:tag="f474" android:label="@string/dummyLabel" />
+ <attribution android:tag="f475" android:label="@string/dummyLabel" />
+ <attribution android:tag="f476" android:label="@string/dummyLabel" />
+ <attribution android:tag="f477" android:label="@string/dummyLabel" />
+ <attribution android:tag="f478" android:label="@string/dummyLabel" />
+ <attribution android:tag="f479" android:label="@string/dummyLabel" />
+ <attribution android:tag="f480" android:label="@string/dummyLabel" />
+ <attribution android:tag="f481" android:label="@string/dummyLabel" />
+ <attribution android:tag="f482" android:label="@string/dummyLabel" />
+ <attribution android:tag="f483" android:label="@string/dummyLabel" />
+ <attribution android:tag="f484" android:label="@string/dummyLabel" />
+ <attribution android:tag="f485" android:label="@string/dummyLabel" />
+ <attribution android:tag="f486" android:label="@string/dummyLabel" />
+ <attribution android:tag="f487" android:label="@string/dummyLabel" />
+ <attribution android:tag="f488" android:label="@string/dummyLabel" />
+ <attribution android:tag="f489" android:label="@string/dummyLabel" />
+ <attribution android:tag="f490" android:label="@string/dummyLabel" />
+ <attribution android:tag="f491" android:label="@string/dummyLabel" />
+ <attribution android:tag="f492" android:label="@string/dummyLabel" />
+ <attribution android:tag="f493" android:label="@string/dummyLabel" />
+ <attribution android:tag="f494" android:label="@string/dummyLabel" />
+ <attribution android:tag="f495" android:label="@string/dummyLabel" />
+ <attribution android:tag="f496" android:label="@string/dummyLabel" />
+ <attribution android:tag="f497" android:label="@string/dummyLabel" />
+ <attribution android:tag="f498" android:label="@string/dummyLabel" />
+ <attribution android:tag="f499" android:label="@string/dummyLabel" />
+ <attribution android:tag="f500" android:label="@string/dummyLabel" />
+ <attribution android:tag="f501" android:label="@string/dummyLabel" />
+ <attribution android:tag="f502" android:label="@string/dummyLabel" />
+ <attribution android:tag="f503" android:label="@string/dummyLabel" />
+ <attribution android:tag="f504" android:label="@string/dummyLabel" />
+ <attribution android:tag="f505" android:label="@string/dummyLabel" />
+ <attribution android:tag="f506" android:label="@string/dummyLabel" />
+ <attribution android:tag="f507" android:label="@string/dummyLabel" />
+ <attribution android:tag="f508" android:label="@string/dummyLabel" />
+ <attribution android:tag="f509" android:label="@string/dummyLabel" />
+ <attribution android:tag="f510" android:label="@string/dummyLabel" />
+ <attribution android:tag="f511" android:label="@string/dummyLabel" />
+ <attribution android:tag="f512" android:label="@string/dummyLabel" />
+ <attribution android:tag="f513" android:label="@string/dummyLabel" />
+ <attribution android:tag="f514" android:label="@string/dummyLabel" />
+ <attribution android:tag="f515" android:label="@string/dummyLabel" />
+ <attribution android:tag="f516" android:label="@string/dummyLabel" />
+ <attribution android:tag="f517" android:label="@string/dummyLabel" />
+ <attribution android:tag="f518" android:label="@string/dummyLabel" />
+ <attribution android:tag="f519" android:label="@string/dummyLabel" />
+ <attribution android:tag="f520" android:label="@string/dummyLabel" />
+ <attribution android:tag="f521" android:label="@string/dummyLabel" />
+ <attribution android:tag="f522" android:label="@string/dummyLabel" />
+ <attribution android:tag="f523" android:label="@string/dummyLabel" />
+ <attribution android:tag="f524" android:label="@string/dummyLabel" />
+ <attribution android:tag="f525" android:label="@string/dummyLabel" />
+ <attribution android:tag="f526" android:label="@string/dummyLabel" />
+ <attribution android:tag="f527" android:label="@string/dummyLabel" />
+ <attribution android:tag="f528" android:label="@string/dummyLabel" />
+ <attribution android:tag="f529" android:label="@string/dummyLabel" />
+ <attribution android:tag="f530" android:label="@string/dummyLabel" />
+ <attribution android:tag="f531" android:label="@string/dummyLabel" />
+ <attribution android:tag="f532" android:label="@string/dummyLabel" />
+ <attribution android:tag="f533" android:label="@string/dummyLabel" />
+ <attribution android:tag="f534" android:label="@string/dummyLabel" />
+ <attribution android:tag="f535" android:label="@string/dummyLabel" />
+ <attribution android:tag="f536" android:label="@string/dummyLabel" />
+ <attribution android:tag="f537" android:label="@string/dummyLabel" />
+ <attribution android:tag="f538" android:label="@string/dummyLabel" />
+ <attribution android:tag="f539" android:label="@string/dummyLabel" />
+ <attribution android:tag="f540" android:label="@string/dummyLabel" />
+ <attribution android:tag="f541" android:label="@string/dummyLabel" />
+ <attribution android:tag="f542" android:label="@string/dummyLabel" />
+ <attribution android:tag="f543" android:label="@string/dummyLabel" />
+ <attribution android:tag="f544" android:label="@string/dummyLabel" />
+ <attribution android:tag="f545" android:label="@string/dummyLabel" />
+ <attribution android:tag="f546" android:label="@string/dummyLabel" />
+ <attribution android:tag="f547" android:label="@string/dummyLabel" />
+ <attribution android:tag="f548" android:label="@string/dummyLabel" />
+ <attribution android:tag="f549" android:label="@string/dummyLabel" />
+ <attribution android:tag="f550" android:label="@string/dummyLabel" />
+ <attribution android:tag="f551" android:label="@string/dummyLabel" />
+ <attribution android:tag="f552" android:label="@string/dummyLabel" />
+ <attribution android:tag="f553" android:label="@string/dummyLabel" />
+ <attribution android:tag="f554" android:label="@string/dummyLabel" />
+ <attribution android:tag="f555" android:label="@string/dummyLabel" />
+ <attribution android:tag="f556" android:label="@string/dummyLabel" />
+ <attribution android:tag="f557" android:label="@string/dummyLabel" />
+ <attribution android:tag="f558" android:label="@string/dummyLabel" />
+ <attribution android:tag="f559" android:label="@string/dummyLabel" />
+ <attribution android:tag="f560" android:label="@string/dummyLabel" />
+ <attribution android:tag="f561" android:label="@string/dummyLabel" />
+ <attribution android:tag="f562" android:label="@string/dummyLabel" />
+ <attribution android:tag="f563" android:label="@string/dummyLabel" />
+ <attribution android:tag="f564" android:label="@string/dummyLabel" />
+ <attribution android:tag="f565" android:label="@string/dummyLabel" />
+ <attribution android:tag="f566" android:label="@string/dummyLabel" />
+ <attribution android:tag="f567" android:label="@string/dummyLabel" />
+ <attribution android:tag="f568" android:label="@string/dummyLabel" />
+ <attribution android:tag="f569" android:label="@string/dummyLabel" />
+ <attribution android:tag="f570" android:label="@string/dummyLabel" />
+ <attribution android:tag="f571" android:label="@string/dummyLabel" />
+ <attribution android:tag="f572" android:label="@string/dummyLabel" />
+ <attribution android:tag="f573" android:label="@string/dummyLabel" />
+ <attribution android:tag="f574" android:label="@string/dummyLabel" />
+ <attribution android:tag="f575" android:label="@string/dummyLabel" />
+ <attribution android:tag="f576" android:label="@string/dummyLabel" />
+ <attribution android:tag="f577" android:label="@string/dummyLabel" />
+ <attribution android:tag="f578" android:label="@string/dummyLabel" />
+ <attribution android:tag="f579" android:label="@string/dummyLabel" />
+ <attribution android:tag="f580" android:label="@string/dummyLabel" />
+ <attribution android:tag="f581" android:label="@string/dummyLabel" />
+ <attribution android:tag="f582" android:label="@string/dummyLabel" />
+ <attribution android:tag="f583" android:label="@string/dummyLabel" />
+ <attribution android:tag="f584" android:label="@string/dummyLabel" />
+ <attribution android:tag="f585" android:label="@string/dummyLabel" />
+ <attribution android:tag="f586" android:label="@string/dummyLabel" />
+ <attribution android:tag="f587" android:label="@string/dummyLabel" />
+ <attribution android:tag="f588" android:label="@string/dummyLabel" />
+ <attribution android:tag="f589" android:label="@string/dummyLabel" />
+ <attribution android:tag="f590" android:label="@string/dummyLabel" />
+ <attribution android:tag="f591" android:label="@string/dummyLabel" />
+ <attribution android:tag="f592" android:label="@string/dummyLabel" />
+ <attribution android:tag="f593" android:label="@string/dummyLabel" />
+ <attribution android:tag="f594" android:label="@string/dummyLabel" />
+ <attribution android:tag="f595" android:label="@string/dummyLabel" />
+ <attribution android:tag="f596" android:label="@string/dummyLabel" />
+ <attribution android:tag="f597" android:label="@string/dummyLabel" />
+ <attribution android:tag="f598" android:label="@string/dummyLabel" />
+ <attribution android:tag="f599" android:label="@string/dummyLabel" />
+ <attribution android:tag="f600" android:label="@string/dummyLabel" />
+ <attribution android:tag="f601" android:label="@string/dummyLabel" />
+ <attribution android:tag="f602" android:label="@string/dummyLabel" />
+ <attribution android:tag="f603" android:label="@string/dummyLabel" />
+ <attribution android:tag="f604" android:label="@string/dummyLabel" />
+ <attribution android:tag="f605" android:label="@string/dummyLabel" />
+ <attribution android:tag="f606" android:label="@string/dummyLabel" />
+ <attribution android:tag="f607" android:label="@string/dummyLabel" />
+ <attribution android:tag="f608" android:label="@string/dummyLabel" />
+ <attribution android:tag="f609" android:label="@string/dummyLabel" />
+ <attribution android:tag="f610" android:label="@string/dummyLabel" />
+ <attribution android:tag="f611" android:label="@string/dummyLabel" />
+ <attribution android:tag="f612" android:label="@string/dummyLabel" />
+ <attribution android:tag="f613" android:label="@string/dummyLabel" />
+ <attribution android:tag="f614" android:label="@string/dummyLabel" />
+ <attribution android:tag="f615" android:label="@string/dummyLabel" />
+ <attribution android:tag="f616" android:label="@string/dummyLabel" />
+ <attribution android:tag="f617" android:label="@string/dummyLabel" />
+ <attribution android:tag="f618" android:label="@string/dummyLabel" />
+ <attribution android:tag="f619" android:label="@string/dummyLabel" />
+ <attribution android:tag="f620" android:label="@string/dummyLabel" />
+ <attribution android:tag="f621" android:label="@string/dummyLabel" />
+ <attribution android:tag="f622" android:label="@string/dummyLabel" />
+ <attribution android:tag="f623" android:label="@string/dummyLabel" />
+ <attribution android:tag="f624" android:label="@string/dummyLabel" />
+ <attribution android:tag="f625" android:label="@string/dummyLabel" />
+ <attribution android:tag="f626" android:label="@string/dummyLabel" />
+ <attribution android:tag="f627" android:label="@string/dummyLabel" />
+ <attribution android:tag="f628" android:label="@string/dummyLabel" />
+ <attribution android:tag="f629" android:label="@string/dummyLabel" />
+ <attribution android:tag="f630" android:label="@string/dummyLabel" />
+ <attribution android:tag="f631" android:label="@string/dummyLabel" />
+ <attribution android:tag="f632" android:label="@string/dummyLabel" />
+ <attribution android:tag="f633" android:label="@string/dummyLabel" />
+ <attribution android:tag="f634" android:label="@string/dummyLabel" />
+ <attribution android:tag="f635" android:label="@string/dummyLabel" />
+ <attribution android:tag="f636" android:label="@string/dummyLabel" />
+ <attribution android:tag="f637" android:label="@string/dummyLabel" />
+ <attribution android:tag="f638" android:label="@string/dummyLabel" />
+ <attribution android:tag="f639" android:label="@string/dummyLabel" />
+ <attribution android:tag="f640" android:label="@string/dummyLabel" />
+ <attribution android:tag="f641" android:label="@string/dummyLabel" />
+ <attribution android:tag="f642" android:label="@string/dummyLabel" />
+ <attribution android:tag="f643" android:label="@string/dummyLabel" />
+ <attribution android:tag="f644" android:label="@string/dummyLabel" />
+ <attribution android:tag="f645" android:label="@string/dummyLabel" />
+ <attribution android:tag="f646" android:label="@string/dummyLabel" />
+ <attribution android:tag="f647" android:label="@string/dummyLabel" />
+ <attribution android:tag="f648" android:label="@string/dummyLabel" />
+ <attribution android:tag="f649" android:label="@string/dummyLabel" />
+ <attribution android:tag="f650" android:label="@string/dummyLabel" />
+ <attribution android:tag="f651" android:label="@string/dummyLabel" />
+ <attribution android:tag="f652" android:label="@string/dummyLabel" />
+ <attribution android:tag="f653" android:label="@string/dummyLabel" />
+ <attribution android:tag="f654" android:label="@string/dummyLabel" />
+ <attribution android:tag="f655" android:label="@string/dummyLabel" />
+ <attribution android:tag="f656" android:label="@string/dummyLabel" />
+ <attribution android:tag="f657" android:label="@string/dummyLabel" />
+ <attribution android:tag="f658" android:label="@string/dummyLabel" />
+ <attribution android:tag="f659" android:label="@string/dummyLabel" />
+ <attribution android:tag="f660" android:label="@string/dummyLabel" />
+ <attribution android:tag="f661" android:label="@string/dummyLabel" />
+ <attribution android:tag="f662" android:label="@string/dummyLabel" />
+ <attribution android:tag="f663" android:label="@string/dummyLabel" />
+ <attribution android:tag="f664" android:label="@string/dummyLabel" />
+ <attribution android:tag="f665" android:label="@string/dummyLabel" />
+ <attribution android:tag="f666" android:label="@string/dummyLabel" />
+ <attribution android:tag="f667" android:label="@string/dummyLabel" />
+ <attribution android:tag="f668" android:label="@string/dummyLabel" />
+ <attribution android:tag="f669" android:label="@string/dummyLabel" />
+ <attribution android:tag="f670" android:label="@string/dummyLabel" />
+ <attribution android:tag="f671" android:label="@string/dummyLabel" />
+ <attribution android:tag="f672" android:label="@string/dummyLabel" />
+ <attribution android:tag="f673" android:label="@string/dummyLabel" />
+ <attribution android:tag="f674" android:label="@string/dummyLabel" />
+ <attribution android:tag="f675" android:label="@string/dummyLabel" />
+ <attribution android:tag="f676" android:label="@string/dummyLabel" />
+ <attribution android:tag="f677" android:label="@string/dummyLabel" />
+ <attribution android:tag="f678" android:label="@string/dummyLabel" />
+ <attribution android:tag="f679" android:label="@string/dummyLabel" />
+ <attribution android:tag="f680" android:label="@string/dummyLabel" />
+ <attribution android:tag="f681" android:label="@string/dummyLabel" />
+ <attribution android:tag="f682" android:label="@string/dummyLabel" />
+ <attribution android:tag="f683" android:label="@string/dummyLabel" />
+ <attribution android:tag="f684" android:label="@string/dummyLabel" />
+ <attribution android:tag="f685" android:label="@string/dummyLabel" />
+ <attribution android:tag="f686" android:label="@string/dummyLabel" />
+ <attribution android:tag="f687" android:label="@string/dummyLabel" />
+ <attribution android:tag="f688" android:label="@string/dummyLabel" />
+ <attribution android:tag="f689" android:label="@string/dummyLabel" />
+ <attribution android:tag="f690" android:label="@string/dummyLabel" />
+ <attribution android:tag="f691" android:label="@string/dummyLabel" />
+ <attribution android:tag="f692" android:label="@string/dummyLabel" />
+ <attribution android:tag="f693" android:label="@string/dummyLabel" />
+ <attribution android:tag="f694" android:label="@string/dummyLabel" />
+ <attribution android:tag="f695" android:label="@string/dummyLabel" />
+ <attribution android:tag="f696" android:label="@string/dummyLabel" />
+ <attribution android:tag="f697" android:label="@string/dummyLabel" />
+ <attribution android:tag="f698" android:label="@string/dummyLabel" />
+ <attribution android:tag="f699" android:label="@string/dummyLabel" />
+ <attribution android:tag="f700" android:label="@string/dummyLabel" />
+ <attribution android:tag="f701" android:label="@string/dummyLabel" />
+ <attribution android:tag="f702" android:label="@string/dummyLabel" />
+ <attribution android:tag="f703" android:label="@string/dummyLabel" />
+ <attribution android:tag="f704" android:label="@string/dummyLabel" />
+ <attribution android:tag="f705" android:label="@string/dummyLabel" />
+ <attribution android:tag="f706" android:label="@string/dummyLabel" />
+ <attribution android:tag="f707" android:label="@string/dummyLabel" />
+ <attribution android:tag="f708" android:label="@string/dummyLabel" />
+ <attribution android:tag="f709" android:label="@string/dummyLabel" />
+ <attribution android:tag="f710" android:label="@string/dummyLabel" />
+ <attribution android:tag="f711" android:label="@string/dummyLabel" />
+ <attribution android:tag="f712" android:label="@string/dummyLabel" />
+ <attribution android:tag="f713" android:label="@string/dummyLabel" />
+ <attribution android:tag="f714" android:label="@string/dummyLabel" />
+ <attribution android:tag="f715" android:label="@string/dummyLabel" />
+ <attribution android:tag="f716" android:label="@string/dummyLabel" />
+ <attribution android:tag="f717" android:label="@string/dummyLabel" />
+ <attribution android:tag="f718" android:label="@string/dummyLabel" />
+ <attribution android:tag="f719" android:label="@string/dummyLabel" />
+ <attribution android:tag="f720" android:label="@string/dummyLabel" />
+ <attribution android:tag="f721" android:label="@string/dummyLabel" />
+ <attribution android:tag="f722" android:label="@string/dummyLabel" />
+ <attribution android:tag="f723" android:label="@string/dummyLabel" />
+ <attribution android:tag="f724" android:label="@string/dummyLabel" />
+ <attribution android:tag="f725" android:label="@string/dummyLabel" />
+ <attribution android:tag="f726" android:label="@string/dummyLabel" />
+ <attribution android:tag="f727" android:label="@string/dummyLabel" />
+ <attribution android:tag="f728" android:label="@string/dummyLabel" />
+ <attribution android:tag="f729" android:label="@string/dummyLabel" />
+ <attribution android:tag="f730" android:label="@string/dummyLabel" />
+ <attribution android:tag="f731" android:label="@string/dummyLabel" />
+ <attribution android:tag="f732" android:label="@string/dummyLabel" />
+ <attribution android:tag="f733" android:label="@string/dummyLabel" />
+ <attribution android:tag="f734" android:label="@string/dummyLabel" />
+ <attribution android:tag="f735" android:label="@string/dummyLabel" />
+ <attribution android:tag="f736" android:label="@string/dummyLabel" />
+ <attribution android:tag="f737" android:label="@string/dummyLabel" />
+ <attribution android:tag="f738" android:label="@string/dummyLabel" />
+ <attribution android:tag="f739" android:label="@string/dummyLabel" />
+ <attribution android:tag="f740" android:label="@string/dummyLabel" />
+ <attribution android:tag="f741" android:label="@string/dummyLabel" />
+ <attribution android:tag="f742" android:label="@string/dummyLabel" />
+ <attribution android:tag="f743" android:label="@string/dummyLabel" />
+ <attribution android:tag="f744" android:label="@string/dummyLabel" />
+ <attribution android:tag="f745" android:label="@string/dummyLabel" />
+ <attribution android:tag="f746" android:label="@string/dummyLabel" />
+ <attribution android:tag="f747" android:label="@string/dummyLabel" />
+ <attribution android:tag="f748" android:label="@string/dummyLabel" />
+ <attribution android:tag="f749" android:label="@string/dummyLabel" />
+ <attribution android:tag="f750" android:label="@string/dummyLabel" />
+ <attribution android:tag="f751" android:label="@string/dummyLabel" />
+ <attribution android:tag="f752" android:label="@string/dummyLabel" />
+ <attribution android:tag="f753" android:label="@string/dummyLabel" />
+ <attribution android:tag="f754" android:label="@string/dummyLabel" />
+ <attribution android:tag="f755" android:label="@string/dummyLabel" />
+ <attribution android:tag="f756" android:label="@string/dummyLabel" />
+ <attribution android:tag="f757" android:label="@string/dummyLabel" />
+ <attribution android:tag="f758" android:label="@string/dummyLabel" />
+ <attribution android:tag="f759" android:label="@string/dummyLabel" />
+ <attribution android:tag="f760" android:label="@string/dummyLabel" />
+ <attribution android:tag="f761" android:label="@string/dummyLabel" />
+ <attribution android:tag="f762" android:label="@string/dummyLabel" />
+ <attribution android:tag="f763" android:label="@string/dummyLabel" />
+ <attribution android:tag="f764" android:label="@string/dummyLabel" />
+ <attribution android:tag="f765" android:label="@string/dummyLabel" />
+ <attribution android:tag="f766" android:label="@string/dummyLabel" />
+ <attribution android:tag="f767" android:label="@string/dummyLabel" />
+ <attribution android:tag="f768" android:label="@string/dummyLabel" />
+ <attribution android:tag="f769" android:label="@string/dummyLabel" />
+ <attribution android:tag="f770" android:label="@string/dummyLabel" />
+ <attribution android:tag="f771" android:label="@string/dummyLabel" />
+ <attribution android:tag="f772" android:label="@string/dummyLabel" />
+ <attribution android:tag="f773" android:label="@string/dummyLabel" />
+ <attribution android:tag="f774" android:label="@string/dummyLabel" />
+ <attribution android:tag="f775" android:label="@string/dummyLabel" />
+ <attribution android:tag="f776" android:label="@string/dummyLabel" />
+ <attribution android:tag="f777" android:label="@string/dummyLabel" />
+ <attribution android:tag="f778" android:label="@string/dummyLabel" />
+ <attribution android:tag="f779" android:label="@string/dummyLabel" />
+ <attribution android:tag="f780" android:label="@string/dummyLabel" />
+ <attribution android:tag="f781" android:label="@string/dummyLabel" />
+ <attribution android:tag="f782" android:label="@string/dummyLabel" />
+ <attribution android:tag="f783" android:label="@string/dummyLabel" />
+ <attribution android:tag="f784" android:label="@string/dummyLabel" />
+ <attribution android:tag="f785" android:label="@string/dummyLabel" />
+ <attribution android:tag="f786" android:label="@string/dummyLabel" />
+ <attribution android:tag="f787" android:label="@string/dummyLabel" />
+ <attribution android:tag="f788" android:label="@string/dummyLabel" />
+ <attribution android:tag="f789" android:label="@string/dummyLabel" />
+ <attribution android:tag="f790" android:label="@string/dummyLabel" />
+ <attribution android:tag="f791" android:label="@string/dummyLabel" />
+ <attribution android:tag="f792" android:label="@string/dummyLabel" />
+ <attribution android:tag="f793" android:label="@string/dummyLabel" />
+ <attribution android:tag="f794" android:label="@string/dummyLabel" />
+ <attribution android:tag="f795" android:label="@string/dummyLabel" />
+ <attribution android:tag="f796" android:label="@string/dummyLabel" />
+ <attribution android:tag="f797" android:label="@string/dummyLabel" />
+ <attribution android:tag="f798" android:label="@string/dummyLabel" />
+ <attribution android:tag="f799" android:label="@string/dummyLabel" />
+ <attribution android:tag="f800" android:label="@string/dummyLabel" />
+ <attribution android:tag="f801" android:label="@string/dummyLabel" />
+ <attribution android:tag="f802" android:label="@string/dummyLabel" />
+ <attribution android:tag="f803" android:label="@string/dummyLabel" />
+ <attribution android:tag="f804" android:label="@string/dummyLabel" />
+ <attribution android:tag="f805" android:label="@string/dummyLabel" />
+ <attribution android:tag="f806" android:label="@string/dummyLabel" />
+ <attribution android:tag="f807" android:label="@string/dummyLabel" />
+ <attribution android:tag="f808" android:label="@string/dummyLabel" />
+ <attribution android:tag="f809" android:label="@string/dummyLabel" />
+ <attribution android:tag="f810" android:label="@string/dummyLabel" />
+ <attribution android:tag="f811" android:label="@string/dummyLabel" />
+ <attribution android:tag="f812" android:label="@string/dummyLabel" />
+ <attribution android:tag="f813" android:label="@string/dummyLabel" />
+ <attribution android:tag="f814" android:label="@string/dummyLabel" />
+ <attribution android:tag="f815" android:label="@string/dummyLabel" />
+ <attribution android:tag="f816" android:label="@string/dummyLabel" />
+ <attribution android:tag="f817" android:label="@string/dummyLabel" />
+ <attribution android:tag="f818" android:label="@string/dummyLabel" />
+ <attribution android:tag="f819" android:label="@string/dummyLabel" />
+ <attribution android:tag="f820" android:label="@string/dummyLabel" />
+ <attribution android:tag="f821" android:label="@string/dummyLabel" />
+ <attribution android:tag="f822" android:label="@string/dummyLabel" />
+ <attribution android:tag="f823" android:label="@string/dummyLabel" />
+ <attribution android:tag="f824" android:label="@string/dummyLabel" />
+ <attribution android:tag="f825" android:label="@string/dummyLabel" />
+ <attribution android:tag="f826" android:label="@string/dummyLabel" />
+ <attribution android:tag="f827" android:label="@string/dummyLabel" />
+ <attribution android:tag="f828" android:label="@string/dummyLabel" />
+ <attribution android:tag="f829" android:label="@string/dummyLabel" />
+ <attribution android:tag="f830" android:label="@string/dummyLabel" />
+ <attribution android:tag="f831" android:label="@string/dummyLabel" />
+ <attribution android:tag="f832" android:label="@string/dummyLabel" />
+ <attribution android:tag="f833" android:label="@string/dummyLabel" />
+ <attribution android:tag="f834" android:label="@string/dummyLabel" />
+ <attribution android:tag="f835" android:label="@string/dummyLabel" />
+ <attribution android:tag="f836" android:label="@string/dummyLabel" />
+ <attribution android:tag="f837" android:label="@string/dummyLabel" />
+ <attribution android:tag="f838" android:label="@string/dummyLabel" />
+ <attribution android:tag="f839" android:label="@string/dummyLabel" />
+ <attribution android:tag="f840" android:label="@string/dummyLabel" />
+ <attribution android:tag="f841" android:label="@string/dummyLabel" />
+ <attribution android:tag="f842" android:label="@string/dummyLabel" />
+ <attribution android:tag="f843" android:label="@string/dummyLabel" />
+ <attribution android:tag="f844" android:label="@string/dummyLabel" />
+ <attribution android:tag="f845" android:label="@string/dummyLabel" />
+ <attribution android:tag="f846" android:label="@string/dummyLabel" />
+ <attribution android:tag="f847" android:label="@string/dummyLabel" />
+ <attribution android:tag="f848" android:label="@string/dummyLabel" />
+ <attribution android:tag="f849" android:label="@string/dummyLabel" />
+ <attribution android:tag="f850" android:label="@string/dummyLabel" />
+ <attribution android:tag="f851" android:label="@string/dummyLabel" />
+ <attribution android:tag="f852" android:label="@string/dummyLabel" />
+ <attribution android:tag="f853" android:label="@string/dummyLabel" />
+ <attribution android:tag="f854" android:label="@string/dummyLabel" />
+ <attribution android:tag="f855" android:label="@string/dummyLabel" />
+ <attribution android:tag="f856" android:label="@string/dummyLabel" />
+ <attribution android:tag="f857" android:label="@string/dummyLabel" />
+ <attribution android:tag="f858" android:label="@string/dummyLabel" />
+ <attribution android:tag="f859" android:label="@string/dummyLabel" />
+ <attribution android:tag="f860" android:label="@string/dummyLabel" />
+ <attribution android:tag="f861" android:label="@string/dummyLabel" />
+ <attribution android:tag="f862" android:label="@string/dummyLabel" />
+ <attribution android:tag="f863" android:label="@string/dummyLabel" />
+ <attribution android:tag="f864" android:label="@string/dummyLabel" />
+ <attribution android:tag="f865" android:label="@string/dummyLabel" />
+ <attribution android:tag="f866" android:label="@string/dummyLabel" />
+ <attribution android:tag="f867" android:label="@string/dummyLabel" />
+ <attribution android:tag="f868" android:label="@string/dummyLabel" />
+ <attribution android:tag="f869" android:label="@string/dummyLabel" />
+ <attribution android:tag="f870" android:label="@string/dummyLabel" />
+ <attribution android:tag="f871" android:label="@string/dummyLabel" />
+ <attribution android:tag="f872" android:label="@string/dummyLabel" />
+ <attribution android:tag="f873" android:label="@string/dummyLabel" />
+ <attribution android:tag="f874" android:label="@string/dummyLabel" />
+ <attribution android:tag="f875" android:label="@string/dummyLabel" />
+ <attribution android:tag="f876" android:label="@string/dummyLabel" />
+ <attribution android:tag="f877" android:label="@string/dummyLabel" />
+ <attribution android:tag="f878" android:label="@string/dummyLabel" />
+ <attribution android:tag="f879" android:label="@string/dummyLabel" />
+ <attribution android:tag="f880" android:label="@string/dummyLabel" />
+ <attribution android:tag="f881" android:label="@string/dummyLabel" />
+ <attribution android:tag="f882" android:label="@string/dummyLabel" />
+ <attribution android:tag="f883" android:label="@string/dummyLabel" />
+ <attribution android:tag="f884" android:label="@string/dummyLabel" />
+ <attribution android:tag="f885" android:label="@string/dummyLabel" />
+ <attribution android:tag="f886" android:label="@string/dummyLabel" />
+ <attribution android:tag="f887" android:label="@string/dummyLabel" />
+ <attribution android:tag="f888" android:label="@string/dummyLabel" />
+ <attribution android:tag="f889" android:label="@string/dummyLabel" />
+ <attribution android:tag="f890" android:label="@string/dummyLabel" />
+ <attribution android:tag="f891" android:label="@string/dummyLabel" />
+ <attribution android:tag="f892" android:label="@string/dummyLabel" />
+ <attribution android:tag="f893" android:label="@string/dummyLabel" />
+ <attribution android:tag="f894" android:label="@string/dummyLabel" />
+ <attribution android:tag="f895" android:label="@string/dummyLabel" />
+ <attribution android:tag="f896" android:label="@string/dummyLabel" />
+ <attribution android:tag="f897" android:label="@string/dummyLabel" />
+ <attribution android:tag="f898" android:label="@string/dummyLabel" />
+ <attribution android:tag="f899" android:label="@string/dummyLabel" />
+ <attribution android:tag="f900" android:label="@string/dummyLabel" />
+ <attribution android:tag="f901" android:label="@string/dummyLabel" />
+ <attribution android:tag="f902" android:label="@string/dummyLabel" />
+ <attribution android:tag="f903" android:label="@string/dummyLabel" />
+ <attribution android:tag="f904" android:label="@string/dummyLabel" />
+ <attribution android:tag="f905" android:label="@string/dummyLabel" />
+ <attribution android:tag="f906" android:label="@string/dummyLabel" />
+ <attribution android:tag="f907" android:label="@string/dummyLabel" />
+ <attribution android:tag="f908" android:label="@string/dummyLabel" />
+ <attribution android:tag="f909" android:label="@string/dummyLabel" />
+ <attribution android:tag="f910" android:label="@string/dummyLabel" />
+ <attribution android:tag="f911" android:label="@string/dummyLabel" />
+ <attribution android:tag="f912" android:label="@string/dummyLabel" />
+ <attribution android:tag="f913" android:label="@string/dummyLabel" />
+ <attribution android:tag="f914" android:label="@string/dummyLabel" />
+ <attribution android:tag="f915" android:label="@string/dummyLabel" />
+ <attribution android:tag="f916" android:label="@string/dummyLabel" />
+ <attribution android:tag="f917" android:label="@string/dummyLabel" />
+ <attribution android:tag="f918" android:label="@string/dummyLabel" />
+ <attribution android:tag="f919" android:label="@string/dummyLabel" />
+ <attribution android:tag="f920" android:label="@string/dummyLabel" />
+ <attribution android:tag="f921" android:label="@string/dummyLabel" />
+ <attribution android:tag="f922" android:label="@string/dummyLabel" />
+ <attribution android:tag="f923" android:label="@string/dummyLabel" />
+ <attribution android:tag="f924" android:label="@string/dummyLabel" />
+ <attribution android:tag="f925" android:label="@string/dummyLabel" />
+ <attribution android:tag="f926" android:label="@string/dummyLabel" />
+ <attribution android:tag="f927" android:label="@string/dummyLabel" />
+ <attribution android:tag="f928" android:label="@string/dummyLabel" />
+ <attribution android:tag="f929" android:label="@string/dummyLabel" />
+ <attribution android:tag="f930" android:label="@string/dummyLabel" />
+ <attribution android:tag="f931" android:label="@string/dummyLabel" />
+ <attribution android:tag="f932" android:label="@string/dummyLabel" />
+ <attribution android:tag="f933" android:label="@string/dummyLabel" />
+ <attribution android:tag="f934" android:label="@string/dummyLabel" />
+ <attribution android:tag="f935" android:label="@string/dummyLabel" />
+ <attribution android:tag="f936" android:label="@string/dummyLabel" />
+ <attribution android:tag="f937" android:label="@string/dummyLabel" />
+ <attribution android:tag="f938" android:label="@string/dummyLabel" />
+ <attribution android:tag="f939" android:label="@string/dummyLabel" />
+ <attribution android:tag="f940" android:label="@string/dummyLabel" />
+ <attribution android:tag="f941" android:label="@string/dummyLabel" />
+ <attribution android:tag="f942" android:label="@string/dummyLabel" />
+ <attribution android:tag="f943" android:label="@string/dummyLabel" />
+ <attribution android:tag="f944" android:label="@string/dummyLabel" />
+ <attribution android:tag="f945" android:label="@string/dummyLabel" />
+ <attribution android:tag="f946" android:label="@string/dummyLabel" />
+ <attribution android:tag="f947" android:label="@string/dummyLabel" />
+ <attribution android:tag="f948" android:label="@string/dummyLabel" />
+ <attribution android:tag="f949" android:label="@string/dummyLabel" />
+ <attribution android:tag="f950" android:label="@string/dummyLabel" />
+ <attribution android:tag="f951" android:label="@string/dummyLabel" />
+ <attribution android:tag="f952" android:label="@string/dummyLabel" />
+ <attribution android:tag="f953" android:label="@string/dummyLabel" />
+ <attribution android:tag="f954" android:label="@string/dummyLabel" />
+ <attribution android:tag="f955" android:label="@string/dummyLabel" />
+ <attribution android:tag="f956" android:label="@string/dummyLabel" />
+ <attribution android:tag="f957" android:label="@string/dummyLabel" />
+ <attribution android:tag="f958" android:label="@string/dummyLabel" />
+ <attribution android:tag="f959" android:label="@string/dummyLabel" />
+ <attribution android:tag="f960" android:label="@string/dummyLabel" />
+ <attribution android:tag="f961" android:label="@string/dummyLabel" />
+ <attribution android:tag="f962" android:label="@string/dummyLabel" />
+ <attribution android:tag="f963" android:label="@string/dummyLabel" />
+ <attribution android:tag="f964" android:label="@string/dummyLabel" />
+ <attribution android:tag="f965" android:label="@string/dummyLabel" />
+ <attribution android:tag="f966" android:label="@string/dummyLabel" />
+ <attribution android:tag="f967" android:label="@string/dummyLabel" />
+ <attribution android:tag="f968" android:label="@string/dummyLabel" />
+ <attribution android:tag="f969" android:label="@string/dummyLabel" />
+ <attribution android:tag="f970" android:label="@string/dummyLabel" />
+ <attribution android:tag="f971" android:label="@string/dummyLabel" />
+ <attribution android:tag="f972" android:label="@string/dummyLabel" />
+ <attribution android:tag="f973" android:label="@string/dummyLabel" />
+ <attribution android:tag="f974" android:label="@string/dummyLabel" />
+ <attribution android:tag="f975" android:label="@string/dummyLabel" />
+ <attribution android:tag="f976" android:label="@string/dummyLabel" />
+ <attribution android:tag="f977" android:label="@string/dummyLabel" />
+ <attribution android:tag="f978" android:label="@string/dummyLabel" />
+ <attribution android:tag="f979" android:label="@string/dummyLabel" />
+ <attribution android:tag="f980" android:label="@string/dummyLabel" />
+ <attribution android:tag="f981" android:label="@string/dummyLabel" />
+ <attribution android:tag="f982" android:label="@string/dummyLabel" />
+ <attribution android:tag="f983" android:label="@string/dummyLabel" />
+ <attribution android:tag="f984" android:label="@string/dummyLabel" />
+ <attribution android:tag="f985" android:label="@string/dummyLabel" />
+ <attribution android:tag="f986" android:label="@string/dummyLabel" />
+ <attribution android:tag="f987" android:label="@string/dummyLabel" />
+ <attribution android:tag="f988" android:label="@string/dummyLabel" />
+ <attribution android:tag="f989" android:label="@string/dummyLabel" />
+ <attribution android:tag="f990" android:label="@string/dummyLabel" />
+ <attribution android:tag="f991" android:label="@string/dummyLabel" />
+ <attribution android:tag="f992" android:label="@string/dummyLabel" />
+ <attribution android:tag="f993" android:label="@string/dummyLabel" />
+ <attribution android:tag="f994" android:label="@string/dummyLabel" />
+ <attribution android:tag="f995" android:label="@string/dummyLabel" />
+ <attribution android:tag="f996" android:label="@string/dummyLabel" />
+ <attribution android:tag="f997" android:label="@string/dummyLabel" />
+ <attribution android:tag="f998" android:label="@string/dummyLabel" />
+ <attribution android:tag="f999" android:label="@string/dummyLabel" />
+
+ <attribution android:tag="toomany" android:label="@string/dummyLabel" />
+
+ <application />
+
+</manifest>
diff --git a/tests/tests/appop/AppWithTooManyFeatures/res/values/strings.xml b/tests/tests/appop/AppWithTooManyAttributions/res/values/strings.xml
similarity index 100%
rename from tests/tests/appop/AppWithTooManyFeatures/res/values/strings.xml
rename to tests/tests/appop/AppWithTooManyAttributions/res/values/strings.xml
diff --git a/tests/tests/appop/AppWithTooManyFeatures/Android.bp b/tests/tests/appop/AppWithTooManyFeatures/Android.bp
deleted file mode 100644
index bc769d6..0000000
--- a/tests/tests/appop/AppWithTooManyFeatures/Android.bp
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright (C) 2020 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_helper_app {
- name: "AppWithTooManyFeatures",
-
- test_suites: [
- "cts",
- "vts",
- "general-tests",
- ]
-}
\ No newline at end of file
diff --git a/tests/tests/appop/AppWithTooManyFeatures/AndroidManifest.xml b/tests/tests/appop/AppWithTooManyFeatures/AndroidManifest.xml
deleted file mode 100644
index eeecef7..0000000
--- a/tests/tests/appop/AppWithTooManyFeatures/AndroidManifest.xml
+++ /dev/null
@@ -1,1028 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<!--
- ~ Copyright (C) 2020 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.app.appops.cts.appwithtoomanyfeatures">
-
- <!-- 1000 features are allowed -->
- <feature android:featureId="f0" android:label="@string/dummyLabel" />
- <feature android:featureId="f1" android:label="@string/dummyLabel" />
- <feature android:featureId="f2" android:label="@string/dummyLabel" />
- <feature android:featureId="f3" android:label="@string/dummyLabel" />
- <feature android:featureId="f4" android:label="@string/dummyLabel" />
- <feature android:featureId="f5" android:label="@string/dummyLabel" />
- <feature android:featureId="f6" android:label="@string/dummyLabel" />
- <feature android:featureId="f7" android:label="@string/dummyLabel" />
- <feature android:featureId="f8" android:label="@string/dummyLabel" />
- <feature android:featureId="f9" android:label="@string/dummyLabel" />
- <feature android:featureId="f10" android:label="@string/dummyLabel" />
- <feature android:featureId="f11" android:label="@string/dummyLabel" />
- <feature android:featureId="f12" android:label="@string/dummyLabel" />
- <feature android:featureId="f13" android:label="@string/dummyLabel" />
- <feature android:featureId="f14" android:label="@string/dummyLabel" />
- <feature android:featureId="f15" android:label="@string/dummyLabel" />
- <feature android:featureId="f16" android:label="@string/dummyLabel" />
- <feature android:featureId="f17" android:label="@string/dummyLabel" />
- <feature android:featureId="f18" android:label="@string/dummyLabel" />
- <feature android:featureId="f19" android:label="@string/dummyLabel" />
- <feature android:featureId="f20" android:label="@string/dummyLabel" />
- <feature android:featureId="f21" android:label="@string/dummyLabel" />
- <feature android:featureId="f22" android:label="@string/dummyLabel" />
- <feature android:featureId="f23" android:label="@string/dummyLabel" />
- <feature android:featureId="f24" android:label="@string/dummyLabel" />
- <feature android:featureId="f25" android:label="@string/dummyLabel" />
- <feature android:featureId="f26" android:label="@string/dummyLabel" />
- <feature android:featureId="f27" android:label="@string/dummyLabel" />
- <feature android:featureId="f28" android:label="@string/dummyLabel" />
- <feature android:featureId="f29" android:label="@string/dummyLabel" />
- <feature android:featureId="f30" android:label="@string/dummyLabel" />
- <feature android:featureId="f31" android:label="@string/dummyLabel" />
- <feature android:featureId="f32" android:label="@string/dummyLabel" />
- <feature android:featureId="f33" android:label="@string/dummyLabel" />
- <feature android:featureId="f34" android:label="@string/dummyLabel" />
- <feature android:featureId="f35" android:label="@string/dummyLabel" />
- <feature android:featureId="f36" android:label="@string/dummyLabel" />
- <feature android:featureId="f37" android:label="@string/dummyLabel" />
- <feature android:featureId="f38" android:label="@string/dummyLabel" />
- <feature android:featureId="f39" android:label="@string/dummyLabel" />
- <feature android:featureId="f40" android:label="@string/dummyLabel" />
- <feature android:featureId="f41" android:label="@string/dummyLabel" />
- <feature android:featureId="f42" android:label="@string/dummyLabel" />
- <feature android:featureId="f43" android:label="@string/dummyLabel" />
- <feature android:featureId="f44" android:label="@string/dummyLabel" />
- <feature android:featureId="f45" android:label="@string/dummyLabel" />
- <feature android:featureId="f46" android:label="@string/dummyLabel" />
- <feature android:featureId="f47" android:label="@string/dummyLabel" />
- <feature android:featureId="f48" android:label="@string/dummyLabel" />
- <feature android:featureId="f49" android:label="@string/dummyLabel" />
- <feature android:featureId="f50" android:label="@string/dummyLabel" />
- <feature android:featureId="f51" android:label="@string/dummyLabel" />
- <feature android:featureId="f52" android:label="@string/dummyLabel" />
- <feature android:featureId="f53" android:label="@string/dummyLabel" />
- <feature android:featureId="f54" android:label="@string/dummyLabel" />
- <feature android:featureId="f55" android:label="@string/dummyLabel" />
- <feature android:featureId="f56" android:label="@string/dummyLabel" />
- <feature android:featureId="f57" android:label="@string/dummyLabel" />
- <feature android:featureId="f58" android:label="@string/dummyLabel" />
- <feature android:featureId="f59" android:label="@string/dummyLabel" />
- <feature android:featureId="f60" android:label="@string/dummyLabel" />
- <feature android:featureId="f61" android:label="@string/dummyLabel" />
- <feature android:featureId="f62" android:label="@string/dummyLabel" />
- <feature android:featureId="f63" android:label="@string/dummyLabel" />
- <feature android:featureId="f64" android:label="@string/dummyLabel" />
- <feature android:featureId="f65" android:label="@string/dummyLabel" />
- <feature android:featureId="f66" android:label="@string/dummyLabel" />
- <feature android:featureId="f67" android:label="@string/dummyLabel" />
- <feature android:featureId="f68" android:label="@string/dummyLabel" />
- <feature android:featureId="f69" android:label="@string/dummyLabel" />
- <feature android:featureId="f70" android:label="@string/dummyLabel" />
- <feature android:featureId="f71" android:label="@string/dummyLabel" />
- <feature android:featureId="f72" android:label="@string/dummyLabel" />
- <feature android:featureId="f73" android:label="@string/dummyLabel" />
- <feature android:featureId="f74" android:label="@string/dummyLabel" />
- <feature android:featureId="f75" android:label="@string/dummyLabel" />
- <feature android:featureId="f76" android:label="@string/dummyLabel" />
- <feature android:featureId="f77" android:label="@string/dummyLabel" />
- <feature android:featureId="f78" android:label="@string/dummyLabel" />
- <feature android:featureId="f79" android:label="@string/dummyLabel" />
- <feature android:featureId="f80" android:label="@string/dummyLabel" />
- <feature android:featureId="f81" android:label="@string/dummyLabel" />
- <feature android:featureId="f82" android:label="@string/dummyLabel" />
- <feature android:featureId="f83" android:label="@string/dummyLabel" />
- <feature android:featureId="f84" android:label="@string/dummyLabel" />
- <feature android:featureId="f85" android:label="@string/dummyLabel" />
- <feature android:featureId="f86" android:label="@string/dummyLabel" />
- <feature android:featureId="f87" android:label="@string/dummyLabel" />
- <feature android:featureId="f88" android:label="@string/dummyLabel" />
- <feature android:featureId="f89" android:label="@string/dummyLabel" />
- <feature android:featureId="f90" android:label="@string/dummyLabel" />
- <feature android:featureId="f91" android:label="@string/dummyLabel" />
- <feature android:featureId="f92" android:label="@string/dummyLabel" />
- <feature android:featureId="f93" android:label="@string/dummyLabel" />
- <feature android:featureId="f94" android:label="@string/dummyLabel" />
- <feature android:featureId="f95" android:label="@string/dummyLabel" />
- <feature android:featureId="f96" android:label="@string/dummyLabel" />
- <feature android:featureId="f97" android:label="@string/dummyLabel" />
- <feature android:featureId="f98" android:label="@string/dummyLabel" />
- <feature android:featureId="f99" android:label="@string/dummyLabel" />
- <feature android:featureId="f100" android:label="@string/dummyLabel" />
- <feature android:featureId="f101" android:label="@string/dummyLabel" />
- <feature android:featureId="f102" android:label="@string/dummyLabel" />
- <feature android:featureId="f103" android:label="@string/dummyLabel" />
- <feature android:featureId="f104" android:label="@string/dummyLabel" />
- <feature android:featureId="f105" android:label="@string/dummyLabel" />
- <feature android:featureId="f106" android:label="@string/dummyLabel" />
- <feature android:featureId="f107" android:label="@string/dummyLabel" />
- <feature android:featureId="f108" android:label="@string/dummyLabel" />
- <feature android:featureId="f109" android:label="@string/dummyLabel" />
- <feature android:featureId="f110" android:label="@string/dummyLabel" />
- <feature android:featureId="f111" android:label="@string/dummyLabel" />
- <feature android:featureId="f112" android:label="@string/dummyLabel" />
- <feature android:featureId="f113" android:label="@string/dummyLabel" />
- <feature android:featureId="f114" android:label="@string/dummyLabel" />
- <feature android:featureId="f115" android:label="@string/dummyLabel" />
- <feature android:featureId="f116" android:label="@string/dummyLabel" />
- <feature android:featureId="f117" android:label="@string/dummyLabel" />
- <feature android:featureId="f118" android:label="@string/dummyLabel" />
- <feature android:featureId="f119" android:label="@string/dummyLabel" />
- <feature android:featureId="f120" android:label="@string/dummyLabel" />
- <feature android:featureId="f121" android:label="@string/dummyLabel" />
- <feature android:featureId="f122" android:label="@string/dummyLabel" />
- <feature android:featureId="f123" android:label="@string/dummyLabel" />
- <feature android:featureId="f124" android:label="@string/dummyLabel" />
- <feature android:featureId="f125" android:label="@string/dummyLabel" />
- <feature android:featureId="f126" android:label="@string/dummyLabel" />
- <feature android:featureId="f127" android:label="@string/dummyLabel" />
- <feature android:featureId="f128" android:label="@string/dummyLabel" />
- <feature android:featureId="f129" android:label="@string/dummyLabel" />
- <feature android:featureId="f130" android:label="@string/dummyLabel" />
- <feature android:featureId="f131" android:label="@string/dummyLabel" />
- <feature android:featureId="f132" android:label="@string/dummyLabel" />
- <feature android:featureId="f133" android:label="@string/dummyLabel" />
- <feature android:featureId="f134" android:label="@string/dummyLabel" />
- <feature android:featureId="f135" android:label="@string/dummyLabel" />
- <feature android:featureId="f136" android:label="@string/dummyLabel" />
- <feature android:featureId="f137" android:label="@string/dummyLabel" />
- <feature android:featureId="f138" android:label="@string/dummyLabel" />
- <feature android:featureId="f139" android:label="@string/dummyLabel" />
- <feature android:featureId="f140" android:label="@string/dummyLabel" />
- <feature android:featureId="f141" android:label="@string/dummyLabel" />
- <feature android:featureId="f142" android:label="@string/dummyLabel" />
- <feature android:featureId="f143" android:label="@string/dummyLabel" />
- <feature android:featureId="f144" android:label="@string/dummyLabel" />
- <feature android:featureId="f145" android:label="@string/dummyLabel" />
- <feature android:featureId="f146" android:label="@string/dummyLabel" />
- <feature android:featureId="f147" android:label="@string/dummyLabel" />
- <feature android:featureId="f148" android:label="@string/dummyLabel" />
- <feature android:featureId="f149" android:label="@string/dummyLabel" />
- <feature android:featureId="f150" android:label="@string/dummyLabel" />
- <feature android:featureId="f151" android:label="@string/dummyLabel" />
- <feature android:featureId="f152" android:label="@string/dummyLabel" />
- <feature android:featureId="f153" android:label="@string/dummyLabel" />
- <feature android:featureId="f154" android:label="@string/dummyLabel" />
- <feature android:featureId="f155" android:label="@string/dummyLabel" />
- <feature android:featureId="f156" android:label="@string/dummyLabel" />
- <feature android:featureId="f157" android:label="@string/dummyLabel" />
- <feature android:featureId="f158" android:label="@string/dummyLabel" />
- <feature android:featureId="f159" android:label="@string/dummyLabel" />
- <feature android:featureId="f160" android:label="@string/dummyLabel" />
- <feature android:featureId="f161" android:label="@string/dummyLabel" />
- <feature android:featureId="f162" android:label="@string/dummyLabel" />
- <feature android:featureId="f163" android:label="@string/dummyLabel" />
- <feature android:featureId="f164" android:label="@string/dummyLabel" />
- <feature android:featureId="f165" android:label="@string/dummyLabel" />
- <feature android:featureId="f166" android:label="@string/dummyLabel" />
- <feature android:featureId="f167" android:label="@string/dummyLabel" />
- <feature android:featureId="f168" android:label="@string/dummyLabel" />
- <feature android:featureId="f169" android:label="@string/dummyLabel" />
- <feature android:featureId="f170" android:label="@string/dummyLabel" />
- <feature android:featureId="f171" android:label="@string/dummyLabel" />
- <feature android:featureId="f172" android:label="@string/dummyLabel" />
- <feature android:featureId="f173" android:label="@string/dummyLabel" />
- <feature android:featureId="f174" android:label="@string/dummyLabel" />
- <feature android:featureId="f175" android:label="@string/dummyLabel" />
- <feature android:featureId="f176" android:label="@string/dummyLabel" />
- <feature android:featureId="f177" android:label="@string/dummyLabel" />
- <feature android:featureId="f178" android:label="@string/dummyLabel" />
- <feature android:featureId="f179" android:label="@string/dummyLabel" />
- <feature android:featureId="f180" android:label="@string/dummyLabel" />
- <feature android:featureId="f181" android:label="@string/dummyLabel" />
- <feature android:featureId="f182" android:label="@string/dummyLabel" />
- <feature android:featureId="f183" android:label="@string/dummyLabel" />
- <feature android:featureId="f184" android:label="@string/dummyLabel" />
- <feature android:featureId="f185" android:label="@string/dummyLabel" />
- <feature android:featureId="f186" android:label="@string/dummyLabel" />
- <feature android:featureId="f187" android:label="@string/dummyLabel" />
- <feature android:featureId="f188" android:label="@string/dummyLabel" />
- <feature android:featureId="f189" android:label="@string/dummyLabel" />
- <feature android:featureId="f190" android:label="@string/dummyLabel" />
- <feature android:featureId="f191" android:label="@string/dummyLabel" />
- <feature android:featureId="f192" android:label="@string/dummyLabel" />
- <feature android:featureId="f193" android:label="@string/dummyLabel" />
- <feature android:featureId="f194" android:label="@string/dummyLabel" />
- <feature android:featureId="f195" android:label="@string/dummyLabel" />
- <feature android:featureId="f196" android:label="@string/dummyLabel" />
- <feature android:featureId="f197" android:label="@string/dummyLabel" />
- <feature android:featureId="f198" android:label="@string/dummyLabel" />
- <feature android:featureId="f199" android:label="@string/dummyLabel" />
- <feature android:featureId="f200" android:label="@string/dummyLabel" />
- <feature android:featureId="f201" android:label="@string/dummyLabel" />
- <feature android:featureId="f202" android:label="@string/dummyLabel" />
- <feature android:featureId="f203" android:label="@string/dummyLabel" />
- <feature android:featureId="f204" android:label="@string/dummyLabel" />
- <feature android:featureId="f205" android:label="@string/dummyLabel" />
- <feature android:featureId="f206" android:label="@string/dummyLabel" />
- <feature android:featureId="f207" android:label="@string/dummyLabel" />
- <feature android:featureId="f208" android:label="@string/dummyLabel" />
- <feature android:featureId="f209" android:label="@string/dummyLabel" />
- <feature android:featureId="f210" android:label="@string/dummyLabel" />
- <feature android:featureId="f211" android:label="@string/dummyLabel" />
- <feature android:featureId="f212" android:label="@string/dummyLabel" />
- <feature android:featureId="f213" android:label="@string/dummyLabel" />
- <feature android:featureId="f214" android:label="@string/dummyLabel" />
- <feature android:featureId="f215" android:label="@string/dummyLabel" />
- <feature android:featureId="f216" android:label="@string/dummyLabel" />
- <feature android:featureId="f217" android:label="@string/dummyLabel" />
- <feature android:featureId="f218" android:label="@string/dummyLabel" />
- <feature android:featureId="f219" android:label="@string/dummyLabel" />
- <feature android:featureId="f220" android:label="@string/dummyLabel" />
- <feature android:featureId="f221" android:label="@string/dummyLabel" />
- <feature android:featureId="f222" android:label="@string/dummyLabel" />
- <feature android:featureId="f223" android:label="@string/dummyLabel" />
- <feature android:featureId="f224" android:label="@string/dummyLabel" />
- <feature android:featureId="f225" android:label="@string/dummyLabel" />
- <feature android:featureId="f226" android:label="@string/dummyLabel" />
- <feature android:featureId="f227" android:label="@string/dummyLabel" />
- <feature android:featureId="f228" android:label="@string/dummyLabel" />
- <feature android:featureId="f229" android:label="@string/dummyLabel" />
- <feature android:featureId="f230" android:label="@string/dummyLabel" />
- <feature android:featureId="f231" android:label="@string/dummyLabel" />
- <feature android:featureId="f232" android:label="@string/dummyLabel" />
- <feature android:featureId="f233" android:label="@string/dummyLabel" />
- <feature android:featureId="f234" android:label="@string/dummyLabel" />
- <feature android:featureId="f235" android:label="@string/dummyLabel" />
- <feature android:featureId="f236" android:label="@string/dummyLabel" />
- <feature android:featureId="f237" android:label="@string/dummyLabel" />
- <feature android:featureId="f238" android:label="@string/dummyLabel" />
- <feature android:featureId="f239" android:label="@string/dummyLabel" />
- <feature android:featureId="f240" android:label="@string/dummyLabel" />
- <feature android:featureId="f241" android:label="@string/dummyLabel" />
- <feature android:featureId="f242" android:label="@string/dummyLabel" />
- <feature android:featureId="f243" android:label="@string/dummyLabel" />
- <feature android:featureId="f244" android:label="@string/dummyLabel" />
- <feature android:featureId="f245" android:label="@string/dummyLabel" />
- <feature android:featureId="f246" android:label="@string/dummyLabel" />
- <feature android:featureId="f247" android:label="@string/dummyLabel" />
- <feature android:featureId="f248" android:label="@string/dummyLabel" />
- <feature android:featureId="f249" android:label="@string/dummyLabel" />
- <feature android:featureId="f250" android:label="@string/dummyLabel" />
- <feature android:featureId="f251" android:label="@string/dummyLabel" />
- <feature android:featureId="f252" android:label="@string/dummyLabel" />
- <feature android:featureId="f253" android:label="@string/dummyLabel" />
- <feature android:featureId="f254" android:label="@string/dummyLabel" />
- <feature android:featureId="f255" android:label="@string/dummyLabel" />
- <feature android:featureId="f256" android:label="@string/dummyLabel" />
- <feature android:featureId="f257" android:label="@string/dummyLabel" />
- <feature android:featureId="f258" android:label="@string/dummyLabel" />
- <feature android:featureId="f259" android:label="@string/dummyLabel" />
- <feature android:featureId="f260" android:label="@string/dummyLabel" />
- <feature android:featureId="f261" android:label="@string/dummyLabel" />
- <feature android:featureId="f262" android:label="@string/dummyLabel" />
- <feature android:featureId="f263" android:label="@string/dummyLabel" />
- <feature android:featureId="f264" android:label="@string/dummyLabel" />
- <feature android:featureId="f265" android:label="@string/dummyLabel" />
- <feature android:featureId="f266" android:label="@string/dummyLabel" />
- <feature android:featureId="f267" android:label="@string/dummyLabel" />
- <feature android:featureId="f268" android:label="@string/dummyLabel" />
- <feature android:featureId="f269" android:label="@string/dummyLabel" />
- <feature android:featureId="f270" android:label="@string/dummyLabel" />
- <feature android:featureId="f271" android:label="@string/dummyLabel" />
- <feature android:featureId="f272" android:label="@string/dummyLabel" />
- <feature android:featureId="f273" android:label="@string/dummyLabel" />
- <feature android:featureId="f274" android:label="@string/dummyLabel" />
- <feature android:featureId="f275" android:label="@string/dummyLabel" />
- <feature android:featureId="f276" android:label="@string/dummyLabel" />
- <feature android:featureId="f277" android:label="@string/dummyLabel" />
- <feature android:featureId="f278" android:label="@string/dummyLabel" />
- <feature android:featureId="f279" android:label="@string/dummyLabel" />
- <feature android:featureId="f280" android:label="@string/dummyLabel" />
- <feature android:featureId="f281" android:label="@string/dummyLabel" />
- <feature android:featureId="f282" android:label="@string/dummyLabel" />
- <feature android:featureId="f283" android:label="@string/dummyLabel" />
- <feature android:featureId="f284" android:label="@string/dummyLabel" />
- <feature android:featureId="f285" android:label="@string/dummyLabel" />
- <feature android:featureId="f286" android:label="@string/dummyLabel" />
- <feature android:featureId="f287" android:label="@string/dummyLabel" />
- <feature android:featureId="f288" android:label="@string/dummyLabel" />
- <feature android:featureId="f289" android:label="@string/dummyLabel" />
- <feature android:featureId="f290" android:label="@string/dummyLabel" />
- <feature android:featureId="f291" android:label="@string/dummyLabel" />
- <feature android:featureId="f292" android:label="@string/dummyLabel" />
- <feature android:featureId="f293" android:label="@string/dummyLabel" />
- <feature android:featureId="f294" android:label="@string/dummyLabel" />
- <feature android:featureId="f295" android:label="@string/dummyLabel" />
- <feature android:featureId="f296" android:label="@string/dummyLabel" />
- <feature android:featureId="f297" android:label="@string/dummyLabel" />
- <feature android:featureId="f298" android:label="@string/dummyLabel" />
- <feature android:featureId="f299" android:label="@string/dummyLabel" />
- <feature android:featureId="f300" android:label="@string/dummyLabel" />
- <feature android:featureId="f301" android:label="@string/dummyLabel" />
- <feature android:featureId="f302" android:label="@string/dummyLabel" />
- <feature android:featureId="f303" android:label="@string/dummyLabel" />
- <feature android:featureId="f304" android:label="@string/dummyLabel" />
- <feature android:featureId="f305" android:label="@string/dummyLabel" />
- <feature android:featureId="f306" android:label="@string/dummyLabel" />
- <feature android:featureId="f307" android:label="@string/dummyLabel" />
- <feature android:featureId="f308" android:label="@string/dummyLabel" />
- <feature android:featureId="f309" android:label="@string/dummyLabel" />
- <feature android:featureId="f310" android:label="@string/dummyLabel" />
- <feature android:featureId="f311" android:label="@string/dummyLabel" />
- <feature android:featureId="f312" android:label="@string/dummyLabel" />
- <feature android:featureId="f313" android:label="@string/dummyLabel" />
- <feature android:featureId="f314" android:label="@string/dummyLabel" />
- <feature android:featureId="f315" android:label="@string/dummyLabel" />
- <feature android:featureId="f316" android:label="@string/dummyLabel" />
- <feature android:featureId="f317" android:label="@string/dummyLabel" />
- <feature android:featureId="f318" android:label="@string/dummyLabel" />
- <feature android:featureId="f319" android:label="@string/dummyLabel" />
- <feature android:featureId="f320" android:label="@string/dummyLabel" />
- <feature android:featureId="f321" android:label="@string/dummyLabel" />
- <feature android:featureId="f322" android:label="@string/dummyLabel" />
- <feature android:featureId="f323" android:label="@string/dummyLabel" />
- <feature android:featureId="f324" android:label="@string/dummyLabel" />
- <feature android:featureId="f325" android:label="@string/dummyLabel" />
- <feature android:featureId="f326" android:label="@string/dummyLabel" />
- <feature android:featureId="f327" android:label="@string/dummyLabel" />
- <feature android:featureId="f328" android:label="@string/dummyLabel" />
- <feature android:featureId="f329" android:label="@string/dummyLabel" />
- <feature android:featureId="f330" android:label="@string/dummyLabel" />
- <feature android:featureId="f331" android:label="@string/dummyLabel" />
- <feature android:featureId="f332" android:label="@string/dummyLabel" />
- <feature android:featureId="f333" android:label="@string/dummyLabel" />
- <feature android:featureId="f334" android:label="@string/dummyLabel" />
- <feature android:featureId="f335" android:label="@string/dummyLabel" />
- <feature android:featureId="f336" android:label="@string/dummyLabel" />
- <feature android:featureId="f337" android:label="@string/dummyLabel" />
- <feature android:featureId="f338" android:label="@string/dummyLabel" />
- <feature android:featureId="f339" android:label="@string/dummyLabel" />
- <feature android:featureId="f340" android:label="@string/dummyLabel" />
- <feature android:featureId="f341" android:label="@string/dummyLabel" />
- <feature android:featureId="f342" android:label="@string/dummyLabel" />
- <feature android:featureId="f343" android:label="@string/dummyLabel" />
- <feature android:featureId="f344" android:label="@string/dummyLabel" />
- <feature android:featureId="f345" android:label="@string/dummyLabel" />
- <feature android:featureId="f346" android:label="@string/dummyLabel" />
- <feature android:featureId="f347" android:label="@string/dummyLabel" />
- <feature android:featureId="f348" android:label="@string/dummyLabel" />
- <feature android:featureId="f349" android:label="@string/dummyLabel" />
- <feature android:featureId="f350" android:label="@string/dummyLabel" />
- <feature android:featureId="f351" android:label="@string/dummyLabel" />
- <feature android:featureId="f352" android:label="@string/dummyLabel" />
- <feature android:featureId="f353" android:label="@string/dummyLabel" />
- <feature android:featureId="f354" android:label="@string/dummyLabel" />
- <feature android:featureId="f355" android:label="@string/dummyLabel" />
- <feature android:featureId="f356" android:label="@string/dummyLabel" />
- <feature android:featureId="f357" android:label="@string/dummyLabel" />
- <feature android:featureId="f358" android:label="@string/dummyLabel" />
- <feature android:featureId="f359" android:label="@string/dummyLabel" />
- <feature android:featureId="f360" android:label="@string/dummyLabel" />
- <feature android:featureId="f361" android:label="@string/dummyLabel" />
- <feature android:featureId="f362" android:label="@string/dummyLabel" />
- <feature android:featureId="f363" android:label="@string/dummyLabel" />
- <feature android:featureId="f364" android:label="@string/dummyLabel" />
- <feature android:featureId="f365" android:label="@string/dummyLabel" />
- <feature android:featureId="f366" android:label="@string/dummyLabel" />
- <feature android:featureId="f367" android:label="@string/dummyLabel" />
- <feature android:featureId="f368" android:label="@string/dummyLabel" />
- <feature android:featureId="f369" android:label="@string/dummyLabel" />
- <feature android:featureId="f370" android:label="@string/dummyLabel" />
- <feature android:featureId="f371" android:label="@string/dummyLabel" />
- <feature android:featureId="f372" android:label="@string/dummyLabel" />
- <feature android:featureId="f373" android:label="@string/dummyLabel" />
- <feature android:featureId="f374" android:label="@string/dummyLabel" />
- <feature android:featureId="f375" android:label="@string/dummyLabel" />
- <feature android:featureId="f376" android:label="@string/dummyLabel" />
- <feature android:featureId="f377" android:label="@string/dummyLabel" />
- <feature android:featureId="f378" android:label="@string/dummyLabel" />
- <feature android:featureId="f379" android:label="@string/dummyLabel" />
- <feature android:featureId="f380" android:label="@string/dummyLabel" />
- <feature android:featureId="f381" android:label="@string/dummyLabel" />
- <feature android:featureId="f382" android:label="@string/dummyLabel" />
- <feature android:featureId="f383" android:label="@string/dummyLabel" />
- <feature android:featureId="f384" android:label="@string/dummyLabel" />
- <feature android:featureId="f385" android:label="@string/dummyLabel" />
- <feature android:featureId="f386" android:label="@string/dummyLabel" />
- <feature android:featureId="f387" android:label="@string/dummyLabel" />
- <feature android:featureId="f388" android:label="@string/dummyLabel" />
- <feature android:featureId="f389" android:label="@string/dummyLabel" />
- <feature android:featureId="f390" android:label="@string/dummyLabel" />
- <feature android:featureId="f391" android:label="@string/dummyLabel" />
- <feature android:featureId="f392" android:label="@string/dummyLabel" />
- <feature android:featureId="f393" android:label="@string/dummyLabel" />
- <feature android:featureId="f394" android:label="@string/dummyLabel" />
- <feature android:featureId="f395" android:label="@string/dummyLabel" />
- <feature android:featureId="f396" android:label="@string/dummyLabel" />
- <feature android:featureId="f397" android:label="@string/dummyLabel" />
- <feature android:featureId="f398" android:label="@string/dummyLabel" />
- <feature android:featureId="f399" android:label="@string/dummyLabel" />
- <feature android:featureId="f400" android:label="@string/dummyLabel" />
- <feature android:featureId="f401" android:label="@string/dummyLabel" />
- <feature android:featureId="f402" android:label="@string/dummyLabel" />
- <feature android:featureId="f403" android:label="@string/dummyLabel" />
- <feature android:featureId="f404" android:label="@string/dummyLabel" />
- <feature android:featureId="f405" android:label="@string/dummyLabel" />
- <feature android:featureId="f406" android:label="@string/dummyLabel" />
- <feature android:featureId="f407" android:label="@string/dummyLabel" />
- <feature android:featureId="f408" android:label="@string/dummyLabel" />
- <feature android:featureId="f409" android:label="@string/dummyLabel" />
- <feature android:featureId="f410" android:label="@string/dummyLabel" />
- <feature android:featureId="f411" android:label="@string/dummyLabel" />
- <feature android:featureId="f412" android:label="@string/dummyLabel" />
- <feature android:featureId="f413" android:label="@string/dummyLabel" />
- <feature android:featureId="f414" android:label="@string/dummyLabel" />
- <feature android:featureId="f415" android:label="@string/dummyLabel" />
- <feature android:featureId="f416" android:label="@string/dummyLabel" />
- <feature android:featureId="f417" android:label="@string/dummyLabel" />
- <feature android:featureId="f418" android:label="@string/dummyLabel" />
- <feature android:featureId="f419" android:label="@string/dummyLabel" />
- <feature android:featureId="f420" android:label="@string/dummyLabel" />
- <feature android:featureId="f421" android:label="@string/dummyLabel" />
- <feature android:featureId="f422" android:label="@string/dummyLabel" />
- <feature android:featureId="f423" android:label="@string/dummyLabel" />
- <feature android:featureId="f424" android:label="@string/dummyLabel" />
- <feature android:featureId="f425" android:label="@string/dummyLabel" />
- <feature android:featureId="f426" android:label="@string/dummyLabel" />
- <feature android:featureId="f427" android:label="@string/dummyLabel" />
- <feature android:featureId="f428" android:label="@string/dummyLabel" />
- <feature android:featureId="f429" android:label="@string/dummyLabel" />
- <feature android:featureId="f430" android:label="@string/dummyLabel" />
- <feature android:featureId="f431" android:label="@string/dummyLabel" />
- <feature android:featureId="f432" android:label="@string/dummyLabel" />
- <feature android:featureId="f433" android:label="@string/dummyLabel" />
- <feature android:featureId="f434" android:label="@string/dummyLabel" />
- <feature android:featureId="f435" android:label="@string/dummyLabel" />
- <feature android:featureId="f436" android:label="@string/dummyLabel" />
- <feature android:featureId="f437" android:label="@string/dummyLabel" />
- <feature android:featureId="f438" android:label="@string/dummyLabel" />
- <feature android:featureId="f439" android:label="@string/dummyLabel" />
- <feature android:featureId="f440" android:label="@string/dummyLabel" />
- <feature android:featureId="f441" android:label="@string/dummyLabel" />
- <feature android:featureId="f442" android:label="@string/dummyLabel" />
- <feature android:featureId="f443" android:label="@string/dummyLabel" />
- <feature android:featureId="f444" android:label="@string/dummyLabel" />
- <feature android:featureId="f445" android:label="@string/dummyLabel" />
- <feature android:featureId="f446" android:label="@string/dummyLabel" />
- <feature android:featureId="f447" android:label="@string/dummyLabel" />
- <feature android:featureId="f448" android:label="@string/dummyLabel" />
- <feature android:featureId="f449" android:label="@string/dummyLabel" />
- <feature android:featureId="f450" android:label="@string/dummyLabel" />
- <feature android:featureId="f451" android:label="@string/dummyLabel" />
- <feature android:featureId="f452" android:label="@string/dummyLabel" />
- <feature android:featureId="f453" android:label="@string/dummyLabel" />
- <feature android:featureId="f454" android:label="@string/dummyLabel" />
- <feature android:featureId="f455" android:label="@string/dummyLabel" />
- <feature android:featureId="f456" android:label="@string/dummyLabel" />
- <feature android:featureId="f457" android:label="@string/dummyLabel" />
- <feature android:featureId="f458" android:label="@string/dummyLabel" />
- <feature android:featureId="f459" android:label="@string/dummyLabel" />
- <feature android:featureId="f460" android:label="@string/dummyLabel" />
- <feature android:featureId="f461" android:label="@string/dummyLabel" />
- <feature android:featureId="f462" android:label="@string/dummyLabel" />
- <feature android:featureId="f463" android:label="@string/dummyLabel" />
- <feature android:featureId="f464" android:label="@string/dummyLabel" />
- <feature android:featureId="f465" android:label="@string/dummyLabel" />
- <feature android:featureId="f466" android:label="@string/dummyLabel" />
- <feature android:featureId="f467" android:label="@string/dummyLabel" />
- <feature android:featureId="f468" android:label="@string/dummyLabel" />
- <feature android:featureId="f469" android:label="@string/dummyLabel" />
- <feature android:featureId="f470" android:label="@string/dummyLabel" />
- <feature android:featureId="f471" android:label="@string/dummyLabel" />
- <feature android:featureId="f472" android:label="@string/dummyLabel" />
- <feature android:featureId="f473" android:label="@string/dummyLabel" />
- <feature android:featureId="f474" android:label="@string/dummyLabel" />
- <feature android:featureId="f475" android:label="@string/dummyLabel" />
- <feature android:featureId="f476" android:label="@string/dummyLabel" />
- <feature android:featureId="f477" android:label="@string/dummyLabel" />
- <feature android:featureId="f478" android:label="@string/dummyLabel" />
- <feature android:featureId="f479" android:label="@string/dummyLabel" />
- <feature android:featureId="f480" android:label="@string/dummyLabel" />
- <feature android:featureId="f481" android:label="@string/dummyLabel" />
- <feature android:featureId="f482" android:label="@string/dummyLabel" />
- <feature android:featureId="f483" android:label="@string/dummyLabel" />
- <feature android:featureId="f484" android:label="@string/dummyLabel" />
- <feature android:featureId="f485" android:label="@string/dummyLabel" />
- <feature android:featureId="f486" android:label="@string/dummyLabel" />
- <feature android:featureId="f487" android:label="@string/dummyLabel" />
- <feature android:featureId="f488" android:label="@string/dummyLabel" />
- <feature android:featureId="f489" android:label="@string/dummyLabel" />
- <feature android:featureId="f490" android:label="@string/dummyLabel" />
- <feature android:featureId="f491" android:label="@string/dummyLabel" />
- <feature android:featureId="f492" android:label="@string/dummyLabel" />
- <feature android:featureId="f493" android:label="@string/dummyLabel" />
- <feature android:featureId="f494" android:label="@string/dummyLabel" />
- <feature android:featureId="f495" android:label="@string/dummyLabel" />
- <feature android:featureId="f496" android:label="@string/dummyLabel" />
- <feature android:featureId="f497" android:label="@string/dummyLabel" />
- <feature android:featureId="f498" android:label="@string/dummyLabel" />
- <feature android:featureId="f499" android:label="@string/dummyLabel" />
- <feature android:featureId="f500" android:label="@string/dummyLabel" />
- <feature android:featureId="f501" android:label="@string/dummyLabel" />
- <feature android:featureId="f502" android:label="@string/dummyLabel" />
- <feature android:featureId="f503" android:label="@string/dummyLabel" />
- <feature android:featureId="f504" android:label="@string/dummyLabel" />
- <feature android:featureId="f505" android:label="@string/dummyLabel" />
- <feature android:featureId="f506" android:label="@string/dummyLabel" />
- <feature android:featureId="f507" android:label="@string/dummyLabel" />
- <feature android:featureId="f508" android:label="@string/dummyLabel" />
- <feature android:featureId="f509" android:label="@string/dummyLabel" />
- <feature android:featureId="f510" android:label="@string/dummyLabel" />
- <feature android:featureId="f511" android:label="@string/dummyLabel" />
- <feature android:featureId="f512" android:label="@string/dummyLabel" />
- <feature android:featureId="f513" android:label="@string/dummyLabel" />
- <feature android:featureId="f514" android:label="@string/dummyLabel" />
- <feature android:featureId="f515" android:label="@string/dummyLabel" />
- <feature android:featureId="f516" android:label="@string/dummyLabel" />
- <feature android:featureId="f517" android:label="@string/dummyLabel" />
- <feature android:featureId="f518" android:label="@string/dummyLabel" />
- <feature android:featureId="f519" android:label="@string/dummyLabel" />
- <feature android:featureId="f520" android:label="@string/dummyLabel" />
- <feature android:featureId="f521" android:label="@string/dummyLabel" />
- <feature android:featureId="f522" android:label="@string/dummyLabel" />
- <feature android:featureId="f523" android:label="@string/dummyLabel" />
- <feature android:featureId="f524" android:label="@string/dummyLabel" />
- <feature android:featureId="f525" android:label="@string/dummyLabel" />
- <feature android:featureId="f526" android:label="@string/dummyLabel" />
- <feature android:featureId="f527" android:label="@string/dummyLabel" />
- <feature android:featureId="f528" android:label="@string/dummyLabel" />
- <feature android:featureId="f529" android:label="@string/dummyLabel" />
- <feature android:featureId="f530" android:label="@string/dummyLabel" />
- <feature android:featureId="f531" android:label="@string/dummyLabel" />
- <feature android:featureId="f532" android:label="@string/dummyLabel" />
- <feature android:featureId="f533" android:label="@string/dummyLabel" />
- <feature android:featureId="f534" android:label="@string/dummyLabel" />
- <feature android:featureId="f535" android:label="@string/dummyLabel" />
- <feature android:featureId="f536" android:label="@string/dummyLabel" />
- <feature android:featureId="f537" android:label="@string/dummyLabel" />
- <feature android:featureId="f538" android:label="@string/dummyLabel" />
- <feature android:featureId="f539" android:label="@string/dummyLabel" />
- <feature android:featureId="f540" android:label="@string/dummyLabel" />
- <feature android:featureId="f541" android:label="@string/dummyLabel" />
- <feature android:featureId="f542" android:label="@string/dummyLabel" />
- <feature android:featureId="f543" android:label="@string/dummyLabel" />
- <feature android:featureId="f544" android:label="@string/dummyLabel" />
- <feature android:featureId="f545" android:label="@string/dummyLabel" />
- <feature android:featureId="f546" android:label="@string/dummyLabel" />
- <feature android:featureId="f547" android:label="@string/dummyLabel" />
- <feature android:featureId="f548" android:label="@string/dummyLabel" />
- <feature android:featureId="f549" android:label="@string/dummyLabel" />
- <feature android:featureId="f550" android:label="@string/dummyLabel" />
- <feature android:featureId="f551" android:label="@string/dummyLabel" />
- <feature android:featureId="f552" android:label="@string/dummyLabel" />
- <feature android:featureId="f553" android:label="@string/dummyLabel" />
- <feature android:featureId="f554" android:label="@string/dummyLabel" />
- <feature android:featureId="f555" android:label="@string/dummyLabel" />
- <feature android:featureId="f556" android:label="@string/dummyLabel" />
- <feature android:featureId="f557" android:label="@string/dummyLabel" />
- <feature android:featureId="f558" android:label="@string/dummyLabel" />
- <feature android:featureId="f559" android:label="@string/dummyLabel" />
- <feature android:featureId="f560" android:label="@string/dummyLabel" />
- <feature android:featureId="f561" android:label="@string/dummyLabel" />
- <feature android:featureId="f562" android:label="@string/dummyLabel" />
- <feature android:featureId="f563" android:label="@string/dummyLabel" />
- <feature android:featureId="f564" android:label="@string/dummyLabel" />
- <feature android:featureId="f565" android:label="@string/dummyLabel" />
- <feature android:featureId="f566" android:label="@string/dummyLabel" />
- <feature android:featureId="f567" android:label="@string/dummyLabel" />
- <feature android:featureId="f568" android:label="@string/dummyLabel" />
- <feature android:featureId="f569" android:label="@string/dummyLabel" />
- <feature android:featureId="f570" android:label="@string/dummyLabel" />
- <feature android:featureId="f571" android:label="@string/dummyLabel" />
- <feature android:featureId="f572" android:label="@string/dummyLabel" />
- <feature android:featureId="f573" android:label="@string/dummyLabel" />
- <feature android:featureId="f574" android:label="@string/dummyLabel" />
- <feature android:featureId="f575" android:label="@string/dummyLabel" />
- <feature android:featureId="f576" android:label="@string/dummyLabel" />
- <feature android:featureId="f577" android:label="@string/dummyLabel" />
- <feature android:featureId="f578" android:label="@string/dummyLabel" />
- <feature android:featureId="f579" android:label="@string/dummyLabel" />
- <feature android:featureId="f580" android:label="@string/dummyLabel" />
- <feature android:featureId="f581" android:label="@string/dummyLabel" />
- <feature android:featureId="f582" android:label="@string/dummyLabel" />
- <feature android:featureId="f583" android:label="@string/dummyLabel" />
- <feature android:featureId="f584" android:label="@string/dummyLabel" />
- <feature android:featureId="f585" android:label="@string/dummyLabel" />
- <feature android:featureId="f586" android:label="@string/dummyLabel" />
- <feature android:featureId="f587" android:label="@string/dummyLabel" />
- <feature android:featureId="f588" android:label="@string/dummyLabel" />
- <feature android:featureId="f589" android:label="@string/dummyLabel" />
- <feature android:featureId="f590" android:label="@string/dummyLabel" />
- <feature android:featureId="f591" android:label="@string/dummyLabel" />
- <feature android:featureId="f592" android:label="@string/dummyLabel" />
- <feature android:featureId="f593" android:label="@string/dummyLabel" />
- <feature android:featureId="f594" android:label="@string/dummyLabel" />
- <feature android:featureId="f595" android:label="@string/dummyLabel" />
- <feature android:featureId="f596" android:label="@string/dummyLabel" />
- <feature android:featureId="f597" android:label="@string/dummyLabel" />
- <feature android:featureId="f598" android:label="@string/dummyLabel" />
- <feature android:featureId="f599" android:label="@string/dummyLabel" />
- <feature android:featureId="f600" android:label="@string/dummyLabel" />
- <feature android:featureId="f601" android:label="@string/dummyLabel" />
- <feature android:featureId="f602" android:label="@string/dummyLabel" />
- <feature android:featureId="f603" android:label="@string/dummyLabel" />
- <feature android:featureId="f604" android:label="@string/dummyLabel" />
- <feature android:featureId="f605" android:label="@string/dummyLabel" />
- <feature android:featureId="f606" android:label="@string/dummyLabel" />
- <feature android:featureId="f607" android:label="@string/dummyLabel" />
- <feature android:featureId="f608" android:label="@string/dummyLabel" />
- <feature android:featureId="f609" android:label="@string/dummyLabel" />
- <feature android:featureId="f610" android:label="@string/dummyLabel" />
- <feature android:featureId="f611" android:label="@string/dummyLabel" />
- <feature android:featureId="f612" android:label="@string/dummyLabel" />
- <feature android:featureId="f613" android:label="@string/dummyLabel" />
- <feature android:featureId="f614" android:label="@string/dummyLabel" />
- <feature android:featureId="f615" android:label="@string/dummyLabel" />
- <feature android:featureId="f616" android:label="@string/dummyLabel" />
- <feature android:featureId="f617" android:label="@string/dummyLabel" />
- <feature android:featureId="f618" android:label="@string/dummyLabel" />
- <feature android:featureId="f619" android:label="@string/dummyLabel" />
- <feature android:featureId="f620" android:label="@string/dummyLabel" />
- <feature android:featureId="f621" android:label="@string/dummyLabel" />
- <feature android:featureId="f622" android:label="@string/dummyLabel" />
- <feature android:featureId="f623" android:label="@string/dummyLabel" />
- <feature android:featureId="f624" android:label="@string/dummyLabel" />
- <feature android:featureId="f625" android:label="@string/dummyLabel" />
- <feature android:featureId="f626" android:label="@string/dummyLabel" />
- <feature android:featureId="f627" android:label="@string/dummyLabel" />
- <feature android:featureId="f628" android:label="@string/dummyLabel" />
- <feature android:featureId="f629" android:label="@string/dummyLabel" />
- <feature android:featureId="f630" android:label="@string/dummyLabel" />
- <feature android:featureId="f631" android:label="@string/dummyLabel" />
- <feature android:featureId="f632" android:label="@string/dummyLabel" />
- <feature android:featureId="f633" android:label="@string/dummyLabel" />
- <feature android:featureId="f634" android:label="@string/dummyLabel" />
- <feature android:featureId="f635" android:label="@string/dummyLabel" />
- <feature android:featureId="f636" android:label="@string/dummyLabel" />
- <feature android:featureId="f637" android:label="@string/dummyLabel" />
- <feature android:featureId="f638" android:label="@string/dummyLabel" />
- <feature android:featureId="f639" android:label="@string/dummyLabel" />
- <feature android:featureId="f640" android:label="@string/dummyLabel" />
- <feature android:featureId="f641" android:label="@string/dummyLabel" />
- <feature android:featureId="f642" android:label="@string/dummyLabel" />
- <feature android:featureId="f643" android:label="@string/dummyLabel" />
- <feature android:featureId="f644" android:label="@string/dummyLabel" />
- <feature android:featureId="f645" android:label="@string/dummyLabel" />
- <feature android:featureId="f646" android:label="@string/dummyLabel" />
- <feature android:featureId="f647" android:label="@string/dummyLabel" />
- <feature android:featureId="f648" android:label="@string/dummyLabel" />
- <feature android:featureId="f649" android:label="@string/dummyLabel" />
- <feature android:featureId="f650" android:label="@string/dummyLabel" />
- <feature android:featureId="f651" android:label="@string/dummyLabel" />
- <feature android:featureId="f652" android:label="@string/dummyLabel" />
- <feature android:featureId="f653" android:label="@string/dummyLabel" />
- <feature android:featureId="f654" android:label="@string/dummyLabel" />
- <feature android:featureId="f655" android:label="@string/dummyLabel" />
- <feature android:featureId="f656" android:label="@string/dummyLabel" />
- <feature android:featureId="f657" android:label="@string/dummyLabel" />
- <feature android:featureId="f658" android:label="@string/dummyLabel" />
- <feature android:featureId="f659" android:label="@string/dummyLabel" />
- <feature android:featureId="f660" android:label="@string/dummyLabel" />
- <feature android:featureId="f661" android:label="@string/dummyLabel" />
- <feature android:featureId="f662" android:label="@string/dummyLabel" />
- <feature android:featureId="f663" android:label="@string/dummyLabel" />
- <feature android:featureId="f664" android:label="@string/dummyLabel" />
- <feature android:featureId="f665" android:label="@string/dummyLabel" />
- <feature android:featureId="f666" android:label="@string/dummyLabel" />
- <feature android:featureId="f667" android:label="@string/dummyLabel" />
- <feature android:featureId="f668" android:label="@string/dummyLabel" />
- <feature android:featureId="f669" android:label="@string/dummyLabel" />
- <feature android:featureId="f670" android:label="@string/dummyLabel" />
- <feature android:featureId="f671" android:label="@string/dummyLabel" />
- <feature android:featureId="f672" android:label="@string/dummyLabel" />
- <feature android:featureId="f673" android:label="@string/dummyLabel" />
- <feature android:featureId="f674" android:label="@string/dummyLabel" />
- <feature android:featureId="f675" android:label="@string/dummyLabel" />
- <feature android:featureId="f676" android:label="@string/dummyLabel" />
- <feature android:featureId="f677" android:label="@string/dummyLabel" />
- <feature android:featureId="f678" android:label="@string/dummyLabel" />
- <feature android:featureId="f679" android:label="@string/dummyLabel" />
- <feature android:featureId="f680" android:label="@string/dummyLabel" />
- <feature android:featureId="f681" android:label="@string/dummyLabel" />
- <feature android:featureId="f682" android:label="@string/dummyLabel" />
- <feature android:featureId="f683" android:label="@string/dummyLabel" />
- <feature android:featureId="f684" android:label="@string/dummyLabel" />
- <feature android:featureId="f685" android:label="@string/dummyLabel" />
- <feature android:featureId="f686" android:label="@string/dummyLabel" />
- <feature android:featureId="f687" android:label="@string/dummyLabel" />
- <feature android:featureId="f688" android:label="@string/dummyLabel" />
- <feature android:featureId="f689" android:label="@string/dummyLabel" />
- <feature android:featureId="f690" android:label="@string/dummyLabel" />
- <feature android:featureId="f691" android:label="@string/dummyLabel" />
- <feature android:featureId="f692" android:label="@string/dummyLabel" />
- <feature android:featureId="f693" android:label="@string/dummyLabel" />
- <feature android:featureId="f694" android:label="@string/dummyLabel" />
- <feature android:featureId="f695" android:label="@string/dummyLabel" />
- <feature android:featureId="f696" android:label="@string/dummyLabel" />
- <feature android:featureId="f697" android:label="@string/dummyLabel" />
- <feature android:featureId="f698" android:label="@string/dummyLabel" />
- <feature android:featureId="f699" android:label="@string/dummyLabel" />
- <feature android:featureId="f700" android:label="@string/dummyLabel" />
- <feature android:featureId="f701" android:label="@string/dummyLabel" />
- <feature android:featureId="f702" android:label="@string/dummyLabel" />
- <feature android:featureId="f703" android:label="@string/dummyLabel" />
- <feature android:featureId="f704" android:label="@string/dummyLabel" />
- <feature android:featureId="f705" android:label="@string/dummyLabel" />
- <feature android:featureId="f706" android:label="@string/dummyLabel" />
- <feature android:featureId="f707" android:label="@string/dummyLabel" />
- <feature android:featureId="f708" android:label="@string/dummyLabel" />
- <feature android:featureId="f709" android:label="@string/dummyLabel" />
- <feature android:featureId="f710" android:label="@string/dummyLabel" />
- <feature android:featureId="f711" android:label="@string/dummyLabel" />
- <feature android:featureId="f712" android:label="@string/dummyLabel" />
- <feature android:featureId="f713" android:label="@string/dummyLabel" />
- <feature android:featureId="f714" android:label="@string/dummyLabel" />
- <feature android:featureId="f715" android:label="@string/dummyLabel" />
- <feature android:featureId="f716" android:label="@string/dummyLabel" />
- <feature android:featureId="f717" android:label="@string/dummyLabel" />
- <feature android:featureId="f718" android:label="@string/dummyLabel" />
- <feature android:featureId="f719" android:label="@string/dummyLabel" />
- <feature android:featureId="f720" android:label="@string/dummyLabel" />
- <feature android:featureId="f721" android:label="@string/dummyLabel" />
- <feature android:featureId="f722" android:label="@string/dummyLabel" />
- <feature android:featureId="f723" android:label="@string/dummyLabel" />
- <feature android:featureId="f724" android:label="@string/dummyLabel" />
- <feature android:featureId="f725" android:label="@string/dummyLabel" />
- <feature android:featureId="f726" android:label="@string/dummyLabel" />
- <feature android:featureId="f727" android:label="@string/dummyLabel" />
- <feature android:featureId="f728" android:label="@string/dummyLabel" />
- <feature android:featureId="f729" android:label="@string/dummyLabel" />
- <feature android:featureId="f730" android:label="@string/dummyLabel" />
- <feature android:featureId="f731" android:label="@string/dummyLabel" />
- <feature android:featureId="f732" android:label="@string/dummyLabel" />
- <feature android:featureId="f733" android:label="@string/dummyLabel" />
- <feature android:featureId="f734" android:label="@string/dummyLabel" />
- <feature android:featureId="f735" android:label="@string/dummyLabel" />
- <feature android:featureId="f736" android:label="@string/dummyLabel" />
- <feature android:featureId="f737" android:label="@string/dummyLabel" />
- <feature android:featureId="f738" android:label="@string/dummyLabel" />
- <feature android:featureId="f739" android:label="@string/dummyLabel" />
- <feature android:featureId="f740" android:label="@string/dummyLabel" />
- <feature android:featureId="f741" android:label="@string/dummyLabel" />
- <feature android:featureId="f742" android:label="@string/dummyLabel" />
- <feature android:featureId="f743" android:label="@string/dummyLabel" />
- <feature android:featureId="f744" android:label="@string/dummyLabel" />
- <feature android:featureId="f745" android:label="@string/dummyLabel" />
- <feature android:featureId="f746" android:label="@string/dummyLabel" />
- <feature android:featureId="f747" android:label="@string/dummyLabel" />
- <feature android:featureId="f748" android:label="@string/dummyLabel" />
- <feature android:featureId="f749" android:label="@string/dummyLabel" />
- <feature android:featureId="f750" android:label="@string/dummyLabel" />
- <feature android:featureId="f751" android:label="@string/dummyLabel" />
- <feature android:featureId="f752" android:label="@string/dummyLabel" />
- <feature android:featureId="f753" android:label="@string/dummyLabel" />
- <feature android:featureId="f754" android:label="@string/dummyLabel" />
- <feature android:featureId="f755" android:label="@string/dummyLabel" />
- <feature android:featureId="f756" android:label="@string/dummyLabel" />
- <feature android:featureId="f757" android:label="@string/dummyLabel" />
- <feature android:featureId="f758" android:label="@string/dummyLabel" />
- <feature android:featureId="f759" android:label="@string/dummyLabel" />
- <feature android:featureId="f760" android:label="@string/dummyLabel" />
- <feature android:featureId="f761" android:label="@string/dummyLabel" />
- <feature android:featureId="f762" android:label="@string/dummyLabel" />
- <feature android:featureId="f763" android:label="@string/dummyLabel" />
- <feature android:featureId="f764" android:label="@string/dummyLabel" />
- <feature android:featureId="f765" android:label="@string/dummyLabel" />
- <feature android:featureId="f766" android:label="@string/dummyLabel" />
- <feature android:featureId="f767" android:label="@string/dummyLabel" />
- <feature android:featureId="f768" android:label="@string/dummyLabel" />
- <feature android:featureId="f769" android:label="@string/dummyLabel" />
- <feature android:featureId="f770" android:label="@string/dummyLabel" />
- <feature android:featureId="f771" android:label="@string/dummyLabel" />
- <feature android:featureId="f772" android:label="@string/dummyLabel" />
- <feature android:featureId="f773" android:label="@string/dummyLabel" />
- <feature android:featureId="f774" android:label="@string/dummyLabel" />
- <feature android:featureId="f775" android:label="@string/dummyLabel" />
- <feature android:featureId="f776" android:label="@string/dummyLabel" />
- <feature android:featureId="f777" android:label="@string/dummyLabel" />
- <feature android:featureId="f778" android:label="@string/dummyLabel" />
- <feature android:featureId="f779" android:label="@string/dummyLabel" />
- <feature android:featureId="f780" android:label="@string/dummyLabel" />
- <feature android:featureId="f781" android:label="@string/dummyLabel" />
- <feature android:featureId="f782" android:label="@string/dummyLabel" />
- <feature android:featureId="f783" android:label="@string/dummyLabel" />
- <feature android:featureId="f784" android:label="@string/dummyLabel" />
- <feature android:featureId="f785" android:label="@string/dummyLabel" />
- <feature android:featureId="f786" android:label="@string/dummyLabel" />
- <feature android:featureId="f787" android:label="@string/dummyLabel" />
- <feature android:featureId="f788" android:label="@string/dummyLabel" />
- <feature android:featureId="f789" android:label="@string/dummyLabel" />
- <feature android:featureId="f790" android:label="@string/dummyLabel" />
- <feature android:featureId="f791" android:label="@string/dummyLabel" />
- <feature android:featureId="f792" android:label="@string/dummyLabel" />
- <feature android:featureId="f793" android:label="@string/dummyLabel" />
- <feature android:featureId="f794" android:label="@string/dummyLabel" />
- <feature android:featureId="f795" android:label="@string/dummyLabel" />
- <feature android:featureId="f796" android:label="@string/dummyLabel" />
- <feature android:featureId="f797" android:label="@string/dummyLabel" />
- <feature android:featureId="f798" android:label="@string/dummyLabel" />
- <feature android:featureId="f799" android:label="@string/dummyLabel" />
- <feature android:featureId="f800" android:label="@string/dummyLabel" />
- <feature android:featureId="f801" android:label="@string/dummyLabel" />
- <feature android:featureId="f802" android:label="@string/dummyLabel" />
- <feature android:featureId="f803" android:label="@string/dummyLabel" />
- <feature android:featureId="f804" android:label="@string/dummyLabel" />
- <feature android:featureId="f805" android:label="@string/dummyLabel" />
- <feature android:featureId="f806" android:label="@string/dummyLabel" />
- <feature android:featureId="f807" android:label="@string/dummyLabel" />
- <feature android:featureId="f808" android:label="@string/dummyLabel" />
- <feature android:featureId="f809" android:label="@string/dummyLabel" />
- <feature android:featureId="f810" android:label="@string/dummyLabel" />
- <feature android:featureId="f811" android:label="@string/dummyLabel" />
- <feature android:featureId="f812" android:label="@string/dummyLabel" />
- <feature android:featureId="f813" android:label="@string/dummyLabel" />
- <feature android:featureId="f814" android:label="@string/dummyLabel" />
- <feature android:featureId="f815" android:label="@string/dummyLabel" />
- <feature android:featureId="f816" android:label="@string/dummyLabel" />
- <feature android:featureId="f817" android:label="@string/dummyLabel" />
- <feature android:featureId="f818" android:label="@string/dummyLabel" />
- <feature android:featureId="f819" android:label="@string/dummyLabel" />
- <feature android:featureId="f820" android:label="@string/dummyLabel" />
- <feature android:featureId="f821" android:label="@string/dummyLabel" />
- <feature android:featureId="f822" android:label="@string/dummyLabel" />
- <feature android:featureId="f823" android:label="@string/dummyLabel" />
- <feature android:featureId="f824" android:label="@string/dummyLabel" />
- <feature android:featureId="f825" android:label="@string/dummyLabel" />
- <feature android:featureId="f826" android:label="@string/dummyLabel" />
- <feature android:featureId="f827" android:label="@string/dummyLabel" />
- <feature android:featureId="f828" android:label="@string/dummyLabel" />
- <feature android:featureId="f829" android:label="@string/dummyLabel" />
- <feature android:featureId="f830" android:label="@string/dummyLabel" />
- <feature android:featureId="f831" android:label="@string/dummyLabel" />
- <feature android:featureId="f832" android:label="@string/dummyLabel" />
- <feature android:featureId="f833" android:label="@string/dummyLabel" />
- <feature android:featureId="f834" android:label="@string/dummyLabel" />
- <feature android:featureId="f835" android:label="@string/dummyLabel" />
- <feature android:featureId="f836" android:label="@string/dummyLabel" />
- <feature android:featureId="f837" android:label="@string/dummyLabel" />
- <feature android:featureId="f838" android:label="@string/dummyLabel" />
- <feature android:featureId="f839" android:label="@string/dummyLabel" />
- <feature android:featureId="f840" android:label="@string/dummyLabel" />
- <feature android:featureId="f841" android:label="@string/dummyLabel" />
- <feature android:featureId="f842" android:label="@string/dummyLabel" />
- <feature android:featureId="f843" android:label="@string/dummyLabel" />
- <feature android:featureId="f844" android:label="@string/dummyLabel" />
- <feature android:featureId="f845" android:label="@string/dummyLabel" />
- <feature android:featureId="f846" android:label="@string/dummyLabel" />
- <feature android:featureId="f847" android:label="@string/dummyLabel" />
- <feature android:featureId="f848" android:label="@string/dummyLabel" />
- <feature android:featureId="f849" android:label="@string/dummyLabel" />
- <feature android:featureId="f850" android:label="@string/dummyLabel" />
- <feature android:featureId="f851" android:label="@string/dummyLabel" />
- <feature android:featureId="f852" android:label="@string/dummyLabel" />
- <feature android:featureId="f853" android:label="@string/dummyLabel" />
- <feature android:featureId="f854" android:label="@string/dummyLabel" />
- <feature android:featureId="f855" android:label="@string/dummyLabel" />
- <feature android:featureId="f856" android:label="@string/dummyLabel" />
- <feature android:featureId="f857" android:label="@string/dummyLabel" />
- <feature android:featureId="f858" android:label="@string/dummyLabel" />
- <feature android:featureId="f859" android:label="@string/dummyLabel" />
- <feature android:featureId="f860" android:label="@string/dummyLabel" />
- <feature android:featureId="f861" android:label="@string/dummyLabel" />
- <feature android:featureId="f862" android:label="@string/dummyLabel" />
- <feature android:featureId="f863" android:label="@string/dummyLabel" />
- <feature android:featureId="f864" android:label="@string/dummyLabel" />
- <feature android:featureId="f865" android:label="@string/dummyLabel" />
- <feature android:featureId="f866" android:label="@string/dummyLabel" />
- <feature android:featureId="f867" android:label="@string/dummyLabel" />
- <feature android:featureId="f868" android:label="@string/dummyLabel" />
- <feature android:featureId="f869" android:label="@string/dummyLabel" />
- <feature android:featureId="f870" android:label="@string/dummyLabel" />
- <feature android:featureId="f871" android:label="@string/dummyLabel" />
- <feature android:featureId="f872" android:label="@string/dummyLabel" />
- <feature android:featureId="f873" android:label="@string/dummyLabel" />
- <feature android:featureId="f874" android:label="@string/dummyLabel" />
- <feature android:featureId="f875" android:label="@string/dummyLabel" />
- <feature android:featureId="f876" android:label="@string/dummyLabel" />
- <feature android:featureId="f877" android:label="@string/dummyLabel" />
- <feature android:featureId="f878" android:label="@string/dummyLabel" />
- <feature android:featureId="f879" android:label="@string/dummyLabel" />
- <feature android:featureId="f880" android:label="@string/dummyLabel" />
- <feature android:featureId="f881" android:label="@string/dummyLabel" />
- <feature android:featureId="f882" android:label="@string/dummyLabel" />
- <feature android:featureId="f883" android:label="@string/dummyLabel" />
- <feature android:featureId="f884" android:label="@string/dummyLabel" />
- <feature android:featureId="f885" android:label="@string/dummyLabel" />
- <feature android:featureId="f886" android:label="@string/dummyLabel" />
- <feature android:featureId="f887" android:label="@string/dummyLabel" />
- <feature android:featureId="f888" android:label="@string/dummyLabel" />
- <feature android:featureId="f889" android:label="@string/dummyLabel" />
- <feature android:featureId="f890" android:label="@string/dummyLabel" />
- <feature android:featureId="f891" android:label="@string/dummyLabel" />
- <feature android:featureId="f892" android:label="@string/dummyLabel" />
- <feature android:featureId="f893" android:label="@string/dummyLabel" />
- <feature android:featureId="f894" android:label="@string/dummyLabel" />
- <feature android:featureId="f895" android:label="@string/dummyLabel" />
- <feature android:featureId="f896" android:label="@string/dummyLabel" />
- <feature android:featureId="f897" android:label="@string/dummyLabel" />
- <feature android:featureId="f898" android:label="@string/dummyLabel" />
- <feature android:featureId="f899" android:label="@string/dummyLabel" />
- <feature android:featureId="f900" android:label="@string/dummyLabel" />
- <feature android:featureId="f901" android:label="@string/dummyLabel" />
- <feature android:featureId="f902" android:label="@string/dummyLabel" />
- <feature android:featureId="f903" android:label="@string/dummyLabel" />
- <feature android:featureId="f904" android:label="@string/dummyLabel" />
- <feature android:featureId="f905" android:label="@string/dummyLabel" />
- <feature android:featureId="f906" android:label="@string/dummyLabel" />
- <feature android:featureId="f907" android:label="@string/dummyLabel" />
- <feature android:featureId="f908" android:label="@string/dummyLabel" />
- <feature android:featureId="f909" android:label="@string/dummyLabel" />
- <feature android:featureId="f910" android:label="@string/dummyLabel" />
- <feature android:featureId="f911" android:label="@string/dummyLabel" />
- <feature android:featureId="f912" android:label="@string/dummyLabel" />
- <feature android:featureId="f913" android:label="@string/dummyLabel" />
- <feature android:featureId="f914" android:label="@string/dummyLabel" />
- <feature android:featureId="f915" android:label="@string/dummyLabel" />
- <feature android:featureId="f916" android:label="@string/dummyLabel" />
- <feature android:featureId="f917" android:label="@string/dummyLabel" />
- <feature android:featureId="f918" android:label="@string/dummyLabel" />
- <feature android:featureId="f919" android:label="@string/dummyLabel" />
- <feature android:featureId="f920" android:label="@string/dummyLabel" />
- <feature android:featureId="f921" android:label="@string/dummyLabel" />
- <feature android:featureId="f922" android:label="@string/dummyLabel" />
- <feature android:featureId="f923" android:label="@string/dummyLabel" />
- <feature android:featureId="f924" android:label="@string/dummyLabel" />
- <feature android:featureId="f925" android:label="@string/dummyLabel" />
- <feature android:featureId="f926" android:label="@string/dummyLabel" />
- <feature android:featureId="f927" android:label="@string/dummyLabel" />
- <feature android:featureId="f928" android:label="@string/dummyLabel" />
- <feature android:featureId="f929" android:label="@string/dummyLabel" />
- <feature android:featureId="f930" android:label="@string/dummyLabel" />
- <feature android:featureId="f931" android:label="@string/dummyLabel" />
- <feature android:featureId="f932" android:label="@string/dummyLabel" />
- <feature android:featureId="f933" android:label="@string/dummyLabel" />
- <feature android:featureId="f934" android:label="@string/dummyLabel" />
- <feature android:featureId="f935" android:label="@string/dummyLabel" />
- <feature android:featureId="f936" android:label="@string/dummyLabel" />
- <feature android:featureId="f937" android:label="@string/dummyLabel" />
- <feature android:featureId="f938" android:label="@string/dummyLabel" />
- <feature android:featureId="f939" android:label="@string/dummyLabel" />
- <feature android:featureId="f940" android:label="@string/dummyLabel" />
- <feature android:featureId="f941" android:label="@string/dummyLabel" />
- <feature android:featureId="f942" android:label="@string/dummyLabel" />
- <feature android:featureId="f943" android:label="@string/dummyLabel" />
- <feature android:featureId="f944" android:label="@string/dummyLabel" />
- <feature android:featureId="f945" android:label="@string/dummyLabel" />
- <feature android:featureId="f946" android:label="@string/dummyLabel" />
- <feature android:featureId="f947" android:label="@string/dummyLabel" />
- <feature android:featureId="f948" android:label="@string/dummyLabel" />
- <feature android:featureId="f949" android:label="@string/dummyLabel" />
- <feature android:featureId="f950" android:label="@string/dummyLabel" />
- <feature android:featureId="f951" android:label="@string/dummyLabel" />
- <feature android:featureId="f952" android:label="@string/dummyLabel" />
- <feature android:featureId="f953" android:label="@string/dummyLabel" />
- <feature android:featureId="f954" android:label="@string/dummyLabel" />
- <feature android:featureId="f955" android:label="@string/dummyLabel" />
- <feature android:featureId="f956" android:label="@string/dummyLabel" />
- <feature android:featureId="f957" android:label="@string/dummyLabel" />
- <feature android:featureId="f958" android:label="@string/dummyLabel" />
- <feature android:featureId="f959" android:label="@string/dummyLabel" />
- <feature android:featureId="f960" android:label="@string/dummyLabel" />
- <feature android:featureId="f961" android:label="@string/dummyLabel" />
- <feature android:featureId="f962" android:label="@string/dummyLabel" />
- <feature android:featureId="f963" android:label="@string/dummyLabel" />
- <feature android:featureId="f964" android:label="@string/dummyLabel" />
- <feature android:featureId="f965" android:label="@string/dummyLabel" />
- <feature android:featureId="f966" android:label="@string/dummyLabel" />
- <feature android:featureId="f967" android:label="@string/dummyLabel" />
- <feature android:featureId="f968" android:label="@string/dummyLabel" />
- <feature android:featureId="f969" android:label="@string/dummyLabel" />
- <feature android:featureId="f970" android:label="@string/dummyLabel" />
- <feature android:featureId="f971" android:label="@string/dummyLabel" />
- <feature android:featureId="f972" android:label="@string/dummyLabel" />
- <feature android:featureId="f973" android:label="@string/dummyLabel" />
- <feature android:featureId="f974" android:label="@string/dummyLabel" />
- <feature android:featureId="f975" android:label="@string/dummyLabel" />
- <feature android:featureId="f976" android:label="@string/dummyLabel" />
- <feature android:featureId="f977" android:label="@string/dummyLabel" />
- <feature android:featureId="f978" android:label="@string/dummyLabel" />
- <feature android:featureId="f979" android:label="@string/dummyLabel" />
- <feature android:featureId="f980" android:label="@string/dummyLabel" />
- <feature android:featureId="f981" android:label="@string/dummyLabel" />
- <feature android:featureId="f982" android:label="@string/dummyLabel" />
- <feature android:featureId="f983" android:label="@string/dummyLabel" />
- <feature android:featureId="f984" android:label="@string/dummyLabel" />
- <feature android:featureId="f985" android:label="@string/dummyLabel" />
- <feature android:featureId="f986" android:label="@string/dummyLabel" />
- <feature android:featureId="f987" android:label="@string/dummyLabel" />
- <feature android:featureId="f988" android:label="@string/dummyLabel" />
- <feature android:featureId="f989" android:label="@string/dummyLabel" />
- <feature android:featureId="f990" android:label="@string/dummyLabel" />
- <feature android:featureId="f991" android:label="@string/dummyLabel" />
- <feature android:featureId="f992" android:label="@string/dummyLabel" />
- <feature android:featureId="f993" android:label="@string/dummyLabel" />
- <feature android:featureId="f994" android:label="@string/dummyLabel" />
- <feature android:featureId="f995" android:label="@string/dummyLabel" />
- <feature android:featureId="f996" android:label="@string/dummyLabel" />
- <feature android:featureId="f997" android:label="@string/dummyLabel" />
- <feature android:featureId="f998" android:label="@string/dummyLabel" />
- <feature android:featureId="f999" android:label="@string/dummyLabel" />
-
- <feature android:featureId="toomany" android:label="@string/dummyLabel" />
-
- <application />
-
-</manifest>
diff --git a/tests/tests/appop/aidl/AppOpsUserService/src/android/app/appops/cts/IAppOpsUserClient.aidl b/tests/tests/appop/aidl/AppOpsUserService/src/android/app/appops/cts/IAppOpsUserClient.aidl
index f3af855..e4125f7 100644
--- a/tests/tests/appop/aidl/AppOpsUserService/src/android/app/appops/cts/IAppOpsUserClient.aidl
+++ b/tests/tests/appop/aidl/AppOpsUserService/src/android/app/appops/cts/IAppOpsUserClient.aidl
@@ -18,7 +18,7 @@
interface IAppOpsUserClient {
void noteSyncOp();
- void noteSyncOpWithFeature(String featureId);
+ void noteSyncOpWithAttribution(String attributionTag);
void callBackIntoService();
void noteNonPermissionSyncOp();
void noteSyncOpTwice();
@@ -30,7 +30,7 @@
void noteSyncOpOtherUid();
void noteSyncOpOtherUidNative();
void noteAsyncOp();
- void noteAsyncOpWithFeature(String featureId);
+ void noteAsyncOpWithAttribution(String attributionTag);
void noteAsyncOpWithCustomMessage();
void noteAsyncOpNative();
void noteAsyncOpNativeWithCustomMessage();
diff --git a/tests/tests/appop/aidl/AppOpsUserService/src/android/app/appops/cts/IAppOpsUserService.aidl b/tests/tests/appop/aidl/AppOpsUserService/src/android/app/appops/cts/IAppOpsUserService.aidl
index a19705f..0b073fb 100644
--- a/tests/tests/appop/aidl/AppOpsUserService/src/android/app/appops/cts/IAppOpsUserService.aidl
+++ b/tests/tests/appop/aidl/AppOpsUserService/src/android/app/appops/cts/IAppOpsUserService.aidl
@@ -23,7 +23,7 @@
void disableCollectorAndCallASyncOpsWhichWillBeCollected(in IAppOpsUserClient client);
void callApiThatNotesSyncOpAndCheckLog(in IAppOpsUserClient client);
void callApiThatNotesSyncOpAndClearLog(in IAppOpsUserClient client);
- void callApiThatNotesSyncOpWithFeatureAndCheckLog(in IAppOpsUserClient client);
+ void callApiThatNotesSyncOpWithAttributionAndCheckLog(in IAppOpsUserClient client);
void callApiThatCallsBackIntoServiceAndCheckLog(in IAppOpsUserClient client);
void callApiThatNotesSyncOpFromNativeCodeAndCheckLog(in IAppOpsUserClient client);
void callApiThatNotesSyncOpFromNativeCodeAndCheckMessage(in IAppOpsUserClient client);
@@ -38,7 +38,7 @@
void callApiThatNotesSyncOpOtherUidAndCheckLog(in IAppOpsUserClient client);
void callApiThatNotesSyncOpOtherUidNativelyAndCheckLog(in IAppOpsUserClient client);
void callApiThatNotesAsyncOpAndCheckLog(in IAppOpsUserClient client);
- void callApiThatNotesAsyncOpWithFeatureAndCheckLog(in IAppOpsUserClient client);
+ void callApiThatNotesAsyncOpWithAttributionAndCheckLog(in IAppOpsUserClient client);
void callApiThatNotesAsyncOpAndCheckDefaultMessage(in IAppOpsUserClient client);
void callApiThatNotesAsyncOpAndCheckCustomMessage(in IAppOpsUserClient client);
void callApiThatNotesAsyncOpNativelyAndCheckCustomMessage(in IAppOpsUserClient client);
diff --git a/tests/tests/appop/appopsTestUtilLib/src/android/app/appops/cts/AppOpsUtils.kt b/tests/tests/appop/appopsTestUtilLib/src/android/app/appops/cts/AppOpsUtils.kt
index da8f8d2..b1588d5 100644
--- a/tests/tests/appop/appopsTestUtilLib/src/android/app/appops/cts/AppOpsUtils.kt
+++ b/tests/tests/appop/appopsTestUtilLib/src/android/app/appops/cts/AppOpsUtils.kt
@@ -29,7 +29,7 @@
private const val LOG_TAG = "AppOpsUtils"
private const val TIMEOUT_MILLIS = 10000L
-const val TEST_FEATURE_ID = "testFeature"
+const val TEST_ATTRIBUTION_TAG = "testAttribution"
/**
* Resets a package's app ops configuration to the device default. See AppOpsManager for the
diff --git a/tests/tests/appop/jni/android/app/appops/cts/AppOpsLoggingTest.cpp b/tests/tests/appop/jni/android/app/appops/cts/AppOpsLoggingTest.cpp
index 0b47701..a403163 100644
--- a/tests/tests/appop/jni/android/app/appops/cts/AppOpsLoggingTest.cpp
+++ b/tests/tests/appop/jni/android/app/appops/cts/AppOpsLoggingTest.cpp
@@ -29,17 +29,17 @@
// Note op from native code
extern "C" JNIEXPORT void JNICALL
Java_android_app_appops_cts_AppOpsLoggingTestKt_nativeNoteOp(JNIEnv* env, jobject obj,
- jint op, jint uid, jstring jCallingPackageName, jstring jFeatureId, jstring jMessage) {
+ jint op, jint uid, jstring jCallingPackageName, jstring jAttributionTag, jstring jMessage) {
AppOpsManager appOpsManager;
const char *nativeCallingPackageName = env->GetStringUTFChars(jCallingPackageName, 0);
String16 callingPackageName(nativeCallingPackageName);
- const char *nativeFeatureId;
- std::unique_ptr<String16> featureId;
- if (jFeatureId != nullptr) {
- nativeFeatureId = env->GetStringUTFChars(jFeatureId, 0);
- featureId = std::unique_ptr<String16>(new String16(nativeFeatureId));
+ const char *nativeAttributionTag;
+ std::unique_ptr<String16> attributionTag;
+ if (jAttributionTag != nullptr) {
+ nativeAttributionTag = env->GetStringUTFChars(jAttributionTag, 0);
+ attributionTag = std::unique_ptr<String16>(new String16(nativeAttributionTag));
}
const char *nativeMessage;
@@ -51,12 +51,12 @@
message = new String16();
}
- appOpsManager.noteOp(op, uid, callingPackageName, featureId, *message);
+ appOpsManager.noteOp(op, uid, callingPackageName, attributionTag, *message);
env->ReleaseStringUTFChars(jCallingPackageName, nativeCallingPackageName);
- if (jFeatureId != nullptr) {
- env->ReleaseStringUTFChars(jFeatureId, nativeFeatureId);
+ if (jAttributionTag != nullptr) {
+ env->ReleaseStringUTFChars(jAttributionTag, nativeAttributionTag);
}
if (jMessage != nullptr) {
diff --git a/tests/tests/appop/src/android/app/appops/cts/AppOpEventCollectionTest.kt b/tests/tests/appop/src/android/app/appops/cts/AppOpEventCollectionTest.kt
index 51bad70..103a4b2 100644
--- a/tests/tests/appop/src/android/app/appops/cts/AppOpEventCollectionTest.kt
+++ b/tests/tests/appop/src/android/app/appops/cts/AppOpEventCollectionTest.kt
@@ -96,36 +96,36 @@
}
@Test
- fun noteWithFeatureAndCheckOpEntries() {
+ fun noteWithAttributionAndCheckOpEntries() {
val before = System.currentTimeMillis()
- appOpsManager.noteOp(OPSTR_WIFI_SCAN, myUid, myPackage, TEST_FEATURE_ID, null)
+ appOpsManager.noteOp(OPSTR_WIFI_SCAN, myUid, myPackage, TEST_ATTRIBUTION_TAG, null)
val after = System.currentTimeMillis()
val opEntry = getOpEntry(myUid, myPackage, OPSTR_WIFI_SCAN)!!
- val featureOpEntry = opEntry.features[TEST_FEATURE_ID]!!
+ val attributionOpEntry = opEntry.attributedOpEntries[TEST_ATTRIBUTION_TAG]!!
- assertThat(featureOpEntry.getLastAccessForegroundTime(OP_FLAG_SELF)).isIn(before..after)
+ assertThat(attributionOpEntry.getLastAccessForegroundTime(OP_FLAG_SELF)).isIn(before..after)
// Access should should also show up in the combined state for all op-flags
- assertThat(featureOpEntry.getLastAccessForegroundTime(OP_FLAGS_ALL)).isIn(before..after)
+ assertThat(attributionOpEntry.getLastAccessForegroundTime(OP_FLAGS_ALL)).isIn(before..after)
assertThat(opEntry.getLastAccessTime(OP_FLAGS_ALL)).isIn(before..after)
// Foreground access should should also show up in the combined state for fg and bg
- assertThat(featureOpEntry.getLastAccessTime(OP_FLAG_SELF)).isIn(before..after)
+ assertThat(attributionOpEntry.getLastAccessTime(OP_FLAG_SELF)).isIn(before..after)
assertThat(opEntry.getLastAccessTime(OP_FLAG_SELF)).isIn(before..after)
// The access was in foreground, hence there is no background access
- assertThat(featureOpEntry.getLastBackgroundDuration(OP_FLAG_SELF)).isLessThan(before)
+ assertThat(attributionOpEntry.getLastBackgroundDuration(OP_FLAG_SELF)).isLessThan(before)
assertThat(opEntry.getLastBackgroundDuration(OP_FLAG_SELF)).isLessThan(before)
- // The access was for a feature, hence there is no access for the default feature
- if (null in opEntry.features) {
- assertThat(opEntry.features[null]!!.getLastAccessForegroundTime(OP_FLAG_SELF))
- .isLessThan(before)
+ // The access was for a attribution, hence there is no access for the default attribution
+ if (null in opEntry.attributedOpEntries) {
+ assertThat(opEntry.attributedOpEntries[null]!!
+ .getLastAccessForegroundTime(OP_FLAG_SELF)).isLessThan(before)
}
// The access does not show up for other op-flags
- assertThat(featureOpEntry.getLastAccessForegroundTime(
+ assertThat(attributionOpEntry.getLastAccessForegroundTime(
OP_FLAGS_ALL and OP_FLAG_SELF.inv())).isLessThan(before)
assertThat(opEntry.getLastAccessForegroundTime(
OP_FLAGS_ALL and OP_FLAG_SELF.inv())).isLessThan(before)
@@ -149,40 +149,40 @@
val after = System.currentTimeMillis()
val opEntry = getOpEntry(myUid, myPackage, OPSTR_WIFI_SCAN)!!
- val featureOpEntry = opEntry.features[null]!!
+ val attributionOpEntry = opEntry.attributedOpEntries[null]!!
- assertThat(featureOpEntry.getLastAccessTime(OP_FLAG_TRUSTED_PROXY))
+ assertThat(attributionOpEntry.getLastAccessTime(OP_FLAG_TRUSTED_PROXY))
.isIn(before..afterTrusted)
- assertThat(featureOpEntry.getLastAccessTime(OP_FLAG_SELF)).isIn(afterTrusted..after)
+ assertThat(attributionOpEntry.getLastAccessTime(OP_FLAG_SELF)).isIn(afterTrusted..after)
assertThat(opEntry.getLastAccessTime(OP_FLAG_TRUSTED_PROXY)).isIn(before..afterTrusted)
assertThat(opEntry.getLastAccessTime(OP_FLAG_SELF)).isIn(afterTrusted..after)
// When asked for any flags, the second access overrides the first
- assertThat(featureOpEntry.getLastAccessTime(OP_FLAGS_ALL)).isIn(afterTrusted..after)
+ assertThat(attributionOpEntry.getLastAccessTime(OP_FLAGS_ALL)).isIn(afterTrusted..after)
assertThat(opEntry.getLastAccessTime(OP_FLAGS_ALL)).isIn(afterTrusted..after)
}
@Test
- fun noteForTwoFeaturesCheckOpEntries() {
+ fun noteForTwoAttributionsCheckOpEntries() {
val before = System.currentTimeMillis()
- appOpsManager.noteOp(OPSTR_WIFI_SCAN, myUid, myPackage, "firstFeature", null)
+ appOpsManager.noteOp(OPSTR_WIFI_SCAN, myUid, myPackage, "firstAttribution", null)
val afterFirst = System.currentTimeMillis()
// Make sure timestamps are distinct
sleep(1)
// self note
- appOpsManager.noteOp(OPSTR_WIFI_SCAN, myUid, myPackage, "secondFeature", null)
+ appOpsManager.noteOp(OPSTR_WIFI_SCAN, myUid, myPackage, "secondAttribution", null)
val after = System.currentTimeMillis()
val opEntry = getOpEntry(myUid, myPackage, OPSTR_WIFI_SCAN)!!
- val firstFeatureOpEntry = opEntry.features["firstFeature"]!!
- val secondFeatureOpEntry = opEntry.features["secondFeature"]!!
+ val firstAttributionOpEntry = opEntry.attributedOpEntries["firstAttribution"]!!
+ val secondAttributionOpEntry = opEntry.attributedOpEntries["secondAttribution"]!!
- assertThat(firstFeatureOpEntry.getLastAccessTime(OP_FLAG_SELF)).isIn(before..afterFirst)
- assertThat(secondFeatureOpEntry.getLastAccessTime(OP_FLAG_SELF)).isIn(afterFirst..after)
+ assertThat(firstAttributionOpEntry.getLastAccessTime(OP_FLAG_SELF)).isIn(before..afterFirst)
+ assertThat(secondAttributionOpEntry.getLastAccessTime(OP_FLAG_SELF)).isIn(afterFirst..after)
- // When asked for any feature, the second access overrides the first
+ // When asked for any attribution, the second access overrides the first
assertThat(opEntry.getLastAccessTime(OP_FLAG_SELF)).isIn(afterFirst..after)
}
@@ -198,7 +198,7 @@
// Using the shell identity causes a trusted proxy note
runWithShellPermissionIdentity {
- context.createFeatureContext("firstProxyFeature")
+ context.createAttributionContext("firstProxyAttribution")
.getSystemService(AppOpsManager::class.java)
.noteProxyOp(OPSTR_WIFI_SCAN, otherPkg, otherUid, null, null)
}
@@ -207,35 +207,37 @@
sleep(1)
// untrusted proxy note
- context.createFeatureContext("secondProxyFeature")
+ context.createAttributionContext("secondProxyAttribution")
.getSystemService(AppOpsManager::class.java)
.noteProxyOp(OPSTR_WIFI_SCAN, otherPkg, otherUid, null, null)
val opEntry = getOpEntry(otherUid, otherPkg, OPSTR_WIFI_SCAN)!!
- val featureOpEntry = opEntry.features[null]!!
+ val attributionOpEntry = opEntry.attributedOpEntries[null]!!
- assertThat(featureOpEntry.getLastProxyInfo(OP_FLAG_TRUSTED_PROXIED)?.packageName)
+ assertThat(attributionOpEntry.getLastProxyInfo(OP_FLAG_TRUSTED_PROXIED)?.packageName)
.isEqualTo(myPackage)
assertThat(opEntry.getLastProxyInfo(OP_FLAG_TRUSTED_PROXIED)?.packageName)
.isEqualTo(myPackage)
- assertThat(featureOpEntry.getLastProxyInfo(OP_FLAG_TRUSTED_PROXIED)?.uid).isEqualTo(myUid)
+ assertThat(attributionOpEntry.getLastProxyInfo(OP_FLAG_TRUSTED_PROXIED)?.uid)
+ .isEqualTo(myUid)
assertThat(opEntry.getLastProxyInfo(OP_FLAG_TRUSTED_PROXIED)?.uid).isEqualTo(myUid)
- assertThat(featureOpEntry.getLastProxyInfo(OP_FLAG_UNTRUSTED_PROXIED)?.packageName)
+ assertThat(attributionOpEntry.getLastProxyInfo(OP_FLAG_UNTRUSTED_PROXIED)?.packageName)
.isEqualTo(myPackage)
assertThat(opEntry.getLastProxyInfo(OP_FLAG_UNTRUSTED_PROXIED)?.packageName)
.isEqualTo(myPackage)
- assertThat(featureOpEntry.getLastProxyInfo(OP_FLAG_UNTRUSTED_PROXIED)?.uid).isEqualTo(myUid)
+ assertThat(attributionOpEntry.getLastProxyInfo(OP_FLAG_UNTRUSTED_PROXIED)?.uid)
+ .isEqualTo(myUid)
assertThat(opEntry.getLastProxyInfo(OP_FLAG_UNTRUSTED_PROXIED)?.uid).isEqualTo(myUid)
- assertThat(featureOpEntry.getLastProxyInfo(OP_FLAG_TRUSTED_PROXIED)?.featureId)
- .isEqualTo("firstProxyFeature")
- assertThat(featureOpEntry.getLastProxyInfo(OP_FLAG_UNTRUSTED_PROXIED)?.featureId)
- .isEqualTo("secondProxyFeature")
+ assertThat(attributionOpEntry.getLastProxyInfo(OP_FLAG_TRUSTED_PROXIED)?.attributionTag)
+ .isEqualTo("firstProxyAttribution")
+ assertThat(attributionOpEntry.getLastProxyInfo(OP_FLAG_UNTRUSTED_PROXIED)?.attributionTag)
+ .isEqualTo("secondProxyAttribution")
- // If asked for all op-flags the second feature overrides the first
- assertThat(featureOpEntry.getLastProxyInfo(OP_FLAGS_ALL)?.featureId)
- .isEqualTo("secondProxyFeature")
+ // If asked for all op-flags the second attribution overrides the first
+ assertThat(attributionOpEntry.getLastProxyInfo(OP_FLAGS_ALL)?.attributionTag)
+ .isEqualTo("secondProxyAttribution")
}
@Test
@@ -243,140 +245,141 @@
appOpsManager.startOp(OPSTR_WIFI_SCAN, myUid, myPackage, null, null)
with(getOpEntry(myUid, myPackage, OPSTR_WIFI_SCAN)!!) {
- assertThat(features[null]!!.isRunning).isTrue()
- features[TEST_FEATURE_ID]?.let { assertThat(it.isRunning).isFalse() }
+ assertThat(attributedOpEntries[null]!!.isRunning).isTrue()
+ attributedOpEntries[TEST_ATTRIBUTION_TAG]?.let { assertThat(it.isRunning).isFalse() }
assertThat(isRunning).isTrue()
}
- appOpsManager.startOp(OPSTR_WIFI_SCAN, myUid, myPackage, TEST_FEATURE_ID, null)
+ appOpsManager.startOp(OPSTR_WIFI_SCAN, myUid, myPackage, TEST_ATTRIBUTION_TAG, null)
with(getOpEntry(myUid, myPackage, OPSTR_WIFI_SCAN)!!) {
- assertThat(features[null]!!.isRunning).isTrue()
- assertThat(features[TEST_FEATURE_ID]!!.isRunning).isTrue()
+ assertThat(attributedOpEntries[null]!!.isRunning).isTrue()
+ assertThat(attributedOpEntries[TEST_ATTRIBUTION_TAG]!!.isRunning).isTrue()
assertThat(isRunning).isTrue()
}
- appOpsManager.startOp(OPSTR_WIFI_SCAN, myUid, myPackage, TEST_FEATURE_ID, null)
+ appOpsManager.startOp(OPSTR_WIFI_SCAN, myUid, myPackage, TEST_ATTRIBUTION_TAG, null)
with(getOpEntry(myUid, myPackage, OPSTR_WIFI_SCAN)!!) {
- assertThat(features[null]!!.isRunning).isTrue()
- assertThat(features[TEST_FEATURE_ID]!!.isRunning).isTrue()
+ assertThat(attributedOpEntries[null]!!.isRunning).isTrue()
+ assertThat(attributedOpEntries[TEST_ATTRIBUTION_TAG]!!.isRunning).isTrue()
assertThat(isRunning).isTrue()
}
- appOpsManager.finishOp(OPSTR_WIFI_SCAN, myUid, myPackage, TEST_FEATURE_ID)
+ appOpsManager.finishOp(OPSTR_WIFI_SCAN, myUid, myPackage, TEST_ATTRIBUTION_TAG)
with(getOpEntry(myUid, myPackage, OPSTR_WIFI_SCAN)!!) {
- assertThat(features[null]!!.isRunning).isTrue()
- assertThat(features[TEST_FEATURE_ID]!!.isRunning).isTrue()
+ assertThat(attributedOpEntries[null]!!.isRunning).isTrue()
+ assertThat(attributedOpEntries[TEST_ATTRIBUTION_TAG]!!.isRunning).isTrue()
assertThat(isRunning).isTrue()
}
- appOpsManager.finishOp(OPSTR_WIFI_SCAN, myUid, myPackage, TEST_FEATURE_ID)
+ appOpsManager.finishOp(OPSTR_WIFI_SCAN, myUid, myPackage, TEST_ATTRIBUTION_TAG)
with(getOpEntry(myUid, myPackage, OPSTR_WIFI_SCAN)!!) {
- assertThat(features[null]!!.isRunning).isTrue()
- assertThat(features[TEST_FEATURE_ID]!!.isRunning).isFalse()
+ assertThat(attributedOpEntries[null]!!.isRunning).isTrue()
+ assertThat(attributedOpEntries[TEST_ATTRIBUTION_TAG]!!.isRunning).isFalse()
assertThat(isRunning).isTrue()
}
appOpsManager.finishOp(OPSTR_WIFI_SCAN, myUid, myPackage, null)
with(getOpEntry(myUid, myPackage, OPSTR_WIFI_SCAN)!!) {
- assertThat(features[null]!!.isRunning).isFalse()
- assertThat(features[TEST_FEATURE_ID]!!.isRunning).isFalse()
+ assertThat(attributedOpEntries[null]!!.isRunning).isFalse()
+ assertThat(attributedOpEntries[TEST_ATTRIBUTION_TAG]!!.isRunning).isFalse()
assertThat(isRunning).isFalse()
}
}
@Test
fun startStopMultipleOpsAndVerifyLastAccess() {
- val beforeNullFeatureStart = System.currentTimeMillis()
+ val beforeNullAttributionStart = System.currentTimeMillis()
appOpsManager.startOp(OPSTR_WIFI_SCAN, myUid, myPackage, null, null)
- val afterNullFeatureStart = System.currentTimeMillis()
+ val afterNullAttributionStart = System.currentTimeMillis()
with(getOpEntry(myUid, myPackage, OPSTR_WIFI_SCAN)!!) {
- assertThat(features[null]!!.getLastAccessTime(OP_FLAGS_ALL))
- .isIn(beforeNullFeatureStart..afterNullFeatureStart)
- features[TEST_FEATURE_ID]?.let {
- assertThat(it.getLastAccessTime(OP_FLAGS_ALL)).isAtMost(beforeNullFeatureStart)
+ assertThat(attributedOpEntries[null]!!.getLastAccessTime(OP_FLAGS_ALL))
+ .isIn(beforeNullAttributionStart..afterNullAttributionStart)
+ attributedOpEntries[TEST_ATTRIBUTION_TAG]?.let {
+ assertThat(it.getLastAccessTime(OP_FLAGS_ALL)).isAtMost(beforeNullAttributionStart)
}
assertThat(getLastAccessTime(OP_FLAGS_ALL))
- .isIn(beforeNullFeatureStart..afterNullFeatureStart)
+ .isIn(beforeNullAttributionStart..afterNullAttributionStart)
}
- val beforeFirstFeatureStart = System.currentTimeMillis()
- appOpsManager.startOp(OPSTR_WIFI_SCAN, myUid, myPackage, TEST_FEATURE_ID, null)
- val afterFirstFeatureStart = System.currentTimeMillis()
+ val beforeFirstAttributionStart = System.currentTimeMillis()
+ appOpsManager.startOp(OPSTR_WIFI_SCAN, myUid, myPackage, TEST_ATTRIBUTION_TAG, null)
+ val afterFirstAttributionStart = System.currentTimeMillis()
with(getOpEntry(myUid, myPackage, OPSTR_WIFI_SCAN)!!) {
- assertThat(features[null]!!.getLastAccessTime(OP_FLAGS_ALL))
- .isIn(beforeNullFeatureStart..afterNullFeatureStart)
- assertThat(features[TEST_FEATURE_ID]!!.getLastAccessTime(OP_FLAGS_ALL))
- .isIn(beforeFirstFeatureStart..afterFirstFeatureStart)
+ assertThat(attributedOpEntries[null]!!.getLastAccessTime(OP_FLAGS_ALL))
+ .isIn(beforeNullAttributionStart..afterNullAttributionStart)
+ assertThat(attributedOpEntries[TEST_ATTRIBUTION_TAG]!!.getLastAccessTime(OP_FLAGS_ALL))
+ .isIn(beforeFirstAttributionStart..afterFirstAttributionStart)
assertThat(getLastAccessTime(OP_FLAGS_ALL))
- .isIn(beforeFirstFeatureStart..afterFirstFeatureStart)
+ .isIn(beforeFirstAttributionStart..afterFirstAttributionStart)
}
- appOpsManager.startOp(OPSTR_WIFI_SCAN, myUid, myPackage, TEST_FEATURE_ID, null)
+ appOpsManager.startOp(OPSTR_WIFI_SCAN, myUid, myPackage, TEST_ATTRIBUTION_TAG, null)
// Nested startOps do _not_ count as another access
with(getOpEntry(myUid, myPackage, OPSTR_WIFI_SCAN)!!) {
- assertThat(features[null]!!.getLastAccessTime(OP_FLAGS_ALL))
- .isIn(beforeNullFeatureStart..afterNullFeatureStart)
- assertThat(features[TEST_FEATURE_ID]!!.getLastAccessTime(OP_FLAGS_ALL))
- .isIn(beforeFirstFeatureStart..afterFirstFeatureStart)
+ assertThat(attributedOpEntries[null]!!.getLastAccessTime(OP_FLAGS_ALL))
+ .isIn(beforeNullAttributionStart..afterNullAttributionStart)
+ assertThat(attributedOpEntries[TEST_ATTRIBUTION_TAG]!!.getLastAccessTime(OP_FLAGS_ALL))
+ .isIn(beforeFirstAttributionStart..afterFirstAttributionStart)
assertThat(getLastAccessTime(OP_FLAGS_ALL))
- .isIn(beforeFirstFeatureStart..afterFirstFeatureStart)
+ .isIn(beforeFirstAttributionStart..afterFirstAttributionStart)
}
- appOpsManager.finishOp(OPSTR_WIFI_SCAN, myUid, myPackage, TEST_FEATURE_ID)
- appOpsManager.finishOp(OPSTR_WIFI_SCAN, myUid, myPackage, TEST_FEATURE_ID)
+ appOpsManager.finishOp(OPSTR_WIFI_SCAN, myUid, myPackage, TEST_ATTRIBUTION_TAG)
+ appOpsManager.finishOp(OPSTR_WIFI_SCAN, myUid, myPackage, TEST_ATTRIBUTION_TAG)
appOpsManager.finishOp(OPSTR_WIFI_SCAN, myUid, myPackage, null)
}
@Test
fun startStopMultipleOpsAndVerifyDuration() {
- val beforeNullFeatureStart = SystemClock.elapsedRealtime()
+ val beforeNullAttributionStart = SystemClock.elapsedRealtime()
appOpsManager.startOp(OPSTR_WIFI_SCAN, myUid, myPackage, null, null)
- val afterNullFeatureStart = SystemClock.elapsedRealtime()
+ val afterNullAttributionStart = SystemClock.elapsedRealtime()
run {
val beforeGetOp = SystemClock.elapsedRealtime()
with(getOpEntry(myUid, myPackage, OPSTR_WIFI_SCAN)!!) {
val afterGetOp = SystemClock.elapsedRealtime()
- assertThat(features[null]!!.getLastDuration(OP_FLAGS_ALL))
- .isIn(beforeGetOp - afterNullFeatureStart
- ..afterGetOp - beforeNullFeatureStart)
+ assertThat(attributedOpEntries[null]!!.getLastDuration(OP_FLAGS_ALL))
+ .isIn(beforeGetOp - afterNullAttributionStart
+ ..afterGetOp - beforeNullAttributionStart)
assertThat(getLastDuration(OP_FLAGS_ALL))
- .isIn(beforeGetOp - afterNullFeatureStart
- ..afterGetOp - beforeNullFeatureStart)
+ .isIn(beforeGetOp - afterNullAttributionStart
+ ..afterGetOp - beforeNullAttributionStart)
}
}
- val beforeFeatureStart = SystemClock.elapsedRealtime()
- appOpsManager.startOp(OPSTR_WIFI_SCAN, myUid, myPackage, TEST_FEATURE_ID, null)
- val afterFeatureStart = SystemClock.elapsedRealtime()
+ val beforeAttributionStart = SystemClock.elapsedRealtime()
+ appOpsManager.startOp(OPSTR_WIFI_SCAN, myUid, myPackage, TEST_ATTRIBUTION_TAG, null)
+ val afterAttributionStart = SystemClock.elapsedRealtime()
run {
val beforeGetOp = SystemClock.elapsedRealtime()
with(getOpEntry(myUid, myPackage, OPSTR_WIFI_SCAN)!!) {
val afterGetOp = SystemClock.elapsedRealtime()
- assertThat(features[null]!!.getLastDuration(OP_FLAGS_ALL))
- .isIn(beforeGetOp - afterNullFeatureStart
- ..afterGetOp - beforeNullFeatureStart)
- assertThat(features[TEST_FEATURE_ID]!!.getLastDuration(OP_FLAGS_ALL))
- .isIn(beforeGetOp - afterFeatureStart..afterGetOp - beforeFeatureStart)
+ assertThat(attributedOpEntries[null]!!.getLastDuration(OP_FLAGS_ALL))
+ .isIn(beforeGetOp - afterNullAttributionStart
+ ..afterGetOp - beforeNullAttributionStart)
+ assertThat(attributedOpEntries[TEST_ATTRIBUTION_TAG]!!
+ .getLastDuration(OP_FLAGS_ALL)).isIn(beforeGetOp -
+ afterAttributionStart..afterGetOp - beforeAttributionStart)
- // The last duration is the duration of the last started feature
- assertThat(getLastDuration(OP_FLAGS_ALL))
- .isIn(beforeGetOp - afterFeatureStart..afterGetOp - beforeFeatureStart)
+ // The last duration is the duration of the last started attribution
+ assertThat(getLastDuration(OP_FLAGS_ALL)).isIn(beforeGetOp -
+ afterAttributionStart..afterGetOp - beforeAttributionStart)
}
}
- appOpsManager.startOp(OPSTR_WIFI_SCAN, myUid, myPackage, TEST_FEATURE_ID, null)
+ appOpsManager.startOp(OPSTR_WIFI_SCAN, myUid, myPackage, TEST_ATTRIBUTION_TAG, null)
// Nested startOps do _not_ start another duration counting, hence the nested
// startOp and finishOp calls have no affect
@@ -385,68 +388,72 @@
with(getOpEntry(myUid, myPackage, OPSTR_WIFI_SCAN)!!) {
val afterGetOp = SystemClock.elapsedRealtime()
- assertThat(features[null]!!.getLastDuration(OP_FLAGS_ALL))
- .isIn(beforeGetOp - afterNullFeatureStart
- ..afterGetOp - beforeNullFeatureStart)
- assertThat(features[TEST_FEATURE_ID]!!.getLastDuration(OP_FLAGS_ALL))
- .isIn(beforeGetOp - afterFeatureStart..afterGetOp - beforeFeatureStart)
+ assertThat(attributedOpEntries[null]!!.getLastDuration(OP_FLAGS_ALL))
+ .isIn(beforeGetOp - afterNullAttributionStart
+ ..afterGetOp - beforeNullAttributionStart)
+ assertThat(attributedOpEntries[TEST_ATTRIBUTION_TAG]!!
+ .getLastDuration(OP_FLAGS_ALL)).isIn(beforeGetOp -
+ afterAttributionStart..afterGetOp - beforeAttributionStart)
assertThat(getLastDuration(OP_FLAGS_ALL))
- .isIn(beforeGetOp - afterFeatureStart..afterGetOp - beforeFeatureStart)
+ .isIn(beforeGetOp -
+ afterAttributionStart..afterGetOp - beforeAttributionStart)
}
}
- appOpsManager.finishOp(OPSTR_WIFI_SCAN, myUid, myPackage, TEST_FEATURE_ID)
+ appOpsManager.finishOp(OPSTR_WIFI_SCAN, myUid, myPackage, TEST_ATTRIBUTION_TAG)
run {
val beforeGetOp = SystemClock.elapsedRealtime()
with(getOpEntry(myUid, myPackage, OPSTR_WIFI_SCAN)!!) {
val afterGetOp = SystemClock.elapsedRealtime()
- assertThat(features[null]!!.getLastDuration(OP_FLAGS_ALL))
- .isIn(beforeGetOp - afterNullFeatureStart
- ..afterGetOp - beforeNullFeatureStart)
- assertThat(features[TEST_FEATURE_ID]!!.getLastDuration(OP_FLAGS_ALL))
- .isIn(beforeGetOp - afterFeatureStart..afterGetOp - beforeFeatureStart)
- assertThat(getLastDuration(OP_FLAGS_ALL))
- .isIn(beforeGetOp - afterFeatureStart..afterGetOp - beforeFeatureStart)
+ assertThat(attributedOpEntries[null]!!.getLastDuration(OP_FLAGS_ALL))
+ .isIn(beforeGetOp - afterNullAttributionStart
+ ..afterGetOp - beforeNullAttributionStart)
+ assertThat(attributedOpEntries[TEST_ATTRIBUTION_TAG]!!
+ .getLastDuration(OP_FLAGS_ALL)).isIn(beforeGetOp -
+ afterAttributionStart..afterGetOp - beforeAttributionStart)
+ assertThat(getLastDuration(OP_FLAGS_ALL)).isIn(beforeGetOp -
+ afterAttributionStart..afterGetOp - beforeAttributionStart)
}
}
- val beforeFeatureStop = SystemClock.elapsedRealtime()
- appOpsManager.finishOp(OPSTR_WIFI_SCAN, myUid, myPackage, TEST_FEATURE_ID)
- val afterFeatureStop = SystemClock.elapsedRealtime()
+ val beforeAttributionStop = SystemClock.elapsedRealtime()
+ appOpsManager.finishOp(OPSTR_WIFI_SCAN, myUid, myPackage, TEST_ATTRIBUTION_TAG)
+ val afterAttributionStop = SystemClock.elapsedRealtime()
run {
val beforeGetOp = SystemClock.elapsedRealtime()
with(getOpEntry(myUid, myPackage, OPSTR_WIFI_SCAN)!!) {
val afterGetOp = SystemClock.elapsedRealtime()
- assertThat(features[null]!!.getLastDuration(OP_FLAGS_ALL))
- .isIn(beforeGetOp - afterNullFeatureStart
- ..afterGetOp - beforeNullFeatureStart)
- assertThat(features[TEST_FEATURE_ID]!!.getLastDuration(OP_FLAGS_ALL))
- .isIn(beforeFeatureStop - afterFeatureStart
- ..afterFeatureStop - beforeFeatureStart)
+ assertThat(attributedOpEntries[null]!!.getLastDuration(OP_FLAGS_ALL))
+ .isIn(beforeGetOp - afterNullAttributionStart
+ ..afterGetOp - beforeNullAttributionStart)
+ assertThat(attributedOpEntries[TEST_ATTRIBUTION_TAG]!!
+ .getLastDuration(OP_FLAGS_ALL)).isIn(
+ beforeAttributionStop - afterAttributionStart
+ ..afterAttributionStop - beforeAttributionStart)
assertThat(getLastDuration(OP_FLAGS_ALL))
- .isIn(beforeFeatureStop - afterFeatureStart
- ..afterFeatureStop - beforeFeatureStart)
+ .isIn(beforeAttributionStop - afterAttributionStart
+ ..afterAttributionStop - beforeAttributionStart)
}
}
- val beforeNullFeatureStop = SystemClock.elapsedRealtime()
+ val beforeNullAttributionStop = SystemClock.elapsedRealtime()
appOpsManager.finishOp(OPSTR_WIFI_SCAN, myUid, myPackage, null)
- val afterNullFeatureStop = SystemClock.elapsedRealtime()
+ val afterNullAttributionStop = SystemClock.elapsedRealtime()
with(getOpEntry(myUid, myPackage, OPSTR_WIFI_SCAN)!!) {
- assertThat(features[null]!!.getLastDuration(OP_FLAGS_ALL))
- .isIn(beforeNullFeatureStop - afterNullFeatureStart
- ..afterNullFeatureStop - beforeNullFeatureStart)
- assertThat(features[TEST_FEATURE_ID]!!.getLastDuration(OP_FLAGS_ALL))
- .isIn(beforeFeatureStop - afterFeatureStart
- ..afterFeatureStop - beforeFeatureStart)
+ assertThat(attributedOpEntries[null]!!.getLastDuration(OP_FLAGS_ALL))
+ .isIn(beforeNullAttributionStop - afterNullAttributionStart
+ ..afterNullAttributionStop - beforeNullAttributionStart)
+ assertThat(attributedOpEntries[TEST_ATTRIBUTION_TAG]!!.getLastDuration(OP_FLAGS_ALL))
+ .isIn(beforeAttributionStop - afterAttributionStart
+ ..afterAttributionStop - beforeAttributionStart)
assertThat(getLastDuration(OP_FLAGS_ALL))
- .isIn(beforeFeatureStop - afterFeatureStart
- ..afterFeatureStop - beforeFeatureStart)
+ .isIn(beforeAttributionStop - afterAttributionStart
+ ..afterAttributionStop - beforeAttributionStart)
}
}
}
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 2b92c7f..e8db5e2 100644
--- a/tests/tests/appop/src/android/app/appops/cts/AppOpsLoggingTest.kt
+++ b/tests/tests/appop/src/android/app/appops/cts/AppOpsLoggingTest.kt
@@ -78,7 +78,7 @@
op: Int,
uid: Int,
packageName: String,
- featureId: String? = null,
+ attributionTag: String? = null,
message: String? = null
)
@@ -168,15 +168,16 @@
assertThat(noted).isEmpty()
assertThat(asyncNoted).isEmpty()
- assertThat(selfNoted.map { it.first.featureId to it.first.op })
+ assertThat(selfNoted.map { it.first.attributionTag to it.first.op })
.containsExactly(null to OPSTR_COARSE_LOCATION)
}
@Test
- fun selfNoteAndCheckFeature() {
- appOpsManager.noteOpNoThrow(OPSTR_COARSE_LOCATION, myUid, myPackage, TEST_FEATURE_ID, null)
+ fun selfNoteAndCheckAttribution() {
+ appOpsManager.noteOpNoThrow(OPSTR_COARSE_LOCATION, myUid, myPackage, TEST_ATTRIBUTION_TAG,
+ null)
- assertThat(selfNoted.map { it.first.featureId }).containsExactly(TEST_FEATURE_ID)
+ assertThat(selfNoted.map { it.first.attributionTag }).containsExactly(TEST_ATTRIBUTION_TAG)
}
@Test
@@ -188,7 +189,7 @@
// All native notes will be reported as async notes
eventually {
- assertThat(asyncNoted[0].featureId).isEqualTo(null)
+ assertThat(asyncNoted[0].attributionTag).isEqualTo(null)
// There is always a message.
assertThat(asyncNoted[0].message).isNotEqualTo(null)
assertThat(asyncNoted[0].op).isEqualTo(OPSTR_COARSE_LOCATION)
@@ -197,13 +198,13 @@
}
@Test
- fun nativeSelfNoteWithFeatureAndMsgAndCheckLog() {
+ fun nativeSelfNoteWithAttributionAndMsgAndCheckLog() {
nativeNoteOp(strOpToOp(OPSTR_COARSE_LOCATION), myUid, myPackage,
- featureId = TEST_FEATURE_ID, message = "testMsg")
+ attributionTag = TEST_ATTRIBUTION_TAG, message = "testMsg")
// All native notes will be reported as async notes
eventually {
- assertThat(asyncNoted[0].featureId).isEqualTo(TEST_FEATURE_ID)
+ assertThat(asyncNoted[0].attributionTag).isEqualTo(TEST_ATTRIBUTION_TAG)
assertThat(asyncNoted[0].message).isEqualTo("testMsg")
}
}
@@ -232,9 +233,9 @@
}
@Test
- fun noteSyncWithFeatureOpAndCheckLog() {
+ fun noteSyncWithAttributionOpAndCheckLog() {
rethrowThrowableFrom {
- testService.callApiThatNotesSyncOpWithFeatureAndCheckLog(AppOpsUserClient(context))
+ testService.callApiThatNotesSyncOpWithAttributionAndCheckLog(AppOpsUserClient(context))
}
}
@@ -341,9 +342,9 @@
}
@Test
- fun noteAsyncOpWithFeatureAndCheckLog() {
+ fun noteAsyncOpWithAttributionAndCheckLog() {
rethrowThrowableFrom {
- testService.callApiThatNotesAsyncOpWithFeatureAndCheckLog(AppOpsUserClient(context))
+ testService.callApiThatNotesAsyncOpWithAttributionAndCheckLog(AppOpsUserClient(context))
}
}
@@ -381,13 +382,13 @@
*/
@Test
fun getWifiScanResults() {
- val wifiManager = context.createFeatureContext(TEST_FEATURE_ID)
+ val wifiManager = context.createAttributionContext(TEST_ATTRIBUTION_TAG)
.getSystemService(WifiManager::class.java)
val results = wifiManager.scanResults
assertThat(noted[0].first.op).isEqualTo(OPSTR_FINE_LOCATION)
- assertThat(noted[0].first.featureId).isEqualTo(TEST_FEATURE_ID)
+ assertThat(noted[0].first.attributionTag).isEqualTo(TEST_ATTRIBUTION_TAG)
assertThat(noted[0].second.map { it.methodName }).contains("getWifiScanResults")
}
@@ -399,13 +400,13 @@
assumeTrue("Device does not support bluetooth",
context.packageManager.hasSystemFeature(FEATURE_BLUETOOTH))
- val btManager = context.createFeatureContext(TEST_FEATURE_ID)
+ val btManager = context.createAttributionContext(TEST_ATTRIBUTION_TAG)
.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].first.attributionTag).isEqualTo(TEST_ATTRIBUTION_TAG)
assertThat(noted[0].second.map { it.methodName }).contains("getBTScanResults")
} finally {
btManager.adapter.cancelDiscovery()
@@ -417,7 +418,7 @@
*/
@Test
fun getLastKnownLocation() {
- val locationManager = context.createFeatureContext(TEST_FEATURE_ID)
+ val locationManager = context.createAttributionContext(TEST_ATTRIBUTION_TAG)
.getSystemService(LocationManager::class.java)
assumeTrue("Device does not have a network provider",
@@ -428,7 +429,7 @@
assertThat(noted.map { it.first.op }).containsAnyOf(OPSTR_COARSE_LOCATION,
OPSTR_FINE_LOCATION)
- assertThat(noted[0].first.featureId).isEqualTo(TEST_FEATURE_ID)
+ assertThat(noted[0].first.attributionTag).isEqualTo(TEST_ATTRIBUTION_TAG)
assertThat(noted[0].second.map { it.methodName }).contains("getLastKnownLocation")
}
@@ -437,7 +438,7 @@
*/
@Test
fun getAsyncLocation() {
- val locationManager = context.createFeatureContext(TEST_FEATURE_ID)
+ val locationManager = context.createAttributionContext(TEST_ATTRIBUTION_TAG)
.getSystemService(LocationManager::class.java)
assumeTrue("Device does not have a network provider",
@@ -467,7 +468,7 @@
eventually {
assertThat(asyncNoted.map { it.op }).containsAnyOf(OPSTR_COARSE_LOCATION,
OPSTR_FINE_LOCATION)
- assertThat(asyncNoted[0].featureId).isEqualTo(TEST_FEATURE_ID)
+ assertThat(asyncNoted[0].attributionTag).isEqualTo(TEST_ATTRIBUTION_TAG)
assertThat(asyncNoted[0].message).contains(locationListener::class.java.name)
assertThat(asyncNoted[0].message).contains(
@@ -484,7 +485,7 @@
val gotProximityAlert = CompletableFuture<Unit>()
- val locationManager = context.createFeatureContext(TEST_FEATURE_ID)
+ val locationManager = context.createAttributionContext(TEST_ATTRIBUTION_TAG)
.getSystemService(LocationManager::class.java)!!
val proximityAlertReceiver = object : BroadcastReceiver() {
@@ -511,7 +512,7 @@
eventually {
assertThat(asyncNoted.map { it.op }).contains(OPSTR_FINE_LOCATION)
- assertThat(asyncNoted[0].featureId).isEqualTo(TEST_FEATURE_ID)
+ assertThat(asyncNoted[0].attributionTag).isEqualTo(TEST_ATTRIBUTION_TAG)
assertThat(asyncNoted[0].message).contains(
proximityAlertReceiverPendingIntent::class.java.name)
@@ -532,11 +533,11 @@
*/
@Test
fun readFromContactsProvider() {
- context.createFeatureContext(TEST_FEATURE_ID).contentResolver
+ context.createAttributionContext(TEST_ATTRIBUTION_TAG).contentResolver
.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null)
assertThat(noted.map { it.first.op }).containsExactly(OPSTR_READ_CONTACTS)
- assertThat(noted[0].first.featureId).isEqualTo(TEST_FEATURE_ID)
+ assertThat(noted[0].first.attributionTag).isEqualTo(TEST_ATTRIBUTION_TAG)
assertThat(noted[0].second.map { it.methodName }).contains("readFromContactsProvider")
}
@@ -545,11 +546,11 @@
*/
@Test
fun writeToContactsProvider() {
- context.createFeatureContext(TEST_FEATURE_ID).contentResolver
+ context.createAttributionContext(TEST_ATTRIBUTION_TAG).contentResolver
.insert(ContactsContract.RawContacts.CONTENT_URI, ContentValues())
assertThat(noted.map { it.first.op }).containsExactly(OPSTR_WRITE_CONTACTS)
- assertThat(noted[0].first.featureId).isEqualTo(TEST_FEATURE_ID)
+ assertThat(noted[0].first.attributionTag).isEqualTo(TEST_ATTRIBUTION_TAG)
assertThat(noted[0].second.map { it.methodName }).contains("writeToContactsProvider")
}
@@ -560,13 +561,13 @@
fun getCellInfo() {
assumeTrue(context.packageManager.hasSystemFeature(FEATURE_TELEPHONY))
- val telephonyManager = context.createFeatureContext(TEST_FEATURE_ID)
+ val telephonyManager = context.createAttributionContext(TEST_ATTRIBUTION_TAG)
.getSystemService(TelephonyManager::class.java)
telephonyManager.allCellInfo
assertThat(noted[0].first.op).isEqualTo(OPSTR_FINE_LOCATION)
- assertThat(noted[0].first.featureId).isEqualTo(TEST_FEATURE_ID)
+ assertThat(noted[0].first.attributionTag).isEqualTo(TEST_ATTRIBUTION_TAG)
assertThat(noted[0].second.map { it.methodName }).contains("getCellInfo")
}
@@ -591,7 +592,7 @@
eventually {
assertThat(asyncNoted[0].op).isEqualTo(OPSTR_CAMERA)
- assertThat(asyncNoted[0].featureId).isEqualTo(context.featureId)
+ assertThat(asyncNoted[0].attributionTag).isEqualTo(context.attributionTag)
assertThat(asyncNoted[0].message).contains(cameraManager.cameraIdList[0])
}
}
@@ -600,17 +601,17 @@
* Realistic end-to-end test for opening camera
*/
@Test
- fun openCameraWithFeature() {
- openCamera(context.createFeatureContext(TEST_FEATURE_ID))
+ fun openCameraWithAttribution() {
+ openCamera(context.createAttributionContext(TEST_ATTRIBUTION_TAG))
}
/**
- * Realistic end-to-end test for opening camera. This uses the default (==null) feature. This
- * is interesting as null feature handling is more complex in native code.
+ * Realistic end-to-end test for opening camera. This uses the default (==null) attribution.
+ * This is interesting as null attribution handling is more complex in native code.
*/
@Test
- fun openCameraWithDefaultFeature() {
- openCamera(context.createFeatureContext(null))
+ fun openCameraWithDefaultAttribution() {
+ openCamera(context.createAttributionContext(null))
}
/**
@@ -620,13 +621,13 @@
fun getMultiSimSupport() {
assumeTrue(context.packageManager.hasSystemFeature(FEATURE_TELEPHONY))
- val telephonyManager = context.createFeatureContext(TEST_FEATURE_ID)
+ val telephonyManager = context.createAttributionContext(TEST_ATTRIBUTION_TAG)
.getSystemService(TelephonyManager::class.java)
telephonyManager.isMultiSimSupported
assertThat(noted[0].first.op).isEqualTo(OPSTR_READ_PHONE_STATE)
- assertThat(noted[0].first.featureId).isEqualTo(TEST_FEATURE_ID)
+ assertThat(noted[0].first.attributionTag).isEqualTo(TEST_ATTRIBUTION_TAG)
assertThat(noted[0].second.map { it.methodName }).contains("getMultiSimSupport")
}
@@ -635,13 +636,13 @@
*/
@Test
fun getWallpaper() {
- val wallpaperManager = context.createFeatureContext(TEST_FEATURE_ID)
+ val wallpaperManager = context.createAttributionContext(TEST_ATTRIBUTION_TAG)
.getSystemService(WallpaperManager::class.java)
wallpaperManager.getWallpaperFile(FLAG_SYSTEM)
assertThat(noted[0].first.op).isEqualTo(OPSTR_READ_EXTERNAL_STORAGE)
- assertThat(noted[0].first.featureId).isEqualTo(TEST_FEATURE_ID)
+ assertThat(noted[0].first.attributionTag).isEqualTo(TEST_ATTRIBUTION_TAG)
assertThat(noted[0].second.map { it.methodName }).contains("getWallpaper")
}
@@ -650,13 +651,13 @@
*/
@Test
fun isInCall() {
- val telecomManager = context.createFeatureContext(TEST_FEATURE_ID)
+ val telecomManager = context.createAttributionContext(TEST_ATTRIBUTION_TAG)
.getSystemService(TelecomManager::class.java)
telecomManager.isInCall()
assertThat(noted[0].first.op).isEqualTo(OPSTR_READ_PHONE_STATE)
- assertThat(noted[0].first.featureId).isEqualTo(TEST_FEATURE_ID)
+ assertThat(noted[0].first.attributionTag).isEqualTo(TEST_ATTRIBUTION_TAG)
assertThat(noted[0].second.map { it.methodName }).contains("isInCall")
}
@@ -665,13 +666,13 @@
*/
@Test
fun startActivity() {
- context.createFeatureContext(TEST_FEATURE_ID).startActivity(
+ context.createAttributionContext(TEST_ATTRIBUTION_TAG).startActivity(
Intent().setComponent(ComponentName(TEST_SERVICE_PKG,
TEST_SERVICE_PKG + ".AutoClosingActivity"))
.setFlags(FLAG_ACTIVITY_NEW_TASK))
assertThat(noted[0].first.op).isEqualTo(OPSTR_FINE_LOCATION)
- assertThat(noted[0].first.featureId).isEqualTo(TEST_FEATURE_ID)
+ assertThat(noted[0].first.attributionTag).isEqualTo(TEST_ATTRIBUTION_TAG)
assertThat(noted[0].second.map { it.methodName }).contains("startActivity")
}
@@ -706,10 +707,10 @@
}
}
- override fun noteSyncOpWithFeature(featureId: String) {
+ override fun noteSyncOpWithAttribution(attributionTag: String) {
runWithShellPermissionIdentity {
appOpsManager.noteOpNoThrow(OPSTR_COARSE_LOCATION, getCallingUid(),
- TEST_SERVICE_PKG, featureId, null)
+ TEST_SERVICE_PKG, attributionTag, null)
}
}
@@ -789,13 +790,13 @@
}
}
- override fun noteAsyncOpWithFeature(featureId: String) {
+ override fun noteAsyncOpWithAttribution(attributionTag: String) {
val callingUid = getCallingUid()
handler.post {
runWithShellPermissionIdentity {
appOpsManager.noteOpNoThrow(OPSTR_COARSE_LOCATION, callingUid, TEST_SERVICE_PKG,
- featureId, null)
+ attributionTag, null)
}
}
}
diff --git a/tests/tests/appop/src/android/app/appops/cts/AppOpsTest.kt b/tests/tests/appop/src/android/app/appops/cts/AppOpsTest.kt
index f9f8d47..3b4dda1 100644
--- a/tests/tests/appop/src/android/app/appops/cts/AppOpsTest.kt
+++ b/tests/tests/appop/src/android/app/appops/cts/AppOpsTest.kt
@@ -228,7 +228,7 @@
}
@Test
- fun overlappingActiveFeatureOps() {
+ fun overlappingActiveAttributionOps() {
runWithShellPermissionIdentity {
val gotActive = CompletableFuture<Unit>()
val gotInActive = CompletableFuture<Unit>()
@@ -249,17 +249,17 @@
mAppOps.startWatchingActive(arrayOf(OPSTR_WRITE_CALENDAR), Executor { it.run() },
activeWatcher)
try {
- mAppOps.startOp(OPSTR_WRITE_CALENDAR, mMyUid, mOpPackageName, "feature1", null)
+ mAppOps.startOp(OPSTR_WRITE_CALENDAR, mMyUid, mOpPackageName, "attribution1", null)
assertTrue(mAppOps.isOpActive(OPSTR_WRITE_CALENDAR, mMyUid, mOpPackageName))
gotActive.get(TIMEOUT_MS, TimeUnit.MILLISECONDS)
mAppOps.startOp(OPSTR_WRITE_CALENDAR, Process.myUid(), mOpPackageName,
- "feature2", null)
+ "attribution2", null)
assertTrue(mAppOps.isOpActive(OPSTR_WRITE_CALENDAR, mMyUid, mOpPackageName))
assertFalse(gotInActive.isDone)
mAppOps.finishOp(OPSTR_WRITE_CALENDAR, Process.myUid(), mOpPackageName,
- "feature1")
+ "attribution1")
// Allow some time for premature "watchingActive" callbacks to arrive
Thread.sleep(500)
@@ -268,7 +268,7 @@
assertFalse(gotInActive.isDone)
mAppOps.finishOp(OPSTR_WRITE_CALENDAR, Process.myUid(), mOpPackageName,
- "feature2")
+ "attribution2")
assertFalse(mAppOps.isOpActive(OPSTR_WRITE_CALENDAR, mMyUid, mOpPackageName))
gotInActive.get(TIMEOUT_MS, TimeUnit.MILLISECONDS)
} finally {
diff --git a/tests/tests/appop/src/android/app/appops/cts/AttributionTest.kt b/tests/tests/appop/src/android/app/appops/cts/AttributionTest.kt
new file mode 100644
index 0000000..0bdf312
--- /dev/null
+++ b/tests/tests/appop/src/android/app/appops/cts/AttributionTest.kt
@@ -0,0 +1,138 @@
+/*
+ * 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.app.appops.cts
+
+import android.app.AppOpsManager
+import android.app.AppOpsManager.OPSTR_WIFI_SCAN
+import android.app.AppOpsManager.OP_FLAGS_ALL
+import android.platform.test.annotations.AppModeFull
+import androidx.test.platform.app.InstrumentationRegistry
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import java.lang.AssertionError
+import java.lang.Thread.sleep
+
+private const val APK_PATH = "/data/local/tmp/cts/appops/"
+
+private const val APP_PKG = "android.app.appops.cts.apptoblame"
+
+private const val ATTRIBUTION_1 = "attribution1"
+private const val ATTRIBUTION_2 = "attribution2"
+private const val ATTRIBUTION_3 = "attribution3"
+private const val ATTRIBUTION_4 = "attribution4"
+private const val ATTRIBUTION_5 = "attribution5"
+private const val ATTRIBUTION_6 = "attribution6"
+private const val ATTRIBUTION_7 = "attribution7"
+
+@AppModeFull(reason = "Test relies on seeing other apps. Instant apps can't see other apps")
+class AttributionTest {
+ private val instrumentation = InstrumentationRegistry.getInstrumentation()
+ private val context = instrumentation.targetContext
+ private val appOpsManager = context.getSystemService(AppOpsManager::class.java)
+ private val appUid by lazy { context.packageManager.getPackageUid(APP_PKG, 0) }
+
+ private fun installApk(apk: String) {
+ val result = runCommand("pm install -r --force-queryable $APK_PATH$apk")
+ assertThat(result.trim()).isEqualTo("Success")
+ }
+
+ @Before
+ fun resetTestApp() {
+ runCommand("pm uninstall $APP_PKG")
+ installApk("CtsAppToBlame1.apk")
+ }
+
+ private fun noteForAttribution(attribution: String) {
+ // Make sure note times as distinct
+ sleep(1)
+
+ runWithShellPermissionIdentity {
+ appOpsManager.noteOpNoThrow(OPSTR_WIFI_SCAN, appUid, APP_PKG, attribution, null)
+ }
+ }
+
+ @Test
+ fun inheritNotedAppOpsOnUpgrade() {
+ noteForAttribution(ATTRIBUTION_1)
+ noteForAttribution(ATTRIBUTION_2)
+ noteForAttribution(ATTRIBUTION_3)
+ noteForAttribution(ATTRIBUTION_4)
+ noteForAttribution(ATTRIBUTION_5)
+
+ val beforeUpdate = getOpEntry(appUid, APP_PKG, OPSTR_WIFI_SCAN)!!
+ installApk("CtsAppToBlame2.apk")
+
+ eventually {
+ val afterUpdate = getOpEntry(appUid, APP_PKG, OPSTR_WIFI_SCAN)!!
+
+ // Attribution 1 is unchanged
+ assertThat(afterUpdate.attributedOpEntries[ATTRIBUTION_1]!!
+ .getLastAccessTime(OP_FLAGS_ALL))
+ .isEqualTo(beforeUpdate.attributedOpEntries[ATTRIBUTION_1]!!
+ .getLastAccessTime(OP_FLAGS_ALL))
+
+ // Attribution 3 disappeared (i.e. was added into "null" attribution)
+ assertThat(afterUpdate.attributedOpEntries[null]!!.getLastAccessTime(OP_FLAGS_ALL))
+ .isEqualTo(beforeUpdate.attributedOpEntries[ATTRIBUTION_3]!!
+ .getLastAccessTime(OP_FLAGS_ALL))
+
+ // Attribution 6 inherits from attribution 2
+ assertThat(afterUpdate.attributedOpEntries[ATTRIBUTION_6]!!
+ .getLastAccessTime(OP_FLAGS_ALL))
+ .isEqualTo(beforeUpdate.attributedOpEntries[ATTRIBUTION_2]!!
+ .getLastAccessTime(OP_FLAGS_ALL))
+
+ // Attribution 7 inherits from attribution 4 and 5. 5 was noted after 4, hence 4 is
+ // removed
+ assertThat(afterUpdate.attributedOpEntries[ATTRIBUTION_7]!!
+ .getLastAccessTime(OP_FLAGS_ALL))
+ .isEqualTo(beforeUpdate.attributedOpEntries[ATTRIBUTION_5]!!
+ .getLastAccessTime(OP_FLAGS_ALL))
+ }
+ }
+
+ @Test(expected = AssertionError::class)
+ fun cannotInheritFromSelf() {
+ installApk("AppWithAttributionInheritingFromSelf.apk")
+ }
+
+ @Test(expected = AssertionError::class)
+ fun noDuplicateAttributions() {
+ installApk("AppWithDuplicateAttribution.apk")
+ }
+
+ @Test(expected = AssertionError::class)
+ fun cannotInheritFromExisting() {
+ installApk("AppWithAttributionInheritingFromExisting.apk")
+ }
+
+ @Test(expected = AssertionError::class)
+ fun cannotInheritFromSameAsOther() {
+ installApk("AppWithAttributionInheritingFromSameAsOther.apk")
+ }
+
+ @Test(expected = AssertionError::class)
+ fun cannotUseVeryLongAttributionTags() {
+ installApk("AppWithLongAttributionTag.apk")
+ }
+
+ @Test(expected = AssertionError::class)
+ fun cannotUseTooManyAttributions() {
+ installApk("AppWithTooManyAttributions.apk")
+ }
+}
\ No newline at end of file
diff --git a/tests/tests/appop/src/android/app/appops/cts/FeatureTest.kt b/tests/tests/appop/src/android/app/appops/cts/FeatureTest.kt
deleted file mode 100644
index d199055..0000000
--- a/tests/tests/appop/src/android/app/appops/cts/FeatureTest.kt
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * 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.app.appops.cts
-
-import android.app.AppOpsManager
-import android.app.AppOpsManager.OPSTR_WIFI_SCAN
-import android.app.AppOpsManager.OP_FLAGS_ALL
-import android.platform.test.annotations.AppModeFull
-import androidx.test.platform.app.InstrumentationRegistry
-import com.google.common.truth.Truth.assertThat
-import org.junit.Before
-import org.junit.Test
-import java.lang.AssertionError
-import java.lang.Thread.sleep
-
-private const val APK_PATH = "/data/local/tmp/cts/appops/"
-
-private const val APP_PKG = "android.app.appops.cts.apptoblame"
-
-private const val FEATURE_1 = "feature1"
-private const val FEATURE_2 = "feature2"
-private const val FEATURE_3 = "feature3"
-private const val FEATURE_4 = "feature4"
-private const val FEATURE_5 = "feature5"
-private const val FEATURE_6 = "feature6"
-private const val FEATURE_7 = "feature7"
-
-@AppModeFull(reason = "Test relies on seeing other apps. Instant apps can't see other apps")
-class FeatureTest {
- private val instrumentation = InstrumentationRegistry.getInstrumentation()
- private val context = instrumentation.targetContext
- private val appOpsManager = context.getSystemService(AppOpsManager::class.java)
- private val appUid by lazy { context.packageManager.getPackageUid(APP_PKG, 0) }
-
- private fun installApk(apk: String) {
- val result = runCommand("pm install -r --force-queryable $APK_PATH$apk")
- assertThat(result.trim()).isEqualTo("Success")
- }
-
- @Before
- fun resetTestApp() {
- runCommand("pm uninstall $APP_PKG")
- installApk("CtsAppToBlame1.apk")
- }
-
- private fun noteForFeature(feature: String) {
- // Make sure note times as distinct
- sleep(1)
-
- runWithShellPermissionIdentity {
- appOpsManager.noteOpNoThrow(OPSTR_WIFI_SCAN, appUid, APP_PKG, feature, null)
- }
- }
-
- @Test
- fun inheritNotedAppOpsOnUpgrade() {
- noteForFeature(FEATURE_1)
- noteForFeature(FEATURE_2)
- noteForFeature(FEATURE_3)
- noteForFeature(FEATURE_4)
- noteForFeature(FEATURE_5)
-
- val beforeUpdate = getOpEntry(appUid, APP_PKG, OPSTR_WIFI_SCAN)!!
- installApk("CtsAppToBlame2.apk")
-
- eventually {
- val afterUpdate = getOpEntry(appUid, APP_PKG, OPSTR_WIFI_SCAN)!!
-
- // Feature 1 is unchanged
- assertThat(afterUpdate.features[FEATURE_1]!!.getLastAccessTime(OP_FLAGS_ALL))
- .isEqualTo(beforeUpdate.features[FEATURE_1]!!.getLastAccessTime(OP_FLAGS_ALL))
-
- // Feature 3 disappeared (i.e. was added into "null" feature)
- assertThat(afterUpdate.features[null]!!.getLastAccessTime(OP_FLAGS_ALL))
- .isEqualTo(beforeUpdate.features[FEATURE_3]!!.getLastAccessTime(OP_FLAGS_ALL))
-
- // Feature 6 inherits from feature 2
- assertThat(afterUpdate.features[FEATURE_6]!!.getLastAccessTime(OP_FLAGS_ALL))
- .isEqualTo(beforeUpdate.features[FEATURE_2]!!.getLastAccessTime(OP_FLAGS_ALL))
-
- // Feature 7 inherits from feature 4 and 5. 5 was noted after 4, hence 4 is removed
- assertThat(afterUpdate.features[FEATURE_7]!!.getLastAccessTime(OP_FLAGS_ALL))
- .isEqualTo(beforeUpdate.features[FEATURE_5]!!.getLastAccessTime(OP_FLAGS_ALL))
- }
- }
-
- @Test(expected = AssertionError::class)
- fun cannotInheritFromSelf() {
- installApk("AppWithFeatureInheritingFromSelf.apk")
- }
-
- @Test(expected = AssertionError::class)
- fun noDuplicateFeatures() {
- installApk("AppWithDuplicateFeature.apk")
- }
-
- @Test(expected = AssertionError::class)
- fun cannotInheritFromExisting() {
- installApk("AppWithFeatureInheritingFromExisting.apk")
- }
-
- @Test(expected = AssertionError::class)
- fun cannotInheritFromSameAsOther() {
- installApk("AppWithFeatureInheritingFromSameAsOther.apk")
- }
-
- @Test(expected = AssertionError::class)
- fun cannotUseVeryLongFeatureIDs() {
- installApk("AppWithLongFeatureIdFeature.apk")
- }
-
- @Test(expected = AssertionError::class)
- fun cannotUseTooManyFeatures() {
- installApk("AppWithTooManyFeatures.apk")
- }
-}
\ No newline at end of file
diff --git a/tests/tests/appop/src/android/app/appops/cts/HistoricalAppopsTest.kt b/tests/tests/appop/src/android/app/appops/cts/HistoricalAppopsTest.kt
index 28ebc26..eaef444 100644
--- a/tests/tests/appop/src/android/app/appops/cts/HistoricalAppopsTest.kt
+++ b/tests/tests/appop/src/android/app/appops/cts/HistoricalAppopsTest.kt
@@ -201,7 +201,7 @@
}
@Test
- fun testGetHistoricalAggregationOverFeatures() {
+ fun testGetHistoricalAggregationOverAttributions() {
// Configure historical registry behavior.
appOpsManager.setHistoryParameters(
AppOpsManager.HISTORICAL_MODE_ENABLED_ACTIVE,
@@ -212,17 +212,19 @@
UidStateForceActivity.waitForResumed()
- appOpsManager.noteOp(OPSTR_REQUEST_DELETE_PACKAGES, uid, packageName, "firstFeature", null)
- appOpsManager.noteOp(OPSTR_REQUEST_DELETE_PACKAGES, uid, packageName, "secondFeature", null)
+ appOpsManager.noteOp(OPSTR_REQUEST_DELETE_PACKAGES, uid, packageName, "firstAttribution",
+ null)
+ appOpsManager.noteOp(OPSTR_REQUEST_DELETE_PACKAGES, uid, packageName, "secondAttribution",
+ null)
val memOps = getHistoricalOps(appOpsManager, uid = uid)!!
assertThat(memOps.getUidOpsAt(0).getPackageOpsAt(0).getOp(OPSTR_REQUEST_DELETE_PACKAGES)!!
.getForegroundAccessCount(OP_FLAGS_ALL)).isEqualTo(2)
- assertThat(memOps.getUidOpsAt(0).getPackageOpsAt(0).getFeatureOps("firstFeature")!!
+ assertThat(memOps.getUidOpsAt(0).getPackageOpsAt(0).getAttributedOps("firstAttribution")!!
.getOp(OPSTR_REQUEST_DELETE_PACKAGES)!!.getForegroundAccessCount(OP_FLAGS_ALL))
.isEqualTo(1)
- assertThat(memOps.getUidOpsAt(0).getPackageOpsAt(0).getFeatureOps("secondFeature")!!
+ assertThat(memOps.getUidOpsAt(0).getPackageOpsAt(0).getAttributedOps("secondAttribution")!!
.getOp(OPSTR_REQUEST_DELETE_PACKAGES)!!.getForegroundAccessCount(OP_FLAGS_ALL))
.isEqualTo(1)
diff --git a/tests/tests/appop/src/android/app/appops/cts/RuntimeMessageCollectionTest.kt b/tests/tests/appop/src/android/app/appops/cts/RuntimeMessageCollectionTest.kt
index e6730c1..d5e8748 100644
--- a/tests/tests/appop/src/android/app/appops/cts/RuntimeMessageCollectionTest.kt
+++ b/tests/tests/appop/src/android/app/appops/cts/RuntimeMessageCollectionTest.kt
@@ -58,7 +58,7 @@
val start = System.currentTimeMillis()
runWithShellPermissionIdentity {
appOpsManager.noteOp(AppOpsManager.OPSTR_READ_CONTACTS, appUid, APP_PKG,
- TEST_FEATURE_ID, MESSAGE)
+ TEST_ATTRIBUTION_TAG, MESSAGE)
}
while (System.currentTimeMillis() - start < TIMEOUT_MILLIS) {
sleep(200)
@@ -68,7 +68,7 @@
if (message != null && message.packageName.equals(APP_PKG)) {
assertThat(message.op).isEqualTo(AppOpsManager.OPSTR_READ_CONTACTS)
assertThat(message.uid).isEqualTo(appUid)
- assertThat(message.featureId).isEqualTo(TEST_FEATURE_ID)
+ assertThat(message.attributionTag).isEqualTo(TEST_ATTRIBUTION_TAG)
assertThat(message.message).isEqualTo(MESSAGE)
assertThat(message.samplingStrategy)
.isEqualTo(RUNTIME_APP_OP_ACCESS__SAMPLING_STRATEGY__RARELY_USED)
diff --git a/tests/tests/batterysaving/src/android/os/cts/batterysaving/BatterySaverTest.java b/tests/tests/batterysaving/src/android/os/cts/batterysaving/BatterySaverTest.java
index afae17e..56fce94 100644
--- a/tests/tests/batterysaving/src/android/os/cts/batterysaving/BatterySaverTest.java
+++ b/tests/tests/batterysaving/src/android/os/cts/batterysaving/BatterySaverTest.java
@@ -17,6 +17,7 @@
import static com.android.compatibility.common.util.BatteryUtils.enableBatterySaver;
import static com.android.compatibility.common.util.BatteryUtils.runDumpsysBatteryUnplug;
+import static com.android.compatibility.common.util.TestUtils.waitUntil;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -112,36 +113,38 @@
enableBatterySaver(true);
- // Allow time for UI change.
- Thread.sleep(1000);
assertTrue(powerManager.isPowerSaveMode());
assertEquals(PowerManager.LOCATION_MODE_ALL_DISABLED_WHEN_SCREEN_OFF,
powerManager.getLocationPowerSaveMode());
- assertEquals(Configuration.UI_MODE_NIGHT_YES,
- getContext().getResources().getConfiguration().uiMode
- & Configuration.UI_MODE_NIGHT_MASK);
+ // UI change can take a while to propagate, so need to wait for this check.
+ waitUntil("UI mode didn't change to " + Configuration.UI_MODE_NIGHT_YES,
+ () -> Configuration.UI_MODE_NIGHT_YES ==
+ (getContext().getResources().getConfiguration().uiMode
+ & Configuration.UI_MODE_NIGHT_MASK));
uiModeManager.enableCarMode(0);
- // Allow time for UI change.
- Thread.sleep(1000);
+ // Wait for UI change first before checking location mode since we can then be
+ // confident that the broadcast has been processed.
+ waitUntil("UI mode didn't change to " + Configuration.UI_MODE_NIGHT_NO,
+ () -> Configuration.UI_MODE_NIGHT_NO ==
+ (getContext().getResources().getConfiguration().uiMode
+ & Configuration.UI_MODE_NIGHT_MASK));
final int locationPowerSaveMode = powerManager.getLocationPowerSaveMode();
assertTrue("Location power save mode didn't change from " + locationPowerSaveMode,
locationPowerSaveMode == PowerManager.LOCATION_MODE_FOREGROUND_ONLY
|| locationPowerSaveMode == PowerManager.LOCATION_MODE_NO_CHANGE);
- assertEquals(Configuration.UI_MODE_NIGHT_NO,
- getContext().getResources().getConfiguration().uiMode
- & Configuration.UI_MODE_NIGHT_MASK);
uiModeManager.disableCarMode(0);
- // Allow time for UI change.
- Thread.sleep(1000);
+ // Wait for UI change first before checking location mode since we can then be
+ // confident that the broadcast has been processed.
+ waitUntil("UI mode didn't change to " + Configuration.UI_MODE_NIGHT_YES,
+ () -> Configuration.UI_MODE_NIGHT_YES ==
+ (getContext().getResources().getConfiguration().uiMode
+ & Configuration.UI_MODE_NIGHT_MASK));
assertEquals(PowerManager.LOCATION_MODE_ALL_DISABLED_WHEN_SCREEN_OFF,
powerManager.getLocationPowerSaveMode());
- assertEquals(Configuration.UI_MODE_NIGHT_YES,
- getContext().getResources().getConfiguration().uiMode
- & Configuration.UI_MODE_NIGHT_MASK);
} finally {
uiModeManager.disableCarMode(0);
SettingsUtils.delete(SettingsUtils.NAMESPACE_GLOBAL, "battery_saver_constants");
diff --git a/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/1/.hash b/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/1/.hash
index 9c76fef..425104b 100644
--- a/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/1/.hash
+++ b/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/1/.hash
@@ -1 +1 @@
-8d903ce236a40b41624907c4d1d7a651eca9f763 -
+d755ae773aaabd1c48d22b823e29501ee387aff1
diff --git a/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/2/.hash b/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/2/.hash
index ad2b69c3..fce7d03 100644
--- a/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/2/.hash
+++ b/tests/tests/binder_ndk/libbinder_ndk_test/aidl_api/libbinder_ndk_test_interface/2/.hash
@@ -1 +1 @@
-8359746d4317c0ef0f014821d362c4cfe96e2166 -
+3589e207cd708912b7551fb40b7fb263ef3e81b4
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 cee0944..f4aa698 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
@@ -808,7 +808,7 @@
EXPECT_OK(iface->getInterfaceHash(&res));
if (GetParam().shouldBeOld) {
// aidl_api/libbinder_ndk_test_interface/1/.hash
- EXPECT_EQ("8d903ce236a40b41624907c4d1d7a651eca9f763", res);
+ EXPECT_EQ("d755ae773aaabd1c48d22b823e29501ee387aff1", res);
} else {
EXPECT_EQ("notfrozen", res);
}
diff --git a/tests/tests/car/AndroidManifest.xml b/tests/tests/car/AndroidManifest.xml
index d146b32..3894b0b 100644
--- a/tests/tests/car/AndroidManifest.xml
+++ b/tests/tests/car/AndroidManifest.xml
@@ -29,6 +29,8 @@
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
<uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
+ <!-- Allow query of any normal app on the device -->
+ <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
<application>
<uses-library android:name="android.test.runner" />
diff --git a/tests/tests/car/res/values/minimum_required_packages.xml b/tests/tests/car/res/values/minimum_required_packages.xml
new file mode 100644
index 0000000..b730bbf
--- /dev/null
+++ b/tests/tests/car/res/values/minimum_required_packages.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 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
+ -->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string-array translatable="false" name="installed_system_and_full">
+ <item>android</item>
+ <item>com.android.car</item>
+ <item>com.android.car.frameworkpackagestubs</item>
+ </string-array>
+
+ <string-array translatable="false" name="installed_full_only">
+ <item>com.google.android.carassistant</item>
+ </string-array>
+</resources>
\ No newline at end of file
diff --git a/tests/tests/car/src/android/car/cts/CarInfoManagerTest.java b/tests/tests/car/src/android/car/cts/CarInfoManagerTest.java
index f901a4a..d7135da 100644
--- a/tests/tests/car/src/android/car/cts/CarInfoManagerTest.java
+++ b/tests/tests/car/src/android/car/cts/CarInfoManagerTest.java
@@ -15,7 +15,7 @@
*/
package android.car.cts;
-import static org.junit.Assert.assertNotNull;
+import static com.google.common.truth.Truth.assertThat;
import android.car.Car;
import android.car.CarInfoManager;
@@ -26,15 +26,15 @@
import android.platform.test.annotations.RequiresDevice;
import android.test.suitebuilder.annotation.SmallTest;
-import static com.google.common.truth.Truth.assertThat;
import androidx.test.runner.AndroidJUnit4;
-import java.util.Arrays;
-import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.util.Arrays;
+import java.util.List;
+
@SmallTest
@RequiresDevice
@RunWith(AndroidJUnit4.class)
@@ -54,22 +54,24 @@
@Test
public void testVehicleId() throws Exception {
- assertNotNull(mCarInfoManager.getVehicleId());
+ // Not support to get vehicle Id.
+ assertThat(mCarInfoManager.getVehicleId()).isEmpty();
}
@Test
public void testGetManufacturer() throws Exception {
- assertNotNull(mCarInfoManager.getManufacturer());
+ assertThat(mCarInfoManager.getManufacturer()).isNotNull();;
}
@Test
public void testGetModel() throws Exception {
- assertNotNull(mCarInfoManager.getModel());
+ assertThat(mCarInfoManager.getModel()).isNotNull();
}
@Test
public void testGetModelYear() throws Exception {
- assertNotNull(mCarInfoManager.getModelYear());
+ assertThat(mCarInfoManager.getModelYear()).isNotNull();
+ assertThat(mCarInfoManager.getModelYearInInteger()).isAtLeast(0);
}
@Test
@@ -83,7 +85,7 @@
*/
@Test
public void testGetFuelTypes() throws Exception {
- assertNotNull(mCarInfoManager.getFuelTypes());
+ assertThat(mCarInfoManager.getFuelTypes()).isNotNull();
int[] actualResults = mCarInfoManager.getFuelTypes();
for (int result : actualResults) {
assertThat(result).isIn(EXPECTED_FUEL_TYPES);
@@ -103,7 +105,7 @@
*/
@Test
public void testGetEvConnectorTypes() throws Exception {
- assertNotNull(mCarInfoManager.getEvConnectorTypes());
+ assertThat(mCarInfoManager.getEvConnectorTypes()).isNotNull();
int[] actualResults = mCarInfoManager.getEvConnectorTypes();
List<Integer> expectedResults =
diff --git a/tests/tests/car/src/android/car/cts/CarPropertyManagerTest.java b/tests/tests/car/src/android/car/cts/CarPropertyManagerTest.java
index 8f2057d..8a2cc19 100644
--- a/tests/tests/car/src/android/car/cts/CarPropertyManagerTest.java
+++ b/tests/tests/car/src/android/car/cts/CarPropertyManagerTest.java
@@ -15,16 +15,10 @@
*/
package android.car.cts;
-import static org.testng.Assert.assertThrows;
import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
-import static java.lang.Integer.toHexString;
+import static org.testng.Assert.assertThrows;
import android.car.Car;
import android.car.VehicleAreaSeat;
@@ -37,7 +31,6 @@
import android.platform.test.annotations.RequiresDevice;
import android.test.suitebuilder.annotation.SmallTest;
import android.util.ArraySet;
-import android.util.Log;
import android.util.SparseArray;
import androidx.annotation.GuardedBy;
@@ -60,6 +53,7 @@
private static final String TAG = CarPropertyManagerTest.class.getSimpleName();
private static final long WAIT_CALLBACK = 1500L;
+ private static final int NO_EVENTS = 0;
private CarPropertyManager mCarPropertyManager;
/** contains property Ids for the properties required by CDD*/
private ArraySet<Integer> mPropertyIds = new ArraySet<>();
@@ -123,7 +117,7 @@
@Test
public void testGetPropertyList() {
List<CarPropertyConfig> allConfigs = mCarPropertyManager.getPropertyList();
- assertNotNull(allConfigs);
+ assertThat(allConfigs).isNotNull();
}
/**
@@ -133,7 +127,7 @@
public void testGetPropertyListWithArraySet() {
List<CarPropertyConfig> requiredConfigs = mCarPropertyManager.getPropertyList(mPropertyIds);
// Vehicles need to implement all of those properties
- assertEquals(mPropertyIds.size(), requiredConfigs.size());
+ assertThat(requiredConfigs.size()).isEqualTo(mPropertyIds.size());
}
/**
@@ -143,7 +137,7 @@
public void testGetPropertyConfig() {
List<CarPropertyConfig> allConfigs = mCarPropertyManager.getPropertyList();
for (CarPropertyConfig cfg : allConfigs) {
- assertNotNull(mCarPropertyManager.getCarPropertyConfig(cfg.getPropertyId()));
+ assertThat(mCarPropertyManager.getCarPropertyConfig(cfg.getPropertyId())).isNotNull();
}
}
@@ -156,8 +150,9 @@
List<CarPropertyConfig> allConfigs = mCarPropertyManager.getPropertyList();
for (CarPropertyConfig cfg : allConfigs) {
if (cfg.isGlobalProperty()) {
- assertEquals(0, mCarPropertyManager.getAreaId(cfg.getPropertyId(),
- VehicleAreaSeat.SEAT_ROW_1_LEFT));
+ assertThat(mCarPropertyManager.getAreaId(cfg.getPropertyId(),
+ VehicleAreaSeat.SEAT_ROW_1_LEFT))
+ .isEqualTo(VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL);
} else {
int[] areaIds = cfg.getAreaIds();
// Because areaId in propConfig must not be overlapped with each other.
@@ -165,7 +160,7 @@
for (int areaIdInConfig : areaIds) {
int areaIdByCarPropertyManager =
mCarPropertyManager.getAreaId(cfg.getPropertyId(), areaIdInConfig);
- assertEquals(areaIdInConfig, areaIdByCarPropertyManager);
+ assertThat(areaIdByCarPropertyManager).isEqualTo(areaIdInConfig);
}
}
}
@@ -174,33 +169,34 @@
@CddTest(requirement="2.5.1")
@Test
public void testMustSupportGearSelection() throws Exception {
- assertTrue("Must support GEAR_SELECTION",
- mCarPropertyManager.getPropertyList().stream().anyMatch(cfg -> cfg.getPropertyId() ==
- VehiclePropertyIds.GEAR_SELECTION));
+ assertWithMessage("Must support GEAR_SELECTION")
+ .that(mCarPropertyManager.getCarPropertyConfig(VehiclePropertyIds.GEAR_SELECTION))
+ .isNotNull();
}
@CddTest(requirement="2.5.1")
@Test
public void testMustSupportNightMode() {
- assertTrue("Must support NIGHT_MODE",
- mCarPropertyManager.getPropertyList().stream().anyMatch(cfg -> cfg.getPropertyId() ==
- VehiclePropertyIds.NIGHT_MODE));
+ assertWithMessage("Must support NIGHT_MODE")
+ .that(mCarPropertyManager.getCarPropertyConfig(VehiclePropertyIds.NIGHT_MODE))
+ .isNotNull();
}
@CddTest(requirement="2.5.1")
@Test
public void testMustSupportPerfVehicleSpeed() throws Exception {
- assertTrue("Must support PERF_VEHICLE_SPEED",
- mCarPropertyManager.getPropertyList().stream().anyMatch(cfg -> cfg.getPropertyId() ==
- VehiclePropertyIds.PERF_VEHICLE_SPEED));
+ assertWithMessage("Must support PERF_VEHICLE_SPEED")
+ .that(mCarPropertyManager.getCarPropertyConfig(
+ VehiclePropertyIds.PERF_VEHICLE_SPEED)).isNotNull();
}
@CddTest(requirement = "2.5.1")
@Test
public void testMustSupportParkingBrakeOn() throws Exception {
- assertTrue("Must support PARKING_BRAKE_ON",
- mCarPropertyManager.getPropertyList().stream().anyMatch(cfg -> cfg.getPropertyId() ==
- VehiclePropertyIds.PARKING_BRAKE_ON));
+ assertWithMessage("Must support PARKING_BRAKE_ON")
+ .that(mCarPropertyManager.getCarPropertyConfig(VehiclePropertyIds.PARKING_BRAKE_ON))
+ .isNotNull();
+
}
@SuppressWarnings("unchecked")
@@ -286,7 +282,8 @@
for (CarPropertyConfig cfg : configs) {
int[] areaIds = getAreaIdsHelper(cfg);
for (int areaId : areaIds) {
- assertTrue(mCarPropertyManager.isPropertyAvailable(cfg.getPropertyId(), areaId));
+ assertThat(mCarPropertyManager.isPropertyAvailable(cfg.getPropertyId(), areaId))
+ .isTrue();
}
}
}
@@ -313,17 +310,17 @@
int invalidPropertyId = -1;
boolean isRegistered = mCarPropertyManager.registerCallback(
new CarPropertyEventCounter(), invalidPropertyId, 0);
- assertFalse(isRegistered);
+ assertThat(isRegistered).isFalse();
// Test for continuous properties
int vehicleSpeed = VehiclePropertyIds.PERF_VEHICLE_SPEED;
CarPropertyEventCounter speedListenerNormal = new CarPropertyEventCounter();
CarPropertyEventCounter speedListenerUI = new CarPropertyEventCounter();
- assertEquals(0, speedListenerNormal.receivedEvent(vehicleSpeed));
- assertEquals(0, speedListenerNormal.receivedError(vehicleSpeed));
- assertEquals(0, speedListenerUI.receivedEvent(vehicleSpeed));
- assertEquals(0, speedListenerUI.receivedError(vehicleSpeed));
+ assertThat(speedListenerNormal.receivedEvent(vehicleSpeed)).isEqualTo(NO_EVENTS);
+ assertThat(speedListenerNormal.receivedError(vehicleSpeed)).isEqualTo(NO_EVENTS);
+ assertThat(speedListenerUI.receivedEvent(vehicleSpeed)).isEqualTo(NO_EVENTS);
+ assertThat(speedListenerUI.receivedError(vehicleSpeed)).isEqualTo(NO_EVENTS);
mCarPropertyManager.registerCallback(speedListenerNormal, vehicleSpeed,
CarPropertyManager.SENSOR_RATE_NORMAL);
@@ -331,9 +328,8 @@
CarPropertyManager.SENSOR_RATE_FASTEST);
// TODO(b/149778976): Use CountDownLatch in listener instead of waitingTime
Thread.sleep(WAIT_CALLBACK);
- assertNotEquals(0, speedListenerNormal.receivedEvent(vehicleSpeed));
- assertNotEquals(0, speedListenerUI.receivedEvent(vehicleSpeed));
- assertTrue(speedListenerUI.receivedEvent(vehicleSpeed) >
+ assertThat(speedListenerNormal.receivedEvent(vehicleSpeed)).isGreaterThan(NO_EVENTS);
+ assertThat(speedListenerUI.receivedEvent(vehicleSpeed)).isGreaterThan(
speedListenerNormal.receivedEvent(vehicleSpeed));
mCarPropertyManager.unregisterCallback(speedListenerUI);
@@ -344,8 +340,7 @@
CarPropertyEventCounter nightModeListener = new CarPropertyEventCounter();
mCarPropertyManager.registerCallback(nightModeListener, nightMode, 0);
Thread.sleep(WAIT_CALLBACK);
- assertEquals(1, nightModeListener.receivedEvent(nightMode));
-
+ assertThat(nightModeListener.receivedEvent(nightMode)).isEqualTo(1);
mCarPropertyManager.unregisterCallback(nightModeListener);
}
@@ -378,15 +373,15 @@
int currentEventUI = speedListenerUI.receivedEvent(vehicleSpeed);
Thread.sleep(WAIT_CALLBACK);
- assertEquals(currentEventNormal, speedListenerNormal.receivedEvent(vehicleSpeed));
- assertNotEquals(currentEventUI, speedListenerUI.receivedEvent(vehicleSpeed));
+ assertThat(speedListenerNormal.receivedEvent(vehicleSpeed)).isEqualTo(currentEventNormal);
+ assertThat(speedListenerUI.receivedEvent(vehicleSpeed)).isNotEqualTo(currentEventUI);
mCarPropertyManager.unregisterCallback(speedListenerUI);
Thread.sleep(WAIT_CALLBACK);
currentEventUI = speedListenerUI.receivedEvent(vehicleSpeed);
Thread.sleep(WAIT_CALLBACK);
- assertEquals(currentEventUI, speedListenerUI.receivedEvent(vehicleSpeed));
+ assertThat(speedListenerUI.receivedEvent(vehicleSpeed)).isEqualTo(currentEventUI);
}
@Test
diff --git a/tests/tests/car/src/android/car/cts/CarUserManagerTest.java b/tests/tests/car/src/android/car/cts/CarUserManagerTest.java
index ad16148..bf76d3d 100644
--- a/tests/tests/car/src/android/car/cts/CarUserManagerTest.java
+++ b/tests/tests/car/src/android/car/cts/CarUserManagerTest.java
@@ -16,6 +16,7 @@
package android.car.cts;
import static android.os.Process.myUid;
+import static android.os.UserHandle.USER_SYSTEM;
import static com.android.compatibility.common.util.ShellIdentityUtils.invokeMethodWithShellPermissions;
import static com.android.compatibility.common.util.ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn;
@@ -23,6 +24,8 @@
import static com.android.compatibility.common.util.TestUtils.BooleanSupplierWithThrow;
import static com.google.common.truth.Truth.assertWithMessage;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.testng.Assert.assertThrows;
@@ -32,6 +35,7 @@
import android.car.Car;
import android.car.user.CarUserManager;
import android.car.user.CarUserManager.UserLifecycleListener;
+import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.PowerManager;
import android.os.SystemClock;
@@ -46,6 +50,7 @@
import org.junit.Test;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
@@ -79,6 +84,8 @@
private static CarUserManager sCarUserManager;
+ private PackageManager mPackageManager;
+
private static int sInitialUserId = UserHandle.myUserId();
private static int sNewUserId = UserHandle.USER_NULL;
@@ -100,6 +107,8 @@
sNewUserId = createNewUser("CarUserManagerTest", /* isGuestUser= */ false);
Log.i(TAG, "setUp(): myUid=" + myUid() + ", currentUser=" + sInitialUserId
+ ", newUser=" + sNewUserId);
+
+ mPackageManager = sContext.getPackageManager();
}
@AfterClass
@@ -278,6 +287,37 @@
}
}
+ @Test
+ public void testPackageInstalledForSystemAndFullUser() throws Exception {
+ String[] packages = sContext.getResources()
+ .getStringArray(R.array.installed_system_and_full);
+ for (String pkg : packages) {
+ assertWithMessage(pkg + " should be installed for system user.")
+ .that(isInstalled(pkg, USER_SYSTEM)).isTrue();
+ assertWithMessage(pkg + " should be installed for system user.")
+ .that(isInstalled(pkg, sNewUserId)).isTrue();
+ }
+ }
+
+ @Test
+ public void testPackageInstalledForFullUserOnly() throws Exception {
+ String[] packages = sContext.getResources()
+ .getStringArray(R.array.installed_full_only);
+ for (String pkg : packages) {
+ assertWithMessage(pkg + " should not be installed for system user.")
+ .that(isInstalled(pkg, USER_SYSTEM)).isFalse();
+ assertWithMessage(pkg + " should be installed for full user")
+ .that(isInstalled(pkg, sNewUserId)).isTrue();
+ }
+ }
+
+ private boolean isInstalled(String packageName, int userId) {
+ List<PackageInfo> packages = new ArrayList<PackageInfo>();
+ packages = mPackageManager.getInstalledPackagesAsUser(/*PackageInfoFlags = */ 0, userId);
+ return packages.stream().filter(pkg -> pkg.packageName.equals(packageName))
+ .findAny().orElse(null) != null;
+ }
+
/**
* Creates a new Android user, returning its id.
*/
diff --git a/tests/tests/contactsproviderwipe/src/android/provider/cts/contactsproviderwipe/ContactsContract_Wipe.java b/tests/tests/contactsproviderwipe/src/android/provider/cts/contactsproviderwipe/ContactsContract_Wipe.java
index 8bc8134..d1bd895 100644
--- a/tests/tests/contactsproviderwipe/src/android/provider/cts/contactsproviderwipe/ContactsContract_Wipe.java
+++ b/tests/tests/contactsproviderwipe/src/android/provider/cts/contactsproviderwipe/ContactsContract_Wipe.java
@@ -185,6 +185,9 @@
@Override
public void onChange(boolean selfChange, Uri uri) {
Log.i(TAG, "Received notification on " + uri);
+ if (uri == null || !uri.equals(ProviderStatus.CONTENT_URI)) {
+ return; // we only care about a change to ProviderStatus.CONTENT_URI
+ }
notifiedUri.set(uri);
latch.countDown();
}
diff --git a/tests/tests/content/Android.bp b/tests/tests/content/Android.bp
index fa04cba..311974b 100644
--- a/tests/tests/content/Android.bp
+++ b/tests/tests/content/Android.bp
@@ -41,6 +41,7 @@
// TODO: remove once Android migrates to JUnit 4.12, which provides assertThrows:
"testng",
"androidx.legacy_legacy-support-v4",
+ "androidx.test.core",
],
// Use multi-dex as the compatibility-common-util-devicesidelib dependency
// on compatibility-device-util-axt pushes us beyond 64k methods.
diff --git a/tests/tests/content/data/v4-only-original.apk.idsig b/tests/tests/content/data/v4-only-original.apk.idsig
index 3ac4c80..c6ea405 100644
--- a/tests/tests/content/data/v4-only-original.apk.idsig
+++ b/tests/tests/content/data/v4-only-original.apk.idsig
Binary files differ
diff --git a/tests/tests/content/src/android/content/cts/ContextAccessTest.java b/tests/tests/content/src/android/content/cts/ContextAccessTest.java
new file mode 100644
index 0000000..9abd8d9
--- /dev/null
+++ b/tests/tests/content/src/android/content/cts/ContextAccessTest.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2020 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.content.cts;
+
+import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import android.app.Activity;
+import android.app.Service;
+import android.content.Context;
+import android.content.ContextWrapper;
+import android.content.Intent;
+import android.hardware.display.DisplayManager;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.platform.test.annotations.Presubmit;
+import android.view.Display;
+
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.filters.SmallTest;
+import androidx.test.rule.ActivityTestRule;
+import androidx.test.rule.ServiceTestRule;
+
+import org.junit.Rule;
+import org.junit.Test;
+
+import java.util.concurrent.TimeoutException;
+
+/**
+ * Test for {@link Context#getDisplay()}.
+ * <p>Test context type listed below:</p>
+ * <ul>
+ * <li>{@link android.app.Application} - throw exception</li>
+ * <li>{@link Service} - throw exception</li>
+ * <li>{@link Activity} - get {@link Display} entity</li>
+ * <li>Context via {@link Context#createWindowContext(int, Bundle)}
+ * - get {@link Display} entity</li>
+ * <li>Context via {@link Context#createDisplayContext(Display)}
+ * - get {@link Display} entity</li>
+ * <li>{@link ContextWrapper} with base display-associated {@link Context}
+ * - get {@link Display} entity</li>
+ * <li>{@link ContextWrapper} with base non-display-associated {@link Context}
+ * - get {@link Display} entity</li>
+ * </ul>
+ *
+ * <p>Build/Install/Run:
+ * atest CtsContentTestCases:ContextAccessTest
+ */
+@Presubmit
+@SmallTest
+public class ContextAccessTest {
+ private Context mContext = ApplicationProvider.getApplicationContext();
+
+ @Rule
+ public final ActivityTestRule<MockActivity> mActivityRule =
+ new ActivityTestRule<>(MockActivity.class);
+
+ @Test(expected = UnsupportedOperationException.class)
+ public void testGetDisplayFromApplication() {
+ mContext.getDisplay();
+ }
+
+ @Test(expected = UnsupportedOperationException.class)
+ public void testGetDisplayFromService() throws TimeoutException {
+ getTestService().getDisplay();
+ }
+
+ @Test
+ public void testGetDisplayFromActivity() throws Throwable {
+ final Display d = getTestActivity().getDisplay();
+
+ assertNotNull("Display must be accessible from visual components", d);
+ }
+
+ @Test
+ public void testGetDisplayFromDisplayContext() {
+ final Display display = mContext.getSystemService(DisplayManager.class)
+ .getDisplay(DEFAULT_DISPLAY);
+ Context displayContext = mContext.createDisplayContext(display);
+
+ assertEquals(display, displayContext.getDisplay());
+ }
+
+ @Test
+ public void testGetDisplayFromWindowContext() {
+ final Display display = mContext.getSystemService(DisplayManager.class)
+ .getDisplay(DEFAULT_DISPLAY);
+ Context windowContext = mContext.createDisplayContext(display)
+ .createWindowContext(TYPE_APPLICATION_OVERLAY, null /* options */);
+ assertEquals(display, windowContext.getDisplay());
+ }
+
+ @Test
+ public void testGetDisplayFromVisualWrapper() throws Throwable {
+ final Display d = new ContextWrapper(getTestActivity()).getDisplay();
+
+ assertNotNull("Display must be accessible from visual components", d);
+ }
+
+ @Test(expected = UnsupportedOperationException.class)
+ public void testGetDisplayFromNonVisualWrapper() {
+ ContextWrapper wrapper = new ContextWrapper(mContext);
+ wrapper.getDisplay();
+ }
+
+ private Activity getTestActivity() throws Throwable {
+ MockActivity[] activity = new MockActivity[1];
+ mActivityRule.runOnUiThread(() -> {
+ activity[0] = mActivityRule.getActivity();
+ });
+ return activity[0];
+ }
+
+ private Service getTestService() throws TimeoutException {
+ final Intent intent = new Intent(mContext.getApplicationContext(), MockService.class);
+ final ServiceTestRule serviceRule = new ServiceTestRule();
+ IBinder serviceToken;
+ serviceToken = serviceRule.bindService(intent);
+ return ((MockService.MockBinder) serviceToken).getService();
+ }
+}
diff --git a/tests/tests/content/src/android/content/cts/ContextTest.java b/tests/tests/content/src/android/content/cts/ContextTest.java
index 5a41584..f6f7cf5 100644
--- a/tests/tests/content/src/android/content/cts/ContextTest.java
+++ b/tests/tests/content/src/android/content/cts/ContextTest.java
@@ -1414,6 +1414,64 @@
}.run();
}
+ /** The receiver should get the broadcast if it has all the permissions. */
+ public void testSendBroadcastWithMultiplePermissions_receiverHasAllPermissions()
+ throws Exception {
+ final ResultReceiver receiver = new ResultReceiver();
+
+ registerBroadcastReceiver(receiver, new IntentFilter(ResultReceiver.MOCK_ACTION));
+
+ mContext.sendBroadcastWithMultiplePermissions(
+ new Intent(ResultReceiver.MOCK_ACTION),
+ new String[] { // this test APK has both these permissions
+ android.Manifest.permission.ACCESS_WIFI_STATE,
+ android.Manifest.permission.ACCESS_NETWORK_STATE,
+ });
+
+ new PollingCheck(BROADCAST_TIMEOUT) {
+ @Override
+ protected boolean check() {
+ return receiver.hasReceivedBroadCast();
+ }
+ }.run();
+ }
+
+ /** The receiver should not get the broadcast if it does not have all the permissions. */
+ public void testSendBroadcastWithMultiplePermissions_receiverHasSomePermissions()
+ throws Exception {
+ final ResultReceiver receiver = new ResultReceiver();
+
+ registerBroadcastReceiver(receiver, new IntentFilter(ResultReceiver.MOCK_ACTION));
+
+ mContext.sendBroadcastWithMultiplePermissions(
+ new Intent(ResultReceiver.MOCK_ACTION),
+ new String[] { // this test APK only has ACCESS_WIFI_STATE
+ android.Manifest.permission.ACCESS_WIFI_STATE,
+ android.Manifest.permission.NETWORK_STACK,
+ });
+
+ Thread.sleep(BROADCAST_TIMEOUT);
+ assertFalse(receiver.hasReceivedBroadCast());
+ }
+
+ /** The receiver should not get the broadcast if it has none of the permissions. */
+ public void testSendBroadcastWithMultiplePermissions_receiverHasNoPermissions()
+ throws Exception {
+ final ResultReceiver receiver = new ResultReceiver();
+
+ registerBroadcastReceiver(receiver, new IntentFilter(ResultReceiver.MOCK_ACTION));
+
+ mContext.sendBroadcastWithMultiplePermissions(
+ new Intent(ResultReceiver.MOCK_ACTION),
+ new String[] { // this test APK has neither of these permissions
+ android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_STACK,
+ });
+
+ Thread.sleep(BROADCAST_TIMEOUT);
+ assertFalse(receiver.hasReceivedBroadCast());
+ }
+
public void testEnforceCallingOrSelfUriPermission() {
try {
Uri uri = Uri.parse("content://ctstest");
diff --git a/tests/tests/content/src/android/content/pm/cts/PackageManagerShellCommandTest.java b/tests/tests/content/src/android/content/pm/cts/PackageManagerShellCommandTest.java
index 1467cba..41c5d07 100644
--- a/tests/tests/content/src/android/content/pm/cts/PackageManagerShellCommandTest.java
+++ b/tests/tests/content/src/android/content/pm/cts/PackageManagerShellCommandTest.java
@@ -51,7 +51,7 @@
import java.util.stream.Collectors;
@RunWith(Parameterized.class)
-@AppModeFull // TODO(Instant) Figure out which APIs should work.
+@AppModeFull
public class PackageManagerShellCommandTest {
private static final String TEST_APP_PACKAGE = "com.example.helloworld";
@@ -377,6 +377,18 @@
assertEquals("base, config.mdpi, config.xxhdpi", getSplits(TEST_APP_PACKAGE));
}
+ @Test
+ public void testAppInstallErrDuplicate() throws Exception {
+ if (!mStreaming) {
+ return;
+ }
+ String split = createApkPath(TEST_HW5);
+ String commandResult = executeShellCommand(
+ "pm " + mInstall + " -t -g " + split + " " + split);
+ assertEquals("Failure [failed to add file(s)]\n", commandResult);
+ assertFalse(isAppInstalled(TEST_APP_PACKAGE));
+ }
+
private String createUpdateSession(String packageName) throws IOException {
return createSession("-p " + packageName);
}
diff --git a/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java b/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java
index 46592ca..5cb08a1 100644
--- a/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java
+++ b/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java
@@ -53,6 +53,7 @@
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
import static org.hamcrest.Matchers.hasItems;
+import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Build;
import android.os.SystemProperties;
@@ -164,6 +165,10 @@
KM_PURPOSE_SIGN, KM_PURPOSE_VERIFY, KM_PURPOSE_SIGN | KM_PURPOSE_VERIFY
};
+ // Skip the test if there is no secure lock screen
+ if (!hasSecureLockScreen()) {
+ return;
+ }
for (int curveIndex = 0; curveIndex < curves.length; ++curveIndex) {
for (int challengeIndex = 0; challengeIndex < challenges.length; ++challengeIndex) {
for (int purposeIndex = 0; purposeIndex < purposes.length; ++purposeIndex) {
@@ -326,6 +331,10 @@
},
};
+ // Skip the test if there is no secure lock screen
+ if (!hasSecureLockScreen()) {
+ return;
+ }
for (int keySize : keySizes) {
for (byte[] challenge : challenges) {
for (int purpose : purposes) {
@@ -1145,4 +1154,15 @@
}
}
}
+ /*
+ * Device that don't report android.software.device_admin doesn't have secure lock screen
+ * because device with secure lock screen MUST report android.software.device_admin .
+ *
+ * https://source.android.com/compatibility/7.0/android-7.0-cdd.html#3_9_device_administration
+ *
+ */
+ private boolean hasSecureLockScreen() {
+ PackageManager pm = getContext().getPackageManager();
+ return pm.hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN);
+ }
}
diff --git a/tests/tests/media/Android.bp b/tests/tests/media/Android.bp
index 83d6aef..0414e7d 100644
--- a/tests/tests/media/Android.bp
+++ b/tests/tests/media/Android.bp
@@ -59,6 +59,7 @@
"-0 .ts",
"-0 .heic",
"-0 .trp",
+ "-0 .ota",
],
srcs: ["src/**/*.java"],
// This test uses private APIs
diff --git a/tests/tests/media/res/raw/testimy.imy b/tests/tests/media/res/raw/testimy.imy
new file mode 100644
index 0000000..d837815
--- /dev/null
+++ b/tests/tests/media/res/raw/testimy.imy
@@ -0,0 +1,10 @@
+BEGIN:IMELODY
+VERSION:1.2
+FORMAT:CLASS1.0
+NAME:Test
+COMPOSER:Android
+BEAT:120
+STYLE:S1
+VOLUME:V7
+MELODY:a1b2c3backoffa3.backon*4d3a3backoffg3.backon*5c4c1*5#f2*5#f2
+END:IMELODY
diff --git a/tests/tests/media/res/raw/testota.ota b/tests/tests/media/res/raw/testota.ota
new file mode 100644
index 0000000..7aa5f996
--- /dev/null
+++ b/tests/tests/media/res/raw/testota.ota
Binary files differ
diff --git a/tests/tests/media/res/raw/testrtttl.rtttl b/tests/tests/media/res/raw/testrtttl.rtttl
new file mode 100644
index 0000000..1f7e270
--- /dev/null
+++ b/tests/tests/media/res/raw/testrtttl.rtttl
@@ -0,0 +1 @@
+Test:d=2,o=6,b=120,l=2,s=n:a,b,c,d,e,4a,4b#,4c,4d,a4,b4,c4,d4
diff --git a/tests/tests/media/src/android/media/cts/AudioMetadataTest.java b/tests/tests/media/src/android/media/cts/AudioMetadataTest.java
index 4272363..8fa4eaa 100755
--- a/tests/tests/media/src/android/media/cts/AudioMetadataTest.java
+++ b/tests/tests/media/src/android/media/cts/AudioMetadataTest.java
@@ -112,6 +112,63 @@
);
}
+ // Vendor keys created by direct override of the AudioMetadata interface.
+ private static final AudioMetadata.Key<Integer>
+ KEY_VENDOR_INTEGER = new AudioMetadata.Key<Integer>() {
+ @Override
+ public String getName() {
+ return "vendor.integerData";
+ }
+
+ @Override
+ public Class<Integer> getValueClass() {
+ return Integer.class; // matches Class<Integer>
+ }
+ };
+
+ private static final AudioMetadata.Key<Double>
+ KEY_VENDOR_DOUBLE = new AudioMetadata.Key<Double>() {
+ @Override
+ public String getName() {
+ return "vendor.doubleData";
+ }
+
+ @Override
+ public Class<Double> getValueClass() {
+ return Double.class; // matches Class<Double>
+ }
+ };
+
+ private static final AudioMetadata.Key<String>
+ KEY_VENDOR_STRING = new AudioMetadata.Key<String>() {
+ @Override
+ public String getName() {
+ return "vendor.stringData";
+ }
+
+ @Override
+ public Class<String> getValueClass() {
+ return String.class; // matches Class<String>
+ }
+ };
+
+ @Test
+ public void testVendorKeys() {
+ final AudioMetadata.Map audioMetadata = AudioMetadata.createMap();
+
+ audioMetadata.set(KEY_VENDOR_INTEGER, 10);
+ final int ivalue = audioMetadata.get(KEY_VENDOR_INTEGER);
+ assertEquals(10, ivalue);
+
+ audioMetadata.set(KEY_VENDOR_DOUBLE, 11.5);
+ final double dvalue = audioMetadata.get(KEY_VENDOR_DOUBLE);
+ assertEquals(11.5, dvalue, 0. /* epsilon */);
+
+ audioMetadata.set(KEY_VENDOR_STRING, "alphabet");
+ final String svalue = audioMetadata.get(KEY_VENDOR_STRING);
+ assertEquals("alphabet", svalue);
+ }
+
// The byte buffer here is generated by audio_utils::metadata::byteStringFromData(Data).
// Data data = {
// "integer": (int32_t) 1,
diff --git a/tests/tests/media/src/android/media/cts/DecoderTest.java b/tests/tests/media/src/android/media/cts/DecoderTest.java
index 05f7f37..f270d33 100644
--- a/tests/tests/media/src/android/media/cts/DecoderTest.java
+++ b/tests/tests/media/src/android/media/cts/DecoderTest.java
@@ -1123,8 +1123,7 @@
@Override
public void onError(MediaCodec codec, MediaCodec.CodecException e) {
- Log.i(TAG, "got codec exception", e);
- fail("received codec error during decode" + e);
+ Log.e(TAG, "got codec exception", e);
}
@Override
diff --git a/tests/tests/media/src/android/media/cts/MediaPlayerTest.java b/tests/tests/media/src/android/media/cts/MediaPlayerTest.java
index 3e547bb..57cb6e0 100644
--- a/tests/tests/media/src/android/media/cts/MediaPlayerTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaPlayerTest.java
@@ -403,8 +403,13 @@
}
public void testPlayMidi() throws Exception {
- final int resid = R.raw.midi8sec;
- final int midiDuration = 8000;
+ runMidiTest(R.raw.midi8sec, 8000 /* duration */);
+ runMidiTest(R.raw.testrtttl, 30000 /* duration */);
+ runMidiTest(R.raw.testimy, 5125 /* duration */);
+ runMidiTest(R.raw.testota, 5906 /* duration */);
+ }
+
+ private void runMidiTest(int resid, int midiDuration) throws Exception {
final int tolerance = 70;
final int seekDuration = 1000;
diff --git a/tests/tests/media/src/android/media/cts/VideoEncoderTest.java b/tests/tests/media/src/android/media/cts/VideoEncoderTest.java
index 73fc811..b135f89 100644
--- a/tests/tests/media/src/android/media/cts/VideoEncoderTest.java
+++ b/tests/tests/media/src/android/media/cts/VideoEncoderTest.java
@@ -50,6 +50,7 @@
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
+import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.HashMap;
@@ -81,6 +82,7 @@
private int mMediaBuffersEnqueuedCount;
// Media buffers decoded.
private int mMediaBuffersDecodedCount;
+ private final AtomicReference<String> errorMsg = new AtomicReference(null);
public VideoStorage() {
mStream = new LinkedList<Pair<ByteBuffer, BufferInfo>>();
@@ -141,7 +143,10 @@
}
public void onError(MediaCodec codec, MediaCodec.CodecException e) {
Log.i(TAG, "got codec exception", e);
- fail("received codec error during decode" + e);
+ errorMsg.set("received codec error during decode" + e);
+ synchronized (condition) {
+ condition.notifyAll();
+ }
}
public void onOutputFormatChanged(MediaCodec codec, MediaFormat format) {
Log.i(TAG, "got output format " + format);
@@ -158,6 +163,7 @@
}
}
decoder.stop();
+ assertNull(errorMsg.get(), errorMsg.get());
// All enqueued media data buffers should have got decoded.
if (mMediaBuffersEnqueuedCount != mMediaBuffersDecodedCount) {
Log.i(TAG, "mMediaBuffersEnqueuedCount:" + mMediaBuffersEnqueuedCount);
@@ -473,6 +479,7 @@
private LinkedList<Integer> mEncInputBuffers = new LinkedList<Integer>();
private int mEncInputBufferSize = -1;
+ private final AtomicReference<String> errorMsg = new AtomicReference(null);
@Override
public boolean processLoop(
@@ -495,7 +502,7 @@
mEncoder.start();
// main loop - process GL ops as only main thread has GL context
- while (!mCompleted) {
+ while (!mCompleted && errorMsg.get() == null) {
Pair<Integer, BufferInfo> decBuffer = null;
int encBuffer = -1;
synchronized (mCondition) {
@@ -546,6 +553,7 @@
} finally {
close();
}
+ assertNull(errorMsg.get(), errorMsg.get());
return !skipped;
}
@@ -635,7 +643,13 @@
@Override
public void onError(MediaCodec mediaCodec, MediaCodec.CodecException e) {
- fail("received error on " + mediaCodec.getName() + ": " + e);
+ String codecName = null;
+ try {
+ codecName = mediaCodec.getName();
+ } catch (Exception ex) {
+ codecName = "(error getting codec name)";
+ }
+ errorMsg.set("received error on " + codecName + ": " + e);
}
@Override
@@ -690,6 +704,8 @@
private LinkedList<Pair<Integer, BufferInfo>> mBuffersToRender =
new LinkedList<Pair<Integer, BufferInfo>>();
+ private final AtomicReference<String> errorMsg = new AtomicReference(null);
+
@Override
public boolean processLoop(
String path, String outMime, String videoEncName,
@@ -716,7 +732,7 @@
mEncoder.start();
// main loop - process GL ops as only main thread has GL context
- while (!mCompleted) {
+ while (!mCompleted && errorMsg.get() == null) {
BufferInfo info = null;
synchronized (mCondition) {
try {
@@ -784,6 +800,7 @@
mDecSurface = null;
}
}
+ assertNull(errorMsg.get(), errorMsg.get());
return !skipped;
}
@@ -867,7 +884,13 @@
@Override
public void onError(MediaCodec mediaCodec, MediaCodec.CodecException e) {
- fail("received error on " + mediaCodec.getName() + ": " + e);
+ String codecName = null;
+ try {
+ codecName = mediaCodec.getName();
+ } catch (Exception ex) {
+ codecName = "(error getting codec name)";
+ }
+ errorMsg.set("received error on " + codecName + ": " + e);
}
@Override
diff --git a/tests/tests/net/ipsec/OWNERS b/tests/tests/net/ipsec/OWNERS
new file mode 100644
index 0000000..26407ff
--- /dev/null
+++ b/tests/tests/net/ipsec/OWNERS
@@ -0,0 +1,3 @@
+lorenzo@google.com
+nharold@google.com
+satk@google.com
diff --git a/tests/tests/net/src/android/net/wifi/cts/WifiFeature.java b/tests/tests/net/src/android/net/wifi/cts/WifiFeature.java
index 63fa1dd..3e9fef4 100644
--- a/tests/tests/net/src/android/net/wifi/cts/WifiFeature.java
+++ b/tests/tests/net/src/android/net/wifi/cts/WifiFeature.java
@@ -20,12 +20,12 @@
import android.content.pm.PackageManager;
public class WifiFeature {
- static boolean isWifiSupported(Context context) {
+ public static boolean isWifiSupported(Context context) {
PackageManager packageManager = context.getPackageManager();
return packageManager.hasSystemFeature(PackageManager.FEATURE_WIFI);
}
- static boolean isP2pSupported(Context context) {
+ public static boolean isP2pSupported(Context context) {
PackageManager packageManager = context.getPackageManager();
return packageManager.hasSystemFeature(PackageManager.FEATURE_WIFI_DIRECT);
}
diff --git a/tests/tests/net/src/android/net/wifi/cts/WifiHotspot2Test.java b/tests/tests/net/src/android/net/wifi/cts/WifiHotspot2Test.java
new file mode 100644
index 0000000..a05b81b
--- /dev/null
+++ b/tests/tests/net/src/android/net/wifi/cts/WifiHotspot2Test.java
@@ -0,0 +1,488 @@
+/*
+ * Copyright (C) 2020 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.net.wifi.cts;
+
+import static android.net.wifi.WifiConfiguration.METERED_OVERRIDE_NONE;
+
+import android.net.Uri;
+import android.net.wifi.hotspot2.OsuProvider;
+import android.net.wifi.hotspot2.PasspointConfiguration;
+import android.net.wifi.hotspot2.pps.Credential;
+import android.net.wifi.hotspot2.pps.HomeSp;
+import android.test.AndroidTestCase;
+import android.text.TextUtils;
+
+import java.lang.reflect.Constructor;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.X509Certificate;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+public class WifiHotspot2Test extends AndroidTestCase {
+ static final int SIM_CREDENTIAL = 0;
+ static final int USER_CREDENTIAL = 1;
+ static final int CERT_CREDENTIAL = 2;
+ private static final String TEST_SSID = "TEST SSID";
+ private static final String TEST_FRIENDLY_NAME = "Friendly Name";
+ private static final Map<String, String> TEST_FRIENDLY_NAMES =
+ new HashMap<String, String>() {
+ {
+ put("en", TEST_FRIENDLY_NAME);
+ put("kr", TEST_FRIENDLY_NAME + 2);
+ put("jp", TEST_FRIENDLY_NAME + 3);
+ }
+ };
+ private static final String TEST_SERVICE_DESCRIPTION = "Dummy Service";
+ private static final Uri TEST_SERVER_URI = Uri.parse("https://test.com");
+ private static final String TEST_NAI = "test.access.com";
+ private static final List<Integer> TEST_METHOD_LIST =
+ Arrays.asList(1 /* METHOD_SOAP_XML_SPP */);
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ return;
+ }
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ /**
+ * Tests {@link PasspointConfiguration#getMeteredOverride()} method.
+ * <p>
+ * Test default value
+ */
+ public void testGetMeteredOverride() throws Exception {
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ return;
+ }
+ PasspointConfiguration passpointConfiguration = new PasspointConfiguration();
+ assertEquals(METERED_OVERRIDE_NONE, passpointConfiguration.getMeteredOverride());
+ }
+
+ /**
+ * Tests {@link PasspointConfiguration#getSubscriptionExpirationTimeMillis()} method.
+ * <p>
+ * Test default value
+ */
+ public void testGetSubscriptionExpirationTimeMillis() throws Exception {
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ return;
+ }
+ PasspointConfiguration passpointConfiguration = new PasspointConfiguration();
+ assertEquals(Long.MIN_VALUE,
+ passpointConfiguration.getSubscriptionExpirationTimeMillis());
+ }
+
+ /**
+ * Tests {@link PasspointConfiguration#getUniqueId()} method.
+ * <p>
+ * Test unique identifier is not null
+ */
+ public void testGetUniqueId() throws Exception {
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ return;
+ }
+
+ // Create a configuration and make sure the unique ID is not null
+ PasspointConfiguration passpointConfiguration1 = createConfig(SIM_CREDENTIAL, "123456*",
+ 18 /* EAP_SIM */);
+ String uniqueId1 = passpointConfiguration1.getUniqueId();
+ assertNotNull(uniqueId1);
+
+ // Create another configuration and make sure the unique ID is not null
+ PasspointConfiguration passpointConfiguration2 = createConfig(SIM_CREDENTIAL, "567890*",
+ 23 /* EAP_AKA */);
+ String uniqueId2 = passpointConfiguration2.getUniqueId();
+ assertNotNull(uniqueId2);
+
+ // Make sure the IDs are not equal
+ assertFalse(uniqueId1.equals(uniqueId2));
+
+ passpointConfiguration2 = createConfig(USER_CREDENTIAL);
+ assertFalse(uniqueId1.equals(passpointConfiguration2.getUniqueId()));
+
+ passpointConfiguration2 = createConfig(CERT_CREDENTIAL);
+ assertFalse(uniqueId1.equals(passpointConfiguration2.getUniqueId()));
+ }
+
+ /**
+ * Tests {@link PasspointConfiguration#isAutojoinEnabled()} method.
+ * <p>
+ * Test default value
+ */
+ public void testIsAutojoinEnabled() throws Exception {
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ return;
+ }
+ PasspointConfiguration passpointConfiguration = new PasspointConfiguration();
+ assertTrue(passpointConfiguration.isAutojoinEnabled());
+ }
+
+ /**
+ * Tests {@link PasspointConfiguration#isMacRandomizationEnabled()} method.
+ * <p>
+ * Test default value
+ */
+ public void testIsMacRandomizationEnabled() throws Exception {
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ return;
+ }
+ PasspointConfiguration passpointConfiguration = new PasspointConfiguration();
+ assertTrue(passpointConfiguration.isMacRandomizationEnabled());
+ }
+
+ /**
+ * Tests {@link PasspointConfiguration#isOsuProvisioned()} method.
+ * <p>
+ * Test default value
+ */
+ public void testIsOsuProvisioned() throws Exception {
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ return;
+ }
+ PasspointConfiguration passpointConfiguration = createConfig(USER_CREDENTIAL);
+ assertFalse(passpointConfiguration.isOsuProvisioned());
+ }
+
+ /**
+ * Tests {@link PasspointConfiguration#PasspointConfiguration(PasspointConfiguration)} method.
+ * <p>
+ * Test the PasspointConfiguration copy constructor
+ */
+ public void testPasspointConfigurationCopyConstructor() throws Exception {
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ return;
+ }
+ PasspointConfiguration passpointConfiguration = createConfig(USER_CREDENTIAL);
+ PasspointConfiguration copyOfPasspointConfiguration =
+ new PasspointConfiguration(passpointConfiguration);
+ assertEquals(passpointConfiguration, copyOfPasspointConfiguration);
+ }
+
+ /**
+ * Tests {@link HomeSp#HomeSp(HomeSp)} method.
+ * <p>
+ * Test the HomeSp copy constructor
+ */
+ public void testHomeSpCopyConstructor() throws Exception {
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ return;
+ }
+ HomeSp homeSp = createHomeSp();
+ HomeSp copyOfHomeSp = new HomeSp(homeSp);
+ assertEquals(copyOfHomeSp, homeSp);
+ }
+
+ /**
+ * Tests {@link Credential#Credential(Credential)} method.
+ * <p>
+ * Test the Credential copy constructor
+ */
+ public void testCredentialCopyConstructor() throws Exception {
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ return;
+ }
+ Credential credential = createCredentialWithSimCredential("123456*", 18 /* EAP_SIM */);
+ Credential copyOfCredential = new Credential(credential);
+ assertEquals(copyOfCredential, credential);
+ }
+
+ /**
+ * Tests {@link Credential.UserCredential#UserCredential(Credential.UserCredential)} method.
+ * <p>
+ * Test the Credential.UserCredential copy constructor
+ */
+ public void testUserCredentialCopyConstructor() throws Exception {
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ return;
+ }
+ Credential.UserCredential userCredential = new Credential.UserCredential();
+ userCredential.setUsername("username");
+ userCredential.setPassword("password");
+ userCredential.setEapType(21 /* EAP_TTLS */);
+ userCredential.setNonEapInnerMethod("MS-CHAP");
+
+ Credential.UserCredential copyOfUserCredential =
+ new Credential.UserCredential(userCredential);
+ assertEquals(copyOfUserCredential, userCredential);
+ }
+
+ /**
+ * Tests
+ * {@link Credential.CertificateCredential#CertificateCredential(Credential.CertificateCredential)}
+ * method.
+ * <p>
+ * Test the Credential.CertificateCredential copy constructor
+ */
+ public void testCertCredentialCopyConstructor() throws Exception {
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ return;
+ }
+ Credential.CertificateCredential certCredential = new Credential.CertificateCredential();
+ certCredential.setCertType("x509v3");
+
+ Credential.CertificateCredential copyOfCertificateCredential =
+ new Credential.CertificateCredential(certCredential);
+ assertEquals(copyOfCertificateCredential, certCredential);
+ }
+
+ /**
+ * Tests {@link Credential.SimCredential#SimCredential(Credential.SimCredential)} method.
+ * <p>
+ * Test the Credential.SimCredential copy constructor
+ */
+ public void testSimCredentialCopyConstructor() throws Exception {
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ return;
+ }
+ Credential.SimCredential simCredential = new Credential.SimCredential();
+ simCredential.setImsi("1234*");
+ simCredential.setEapType(18/* EAP_SIM */);
+
+ Credential.SimCredential copyOfSimCredential = new Credential.SimCredential(simCredential);
+ assertEquals(copyOfSimCredential, simCredential);
+ }
+
+ /**
+ * Tests {@link Credential#getCaCertificate()} method.
+ * <p>
+ * Test that getting a set certificate produces the same value
+ */
+ public void testCredentialGetCertificate() throws Exception {
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ return;
+ }
+ Credential credential = new Credential();
+ credential.setCaCertificate(FakeKeys.CA_CERT0);
+
+ assertEquals(FakeKeys.CA_CERT0, credential.getCaCertificate());
+ }
+
+ /**
+ * Tests {@link Credential#getClientCertificateChain()} and {@link
+ * Credential#setCaCertificates(X509Certificate[])} methods.
+ * <p>
+ * Test that getting a set client certificate chain produces the same value
+ */
+ public void testCredentialClientCertificateChain() throws Exception {
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ return;
+ }
+ Credential credential = new Credential();
+ X509Certificate[] certificates = new X509Certificate[]{FakeKeys.CLIENT_CERT};
+ credential.setClientCertificateChain(certificates);
+
+ assertTrue(Arrays.equals(certificates, credential.getClientCertificateChain()));
+ }
+
+ /**
+ * Tests {@link Credential#getClientPrivateKey()} and
+ * {@link Credential#setClientPrivateKey(PrivateKey)}
+ * methods.
+ * <p>
+ * Test that getting a set client private key produces the same value
+ */
+ public void testCredentialSetGetClientPrivateKey() throws Exception {
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ return;
+ }
+ Credential credential = new Credential();
+ credential.setClientPrivateKey(FakeKeys.RSA_KEY1);
+
+ assertEquals(FakeKeys.RSA_KEY1, credential.getClientPrivateKey());
+ }
+
+ /**
+ * Tests {@link Credential#getClientPrivateKey()} and
+ * {@link Credential#setClientPrivateKey(PrivateKey)}
+ * methods.
+ * <p>
+ * Test that getting a set client private key produces the same value
+ */
+ public void testCredentialGetClientPrivateKey() throws Exception {
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ return;
+ }
+ Credential credential = new Credential();
+ credential.setClientPrivateKey(FakeKeys.RSA_KEY1);
+
+ assertEquals(FakeKeys.RSA_KEY1, credential.getClientPrivateKey());
+ }
+
+ private static PasspointConfiguration createConfig(int type) throws Exception {
+ return createConfig(type, "123456*", 18 /* EAP_SIM */);
+ }
+
+ private static PasspointConfiguration createConfig(int type, String imsi, int eapType)
+ throws Exception {
+ PasspointConfiguration config = new PasspointConfiguration();
+ config.setHomeSp(createHomeSp());
+ switch (type) {
+ default:
+ case SIM_CREDENTIAL:
+ config.setCredential(
+ createCredentialWithSimCredential(imsi, eapType));
+ break;
+ case USER_CREDENTIAL:
+ config.setCredential(createCredentialWithUserCredential());
+ break;
+ case CERT_CREDENTIAL:
+ config.setCredential(createCredentialWithCertificateCredential());
+ break;
+ }
+
+ return config;
+ }
+
+ /**
+ * Helper function for generating HomeSp for testing.
+ *
+ * @return {@link HomeSp}
+ */
+ private static HomeSp createHomeSp() {
+ HomeSp homeSp = new HomeSp();
+ homeSp.setFqdn("test.com");
+ homeSp.setFriendlyName("friendly name");
+ homeSp.setRoamingConsortiumOis(new long[]{0x55, 0x66});
+ return homeSp;
+ }
+
+ /**
+ * Helper function for generating Credential for testing.
+ *
+ * @param userCred Instance of UserCredential
+ * @param certCred Instance of CertificateCredential
+ * @param simCred Instance of SimCredential
+ * @param clientCertificateChain Chain of client certificates
+ * @param clientPrivateKey Client private key
+ * @param caCerts CA certificates
+ * @return {@link Credential}
+ */
+ private static Credential createCredential(Credential.UserCredential userCred,
+ Credential.CertificateCredential certCred,
+ Credential.SimCredential simCred,
+ X509Certificate[] clientCertificateChain, PrivateKey clientPrivateKey,
+ X509Certificate... caCerts) {
+ Credential cred = new Credential();
+ cred.setRealm("realm");
+ cred.setUserCredential(userCred);
+ cred.setCertCredential(certCred);
+ cred.setSimCredential(simCred);
+ return cred;
+ }
+
+ /**
+ * Helper function for generating certificate credential for testing.
+ *
+ * @return {@link Credential}
+ */
+ private static Credential createCredentialWithCertificateCredential()
+ throws NoSuchAlgorithmException, CertificateEncodingException {
+ Credential.CertificateCredential certCred = new Credential.CertificateCredential();
+ certCred.setCertType("x509v3");
+ certCred.setCertSha256Fingerprint(
+ MessageDigest.getInstance("SHA-256").digest(
+ FakeKeys.CLIENT_CERT.getEncoded()));
+ return createCredential(null, certCred, null, new X509Certificate[]{
+ FakeKeys.CLIENT_CERT},
+ FakeKeys.RSA_KEY1, FakeKeys.CA_CERT0,
+ FakeKeys.CA_CERT1);
+ }
+
+ /**
+ * Helper function for generating SIM credential for testing.
+ *
+ * @return {@link Credential}
+ */
+ private static Credential createCredentialWithSimCredential(String imsi, int eapType) {
+ Credential.SimCredential simCred = new Credential.SimCredential();
+ simCred.setImsi(imsi);
+ simCred.setEapType(eapType);
+ return createCredential(null, null, simCred, null, null, (X509Certificate[]) null);
+ }
+
+ /**
+ * Helper function for generating user credential for testing.
+ *
+ * @return {@link Credential}
+ */
+ private static Credential createCredentialWithUserCredential() {
+ Credential.UserCredential userCred = new Credential.UserCredential();
+ userCred.setUsername("username");
+ userCred.setPassword("password");
+ userCred.setEapType(21 /* EAP_TTLS */);
+ userCred.setNonEapInnerMethod("MS-CHAP");
+ return createCredential(userCred, null, null, null, null,
+ FakeKeys.CA_CERT0);
+ }
+
+ /**
+ * Tests {@link OsuProvider#getFriendlyName()} and {@link OsuProvider#getServerUri()} methods.
+ * <p>
+ * Test that getting a set friendly name and server URI produces the same value
+ */
+ public void testOsuProviderGetters() throws Exception {
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ return;
+ }
+
+ // Using Java reflection to construct an OsuProvider instance because its constructor is
+ // hidden and not available to apps.
+ Class<?> osuProviderClass = Class.forName("android.net.wifi.hotspot2.OsuProvider");
+ Constructor<?> osuProviderClassConstructor = osuProviderClass.getConstructor(String.class,
+ Map.class, String.class, Uri.class, String.class, List.class);
+
+ OsuProvider osuProvider = (OsuProvider) osuProviderClassConstructor.newInstance(TEST_SSID,
+ TEST_FRIENDLY_NAMES, TEST_SERVICE_DESCRIPTION, TEST_SERVER_URI, TEST_NAI,
+ TEST_METHOD_LIST);
+ String lang = Locale.getDefault().getLanguage();
+ String friendlyName = TEST_FRIENDLY_NAMES.get(lang);
+ if (TextUtils.isEmpty(friendlyName)) {
+ friendlyName = TEST_FRIENDLY_NAMES.get("en");
+ }
+ assertEquals(friendlyName, osuProvider.getFriendlyName());
+ assertEquals(TEST_SERVER_URI, osuProvider.getServerUri());
+ }
+}
diff --git a/tests/tests/net/src/android/net/wifi/cts/WifiManagerTest.java b/tests/tests/net/src/android/net/wifi/cts/WifiManagerTest.java
index f4c20e3..ae5ef75 100644
--- a/tests/tests/net/src/android/net/wifi/cts/WifiManagerTest.java
+++ b/tests/tests/net/src/android/net/wifi/cts/WifiManagerTest.java
@@ -32,7 +32,6 @@
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
-import android.net.util.MacAddressUtils;
import android.net.ConnectivityManager;
import android.net.LinkProperties;
import android.net.MacAddress;
@@ -40,15 +39,28 @@
import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
import android.net.NetworkRequest;
+import android.net.TetheringManager;
+import android.net.Uri;
+import android.net.util.MacAddressUtils;
import android.net.wifi.ScanResult;
+import android.net.wifi.SoftApCapability;
import android.net.wifi.SoftApConfiguration;
+import android.net.wifi.SoftApInfo;
+import android.net.wifi.WifiClient;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiManager.WifiLock;
import android.net.wifi.WifiNetworkConnectionStatistics;
import android.net.wifi.hotspot2.ConfigParser;
+import android.net.wifi.hotspot2.OsuProvider;
import android.net.wifi.hotspot2.PasspointConfiguration;
+import android.net.wifi.hotspot2.ProvisioningCallback;
+import android.net.wifi.hotspot2.pps.Credential;
+import android.net.wifi.hotspot2.pps.HomeSp;
+import android.os.Handler;
+import android.os.HandlerExecutor;
+import android.os.HandlerThread;
import android.os.Process;
import android.os.SystemClock;
import android.os.UserHandle;
@@ -66,16 +78,24 @@
import com.android.compatibility.common.util.PollingCheck;
import com.android.compatibility.common.util.ShellIdentityUtils;
import com.android.compatibility.common.util.SystemUtil;
+import com.android.compatibility.common.util.ThrowingRunnable;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
+import java.lang.reflect.Constructor;
import java.net.HttpURLConnection;
import java.net.URL;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Locale;
+import java.util.Map;
import java.util.Objects;
+import java.util.Set;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
@@ -90,6 +110,7 @@
private WifiManager mWifiManager;
private ConnectivityManager mConnectivityManager;
+ private TetheringManager mTetheringManager;
private WifiLock mWifiLock;
private static MySync mMySync;
private List<ScanResult> mScanResults = null;
@@ -97,6 +118,7 @@
private final Object mLock = new Object();
private UiDevice mUiDevice;
private boolean mWasVerboseLoggingEnabled;
+ private SoftApConfiguration mOriginalSoftApConfig = null;
// Please refer to WifiManager
private static final int MIN_RSSI = -100;
@@ -117,7 +139,7 @@
private static final int SCAN_TIMEOUT_MSEC = 9000;
private static final int TIMEOUT_MSEC = 6000;
private static final int WAIT_MSEC = 60;
- private static final int DURATION = 10_000;
+ private static final int TEST_WAIT_DURATION_MS = 10_000;
private static final int DURATION_SCREEN_TOGGLE = 2000;
private static final int DURATION_SETTINGS_TOGGLE = 1_000;
private static final int WIFI_SCAN_TEST_INTERVAL_MILLIS = 60 * 1000;
@@ -177,6 +199,54 @@
}
}
};
+ // Initialize with an invalid status value (0)
+ private int mProvisioningStatus = 0;
+ // Initialize with an invalid status value (0)
+ private int mProvisioningFailureStatus = 0;
+ private boolean mProvisioningComplete = false;
+ private ProvisioningCallback mProvisioningCallback = new ProvisioningCallback() {
+ @Override
+ public void onProvisioningFailure(int status) {
+ synchronized (mLock) {
+ mProvisioningFailureStatus = status;
+ mLock.notify();
+ }
+ }
+
+ @Override
+ public void onProvisioningStatus(int status) {
+ synchronized (mLock) {
+ mProvisioningStatus = status;
+ mLock.notify();
+ }
+ }
+
+ @Override
+ public void onProvisioningComplete() {
+ mProvisioningComplete = true;
+ }
+ };
+ private static final String TEST_SSID = "TEST SSID";
+ private static final String TEST_FRIENDLY_NAME = "Friendly Name";
+ private static final Map<String, String> TEST_FRIENDLY_NAMES =
+ new HashMap<String, String>() {
+ {
+ put("en", TEST_FRIENDLY_NAME);
+ put("kr", TEST_FRIENDLY_NAME + 2);
+ put("jp", TEST_FRIENDLY_NAME + 3);
+ }
+ };
+ private static final String TEST_SERVICE_DESCRIPTION = "Dummy Service";
+ private static final Uri TEST_SERVER_URI = Uri.parse("https://test.com");
+ private static final String TEST_NAI = "test.access.com";
+ private static final List<Integer> TEST_METHOD_LIST =
+ Arrays.asList(1 /* METHOD_SOAP_XML_SPP */);
+ private final HandlerThread mHandlerThread = new HandlerThread("WifiManagerTest");
+ protected final Executor mExecutor;
+ {
+ mHandlerThread.start();
+ mExecutor = new HandlerExecutor(new Handler(mHandlerThread.getLooper()));
+ }
@Override
protected void setUp() throws Exception {
@@ -199,7 +269,9 @@
mContext.registerReceiver(mReceiver, mIntentFilter);
mWifiManager = (WifiManager) getContext().getSystemService(Context.WIFI_SERVICE);
mConnectivityManager = getContext().getSystemService(ConnectivityManager.class);
+ mTetheringManager = getContext().getSystemService(TetheringManager.class);
assertNotNull(mWifiManager);
+ assertNotNull(mTetheringManager);
// turn on verbose logging for tests
mWasVerboseLoggingEnabled = ShellIdentityUtils.invokeWithShellPermissions(
@@ -213,7 +285,7 @@
setWifiEnabled(true);
mUiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
turnScreenOnNoDelay();
- Thread.sleep(DURATION);
+ Thread.sleep(TEST_WAIT_DURATION_MS);
assertTrue(mWifiManager.isWifiEnabled());
synchronized (mMySync) {
mMySync.expectedState = STATE_NULL;
@@ -222,6 +294,10 @@
List<WifiConfiguration> savedNetworks = ShellIdentityUtils.invokeWithShellPermissions(
mWifiManager::getConfiguredNetworks);
assertFalse("Need at least one saved network", savedNetworks.isEmpty());
+
+ // Get original config for restore
+ mOriginalSoftApConfig = ShellIdentityUtils.invokeWithShellPermissions(
+ mWifiManager::getSoftApConfiguration);
}
@Override
@@ -237,7 +313,10 @@
mContext.unregisterReceiver(mReceiver);
ShellIdentityUtils.invokeWithShellPermissions(
() -> mWifiManager.setVerboseLoggingEnabled(mWasVerboseLoggingEnabled));
- Thread.sleep(DURATION);
+ // restore original softap config
+ ShellIdentityUtils.invokeWithShellPermissions(
+ () -> mWifiManager.setSoftApConfiguration(mOriginalSoftApConfig));
+ Thread.sleep(TEST_WAIT_DURATION_MS);
super.tearDown();
}
@@ -355,7 +434,7 @@
+ " empty when location is disabled!");
}
setWifiEnabled(false);
- Thread.sleep(DURATION);
+ Thread.sleep(TEST_WAIT_DURATION_MS);
startScan();
if (mWifiManager.isScanAlwaysAvailable() && isScanCurrentlyAvailable()) {
// Make sure at least one AP is found.
@@ -506,6 +585,140 @@
}
}
+ public class TestSoftApCallback implements WifiManager.SoftApCallback {
+ Object softApLock;
+ int currentState;
+ int currentFailureReason;
+ List<WifiClient> currentClientList;
+ SoftApInfo currentSoftApInfo;
+ SoftApCapability currentSoftApCapability;
+ MacAddress lastBlockedClientMacAddress;
+ int lastBlockedClientReason;
+ boolean onStateChangedCalled = false;
+ boolean onSoftapInfoChangedCalled = false;
+ boolean onSoftApCapabilityChangedCalled = false;
+ boolean onConnectedClientCalled = false;
+ boolean onBlockedClientConnectingCalled = false;
+
+ TestSoftApCallback(Object lock) {
+ softApLock = lock;
+ }
+
+ public boolean getOnStateChangedCalled() {
+ synchronized(softApLock) {
+ return onStateChangedCalled;
+ }
+ }
+
+ public boolean getOnSoftapInfoChangedCalled() {
+ synchronized(softApLock) {
+ return onSoftapInfoChangedCalled;
+ }
+ }
+
+ public boolean getOnSoftApCapabilityChangedCalled() {
+ synchronized(softApLock) {
+ return onSoftApCapabilityChangedCalled;
+ }
+ }
+
+ public boolean getOnConnectedClientCalled() {
+ synchronized(softApLock) {
+ return onConnectedClientCalled;
+ }
+ }
+
+ public boolean getOnBlockedClientConnectingCalled() {
+ synchronized(softApLock) {
+ return onBlockedClientConnectingCalled;
+ }
+ }
+
+ public int getCurrentState() {
+ synchronized(softApLock) {
+ return currentState;
+ }
+ }
+
+ public int getCurrentStateFailureReason() {
+ synchronized(softApLock) {
+ return currentFailureReason;
+ }
+ }
+
+ public List<WifiClient> getCurrentClientList() {
+ synchronized(softApLock) {
+ return currentClientList;
+ }
+ }
+
+ public SoftApInfo getCurrentSoftApInfo() {
+ synchronized(softApLock) {
+ return currentSoftApInfo;
+ }
+ }
+
+ public SoftApCapability getCurrentSoftApCapability() {
+ synchronized(softApLock) {
+ return currentSoftApCapability;
+ }
+ }
+
+ public MacAddress getLastBlockedClientMacAddress() {
+ synchronized(softApLock) {
+ return lastBlockedClientMacAddress;
+ }
+ }
+
+ public int getLastBlockedClientReason() {
+ synchronized(softApLock) {
+ return lastBlockedClientReason;
+ }
+ }
+
+ @Override
+ public void onStateChanged(int state, int failureReason) {
+ synchronized(softApLock) {
+ currentState = state;
+ currentFailureReason = failureReason;
+ onStateChangedCalled = true;
+ }
+ }
+
+ @Override
+ public void onConnectedClientsChanged(List<WifiClient> clients) {
+ synchronized(softApLock) {
+ currentClientList = new ArrayList<>(clients);
+ onConnectedClientCalled = true;
+ }
+ }
+
+ @Override
+ public void onInfoChanged(SoftApInfo softApInfo) {
+ synchronized(softApLock) {
+ currentSoftApInfo = softApInfo;
+ onSoftapInfoChangedCalled = true;
+ }
+ }
+
+ @Override
+ public void onCapabilityChanged(SoftApCapability softApCapability) {
+ synchronized(softApLock) {
+ currentSoftApCapability = softApCapability;
+ onSoftApCapabilityChangedCalled = true;
+ }
+ }
+
+ @Override
+ public void onBlockedClientConnecting(WifiClient client, int blockedReason) {
+ synchronized(softApLock) {
+ lastBlockedClientMacAddress = client.getMacAddress();
+ lastBlockedClientReason = blockedReason;
+ onBlockedClientConnectingCalled = true;
+ }
+ }
+ }
+
private static class TestLocalOnlyHotspotCallback extends WifiManager.LocalOnlyHotspotCallback {
Object hotspotLock;
WifiManager.LocalOnlyHotspotReservation reservation = null;
@@ -556,12 +769,15 @@
try {
mWifiManager.startLocalOnlyHotspot(callback, null);
// now wait for callback
- mLock.wait(DURATION);
+ mLock.wait(TEST_WAIT_DURATION_MS);
} catch (InterruptedException e) {
}
// check if we got the callback
assertTrue(callback.onStartedCalled);
- assertNotNull(callback.reservation.getSoftApConfiguration());
+
+ SoftApConfiguration softApConfig = callback.reservation.getSoftApConfiguration();
+ assertNotNull(softApConfig);
+ assertNotNull(softApConfig.toWifiConfiguration());
if (!hasAutomotiveFeature()) {
assertEquals(
SoftApConfiguration.BAND_2GHZ,
@@ -647,7 +863,7 @@
boolean wifiEnabled = mWifiManager.isWifiEnabled();
// now we should fail to toggle wifi state.
assertFalse(mWifiManager.setWifiEnabled(!wifiEnabled));
- Thread.sleep(DURATION);
+ Thread.sleep(TEST_WAIT_DURATION_MS);
assertEquals(wifiEnabled, mWifiManager.isWifiEnabled());
}
@@ -1055,8 +1271,12 @@
Thread.sleep(DURATION_SCREEN_TOGGLE);
}
- private void turnScreenOff() throws Exception {
+ private void turnScreenOffNoDelay() throws Exception {
mUiDevice.executeShellCommand("input keyevent KEYCODE_SLEEP");
+ }
+
+ private void turnScreenOff() throws Exception {
+ turnScreenOffNoDelay();
// Since the screen on/off intent is ordered, they will not be sent right now.
Thread.sleep(DURATION_SCREEN_TOGGLE);
}
@@ -1067,6 +1287,23 @@
}
}
+ private void runWithScanningEnabled(ThrowingRunnable r) throws Exception {
+ boolean wasScanEnabledForTest = false;
+ if (!mWifiManager.isScanAlwaysAvailable()) {
+ ShellIdentityUtils.invokeWithShellPermissions(
+ () -> mWifiManager.setScanAlwaysAvailable(true));
+ wasScanEnabledForTest = true;
+ }
+ try {
+ r.run();
+ } finally {
+ if (wasScanEnabledForTest) {
+ ShellIdentityUtils.invokeWithShellPermissions(
+ () -> mWifiManager.setScanAlwaysAvailable(false));
+ }
+ }
+ }
+
/**
* Verify that Wi-Fi scanning is not turned off when the screen turns off while wifi is disabled
* but location is on.
@@ -1085,17 +1322,16 @@
fail("Please enable location for this test - since Marshmallow WiFi scan results are"
+ " empty when location is disabled!");
}
- if(!mWifiManager.isScanAlwaysAvailable()) {
- fail("Please enable Wi-Fi scanning for this test!");
- }
- setWifiEnabled(false);
- turnScreenOn();
- assertWifiScanningIsOn();
- // Toggle screen and verify Wi-Fi scanning is still on.
- turnScreenOff();
- assertWifiScanningIsOn();
- turnScreenOn();
- assertWifiScanningIsOn();
+ runWithScanningEnabled(() -> {
+ setWifiEnabled(false);
+ turnScreenOn();
+ assertWifiScanningIsOn();
+ // Toggle screen and verify Wi-Fi scanning is still on.
+ turnScreenOff();
+ assertWifiScanningIsOn();
+ turnScreenOn();
+ assertWifiScanningIsOn();
+ });
}
/**
@@ -1115,17 +1351,16 @@
fail("Please enable location for this test - since Marshmallow WiFi scan results are"
+ " empty when location is disabled!");
}
- if(!mWifiManager.isScanAlwaysAvailable()) {
- fail("Please enable Wi-Fi scanning for this test!");
- }
- setWifiEnabled(true);
- turnScreenOn();
- assertWifiScanningIsOn();
- // Toggle screen and verify Wi-Fi scanning is still on.
- turnScreenOff();
- assertWifiScanningIsOn();
- turnScreenOn();
- assertWifiScanningIsOn();
+ runWithScanningEnabled(() -> {
+ setWifiEnabled(true);
+ turnScreenOn();
+ assertWifiScanningIsOn();
+ // Toggle screen and verify Wi-Fi scanning is still on.
+ turnScreenOff();
+ assertWifiScanningIsOn();
+ turnScreenOn();
+ assertWifiScanningIsOn();
+ });
}
/**
@@ -1141,6 +1376,178 @@
> ENFORCED_NUM_NETWORK_SUGGESTIONS_PER_APP);
}
+ private void verifyRegisterSoftApCallback(TestExecutor executor, TestSoftApCallback callback)
+ throws Exception{
+ // Register callback to get SoftApCapability
+ mWifiManager.registerSoftApCallback(executor, callback);
+ PollingCheck.check(
+ "SoftAp register failed!", 1_000,
+ () -> { executor.runAll();
+ // Verify callback is run on the supplied executor and called
+ return callback.getOnStateChangedCalled() &&
+ callback.getOnSoftapInfoChangedCalled() &&
+ callback.getOnSoftApCapabilityChangedCalled() &&
+ callback.getOnConnectedClientCalled();
+ });
+ }
+
+ private void verifySetGetSoftApConfig(SoftApConfiguration targetConfig) {
+ mWifiManager.setSoftApConfiguration(targetConfig);
+ // Bssid set dodesn't support for tethered hotspot
+ SoftApConfiguration currentConfig = mWifiManager.getSoftApConfiguration();
+ assertNull(currentConfig.getBssid());
+ compareSoftApConfiguration(targetConfig, currentConfig);
+ }
+
+ private void compareSoftApConfiguration(SoftApConfiguration currentConfig,
+ SoftApConfiguration testSoftApConfig) {
+ assertEquals(currentConfig.getSsid(), testSoftApConfig.getSsid());
+ assertEquals(currentConfig.getSecurityType(), testSoftApConfig.getSecurityType());
+ assertEquals(currentConfig.getPassphrase(), testSoftApConfig.getPassphrase());
+ assertEquals(currentConfig.isHiddenSsid(), testSoftApConfig.isHiddenSsid());
+ assertEquals(currentConfig.getBand(), testSoftApConfig.getBand());
+ assertEquals(currentConfig.getChannel(), testSoftApConfig.getChannel());
+ assertEquals(currentConfig.getMaxNumberOfClients(),
+ testSoftApConfig.getMaxNumberOfClients());
+ assertEquals(currentConfig.isAutoShutdownEnabled(),
+ testSoftApConfig.isAutoShutdownEnabled());
+ assertEquals(currentConfig.getShutdownTimeoutMillis(),
+ testSoftApConfig.getShutdownTimeoutMillis());
+ assertEquals(currentConfig.isClientControlByUserEnabled(),
+ testSoftApConfig.isClientControlByUserEnabled());
+ assertEquals(currentConfig.getAllowedClientList(),
+ testSoftApConfig.getAllowedClientList());
+ assertEquals(currentConfig.getBlockedClientList(),
+ testSoftApConfig.getBlockedClientList());
+ }
+
+ private void turnOffWifiAndTetheredHotspotIfEnabled() throws Exception {
+ if (mWifiManager.isWifiEnabled()) {
+ Log.d(TAG, "Turn off WiFi");
+ mWifiManager.setWifiEnabled(false);
+ PollingCheck.check(
+ "Wifi turn off failed!", 2_000,
+ () -> mWifiManager.isWifiEnabled() == false);
+ }
+ if (mWifiManager.isWifiApEnabled()) {
+ mTetheringManager.stopTethering(ConnectivityManager.TETHERING_WIFI);
+ Log.d(TAG, "Turn off tethered Hotspot");
+ PollingCheck.check(
+ "SoftAp turn off failed!", 2_000,
+ () -> mWifiManager.isWifiApEnabled() == false);
+ mTetheringManager.stopTethering(ConnectivityManager.TETHERING_WIFI);
+ }
+ }
+
+ /**
+ * Verify that the configuration from getSoftApConfiguration is same as the configuration which
+ * set by setSoftApConfiguration. And depends softap capability callback to test different
+ * configuration.
+ * @throws Exception
+ */
+ public void testSetGetSoftApConfigurationAndSoftApCapabilityCallback() throws Exception {
+ UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
+ try {
+ uiAutomation.adoptShellPermissionIdentity();
+ turnOffWifiAndTetheredHotspotIfEnabled();
+ TestExecutor executor = new TestExecutor();
+ TestSoftApCallback callback = new TestSoftApCallback(mLock);
+ verifyRegisterSoftApCallback(executor, callback);
+
+ SoftApConfiguration.Builder softApConfigBuilder = new SoftApConfiguration.Builder()
+ .setSsid(TEST_SSID_UNQUOTED)
+ .setBssid(TEST_MAC)
+ .setPassphrase(TEST_PASSPHRASE, SoftApConfiguration.SECURITY_TYPE_WPA2_PSK)
+ .setAutoShutdownEnabled(true)
+ .setShutdownTimeoutMillis(100000)
+ .setBand(SoftApConfiguration.BAND_2GHZ | SoftApConfiguration.BAND_5GHZ)
+ .setHiddenSsid(false);
+
+ // Test SoftApConfiguration set and get
+ verifySetGetSoftApConfig(softApConfigBuilder.build());
+
+ // Test CLIENT_FORCE_DISCONNECT supported config.
+ if (callback.getCurrentSoftApCapability()
+ .areFeaturesSupported(
+ SoftApCapability.SOFTAP_FEATURE_CLIENT_FORCE_DISCONNECT)) {
+ softApConfigBuilder.setMaxNumberOfClients(10);
+ softApConfigBuilder.setClientControlByUserEnabled(true);
+ softApConfigBuilder.setBlockedClientList(new ArrayList<>());
+ softApConfigBuilder.setAllowedClientList(new ArrayList<>());
+ verifySetGetSoftApConfig(softApConfigBuilder.build());
+ }
+
+ // Test SAE config
+ if (callback.getCurrentSoftApCapability()
+ .areFeaturesSupported(SoftApCapability.SOFTAP_FEATURE_WPA3_SAE)) {
+ softApConfigBuilder
+ .setPassphrase(TEST_PASSPHRASE,
+ SoftApConfiguration.SECURITY_TYPE_WPA3_SAE_TRANSITION);
+ verifySetGetSoftApConfig(softApConfigBuilder.build());
+ softApConfigBuilder
+ .setPassphrase(TEST_PASSPHRASE,
+ SoftApConfiguration.SECURITY_TYPE_WPA3_SAE);
+ verifySetGetSoftApConfig(softApConfigBuilder.build());
+ }
+ } finally {
+ uiAutomation.dropShellPermissionIdentity();
+ }
+ }
+
+ /**
+ * Verify that startTetheredHotspot with specific channel config.
+ * @throws Exception
+ */
+ public void testStartTetheredHotspotWithChannelConfigAndSoftApStateAndInfoCallback()
+ throws Exception {
+ UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
+ try {
+ uiAutomation.adoptShellPermissionIdentity();
+ turnOffWifiAndTetheredHotspotIfEnabled();
+ TestExecutor executor = new TestExecutor();
+ TestSoftApCallback callback = new TestSoftApCallback(mLock);
+ verifyRegisterSoftApCallback(executor, callback);
+
+ SoftApConfiguration testSoftApConfig = new SoftApConfiguration.Builder()
+ .setSsid(TEST_SSID_UNQUOTED)
+ .setPassphrase(TEST_PASSPHRASE, SoftApConfiguration.SECURITY_TYPE_WPA2_PSK)
+ .setChannel(11, SoftApConfiguration.BAND_2GHZ) // Channel 11 = Freq 2462
+ .build();
+
+ mWifiManager.setSoftApConfiguration(testSoftApConfig);
+
+ // start tethering which used to verify startTetheredHotspot
+ mTetheringManager.startTethering(ConnectivityManager.TETHERING_WIFI, executor,
+ new TetheringManager.StartTetheringCallback() {
+ @Override
+ public void onTetheringFailed(final int result) {
+ }
+ });
+
+ // Verify state and info callback value as expected
+ PollingCheck.check(
+ "SoftAp channel and state mismatch!!!", 5_000,
+ () -> { executor.runAll();
+ return WifiManager.WIFI_AP_STATE_ENABLED == callback.getCurrentState() &&
+ 2462 == callback.getCurrentSoftApInfo().getFrequency();
+ });
+
+ // stop tethering which used to verify stopSoftAp
+ mTetheringManager.stopTethering(ConnectivityManager.TETHERING_WIFI);
+
+ // Verify clean up
+ PollingCheck.check(
+ "Stop Softap failed", 2_000,
+ () -> { executor.runAll();
+ return WifiManager.WIFI_AP_STATE_DISABLED == callback.getCurrentState() &&
+ 0 == callback.getCurrentSoftApInfo().getBandwidth() &&
+ 0 == callback.getCurrentSoftApInfo().getFrequency();
+ });
+ } finally {
+ uiAutomation.dropShellPermissionIdentity();
+ }
+ }
+
private static class TestActionListener implements WifiManager.ActionListener {
private final Object mLock;
public boolean onSuccessCalled = false;
@@ -1203,7 +1610,7 @@
mWifiManager.connect(savedNetworks.get(0), actionListener);
}
// now wait for callback
- mLock.wait(DURATION);
+ mLock.wait(TEST_WAIT_DURATION_MS);
} catch (InterruptedException e) {
}
}
@@ -1282,7 +1689,7 @@
.build(),
networkCallbackListener);
// now wait for callback
- mLock.wait(DURATION);
+ mLock.wait(TEST_WAIT_DURATION_MS);
} catch (InterruptedException e) {
}
}
@@ -1330,7 +1737,7 @@
modSavedNetwork.meteredOverride = WifiConfiguration.METERED_OVERRIDE_METERED;
mWifiManager.save(modSavedNetwork, actionListener);
// now wait for callback
- mLock.wait(DURATION);
+ mLock.wait(TEST_WAIT_DURATION_MS);
} catch (InterruptedException e) {
}
}
@@ -1378,7 +1785,7 @@
try {
mWifiManager.forget(newNetworkId, actionListener);
// now wait for callback
- mLock.wait(DURATION);
+ mLock.wait(TEST_WAIT_DURATION_MS);
} catch (InterruptedException e) {
}
}
@@ -1455,13 +1862,107 @@
mWifiManager.isPreferredNetworkOffloadSupported();
}
+ /** Test that PNO scans reconnects us when the device is disconnected and the screen is off. */
+ public void testPnoScan() throws Exception {
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ return;
+ }
+ if (!mWifiManager.isPreferredNetworkOffloadSupported()) {
+ // skip the test if PNO scanning is not supported
+ return;
+ }
+
+ // make sure we're connected
+ waitForConnection();
+
+ WifiInfo currentNetwork = ShellIdentityUtils.invokeWithShellPermissions(
+ mWifiManager::getConnectionInfo);
+
+ // disable all networks that aren't already disabled
+ List<WifiConfiguration> savedNetworks = ShellIdentityUtils.invokeWithShellPermissions(
+ mWifiManager::getConfiguredNetworks);
+ Set<Integer> disabledNetworkIds = new HashSet<>();
+ for (WifiConfiguration config : savedNetworks) {
+ if (config.getNetworkSelectionStatus().getNetworkSelectionDisableReason()
+ == WifiConfiguration.NetworkSelectionStatus.DISABLED_NONE) {
+ ShellIdentityUtils.invokeWithShellPermissions(
+ () -> mWifiManager.disableNetwork(config.networkId));
+ disabledNetworkIds.add(config.networkId);
+ }
+ }
+
+ try {
+ // wait for disconnection from current network
+ waitForDisconnection();
+
+ // turn screen off
+ turnScreenOffNoDelay();
+
+ // re-enable the current network - this will trigger PNO
+ ShellIdentityUtils.invokeWithShellPermissions(
+ () -> mWifiManager.enableNetwork(currentNetwork.getNetworkId(), false));
+ disabledNetworkIds.remove(currentNetwork.getNetworkId());
+
+ // PNO should reconnect us back to the network we disconnected from
+ waitForConnection();
+ } finally {
+ // re-enable disabled networks
+ for (int disabledNetworkId : disabledNetworkIds) {
+ ShellIdentityUtils.invokeWithShellPermissions(
+ () -> mWifiManager.enableNetwork(disabledNetworkId, false));
+ }
+ }
+ }
+
+ /**
+ * Tests {@link WifiManager#isTdlsSupported()} does not crash.
+ */
+ public void testIsTdlsSupported() throws Exception {
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ return;
+ }
+ mWifiManager.isTdlsSupported();
+ }
+
+ /**
+ * Tests {@link WifiManager#isStaApConcurrencySupported().
+ */
+ public void testIsStaApConcurrencySupported() throws Exception {
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ return;
+ }
+ // check that softap mode is supported by the device
+ if (!mWifiManager.isPortableHotspotSupported()) {
+ return;
+ }
+ assertTrue(mWifiManager.isWifiEnabled());
+
+ boolean isStaApConcurrencySupported = mWifiManager.isStaApConcurrencySupported();
+ // start local only hotspot.
+ TestLocalOnlyHotspotCallback callback = startLocalOnlyHotspot();
+ if (isStaApConcurrencySupported) {
+ assertTrue(mWifiManager.isWifiEnabled());
+ } else {
+ // no concurrency, wifi should be disabled.
+ assertFalse(mWifiManager.isWifiEnabled());
+ }
+ stopLocalOnlyHotspot(callback, true);
+
+ assertTrue(mWifiManager.isWifiEnabled());
+ }
+
private static class TestTrafficStateCallback implements WifiManager.TrafficStateCallback {
private final Object mLock;
+ private final int mWaitForState;
public boolean onStateChangedCalled = false;
public int state = -1;
- TestTrafficStateCallback(Object lock) {
+ TestTrafficStateCallback(Object lock, int waitForState) {
mLock = lock;
+ mWaitForState = waitForState;
}
@Override
@@ -1469,7 +1970,9 @@
synchronized (mLock) {
onStateChangedCalled = true;
this.state = state;
- mLock.notify();
+ if (mWaitForState == state) { // only notify if we got the expected state.
+ mLock.notify();
+ }
}
}
}
@@ -1503,7 +2006,8 @@
// skip the test if WiFi is not supported
return;
}
- TestTrafficStateCallback trafficStateCallback = new TestTrafficStateCallback(mLock);
+ TestTrafficStateCallback trafficStateCallback =
+ new TestTrafficStateCallback(mLock, DATA_ACTIVITY_INOUT);
UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
try {
uiAutomation.adoptShellPermissionIdentity();
@@ -1520,7 +2024,7 @@
// Send some traffic to trigger the traffic state change callbacks.
sendTraffic();
// now wait for callback
- mLock.wait(DURATION);
+ mLock.wait(TEST_WAIT_DURATION_MS);
} catch (InterruptedException e) {
}
}
@@ -1743,7 +2247,7 @@
.build(),
networkCallbackListener);
// now wait for callback
- mLock.wait(DURATION);
+ mLock.wait(TEST_WAIT_DURATION_MS);
} catch (InterruptedException e) {
}
}
@@ -1759,4 +2263,252 @@
assertNull(ShellIdentityUtils.invokeWithShellPermissions(mWifiManager::getCurrentNetwork));
}
+
+ /**
+ * Tests {@link WifiManager#isWpa3SaeSupported()} does not crash.
+ */
+ public void testIsWpa3SaeSupported() throws Exception {
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ return;
+ }
+ mWifiManager.isWpa3SaeSupported();
+ }
+
+ /**
+ * Tests {@link WifiManager#isWpa3SuiteBSupported()} does not crash.
+ */
+ public void testIsWpa3SuiteBSupported() throws Exception {
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ return;
+ }
+ mWifiManager.isWpa3SuiteBSupported();
+ }
+
+ /**
+ * Tests {@link WifiManager#isEnhancedOpenSupported()} does not crash.
+ */
+ public void testIsEnhancedOpenSupported() throws Exception {
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ return;
+ }
+ mWifiManager.isEnhancedOpenSupported();
+ }
+
+ /**
+ * Test that {@link WifiManager#is5GHzBandSupported()} returns successfully in
+ * both WiFi enabled/disabled states.
+ * Note that the response depends on device support and hence both true/false
+ * are valid responses.
+ */
+ public void testIs5GhzBandSupported() throws Exception {
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ return;
+ }
+
+ // Check for 5GHz support with wifi enabled
+ setWifiEnabled(true);
+ PollingCheck.check(
+ "Wifi not enabled!",
+ 20000,
+ () -> mWifiManager.isWifiEnabled());
+ boolean isSupportedEnabled = mWifiManager.is5GHzBandSupported();
+
+ // Check for 5GHz support with wifi disabled
+ setWifiEnabled(false);
+ PollingCheck.check(
+ "Wifi not disabled!",
+ 20000,
+ () -> !mWifiManager.isWifiEnabled());
+ boolean isSupportedDisabled = mWifiManager.is5GHzBandSupported();
+
+ // If Support is true when WiFi is disable, then it has to be true when it is enabled.
+ // Note, the reverse is a valid case.
+ if (isSupportedDisabled) {
+ assertTrue(isSupportedEnabled);
+ }
+ }
+
+ /**
+ * Test that {@link WifiManager#is6GHzBandSupported()} returns successfully in
+ * both Wifi enabled/disabled states.
+ * Note that the response depends on device support and hence both true/false
+ * are valid responses.
+ */
+ public void testIs6GhzBandSupported() throws Exception {
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ return;
+ }
+
+ // Check for 6GHz support with wifi enabled
+ setWifiEnabled(true);
+ PollingCheck.check(
+ "Wifi not enabled!",
+ 20000,
+ () -> mWifiManager.isWifiEnabled());
+ boolean isSupportedEnabled = mWifiManager.is6GHzBandSupported();
+
+ // Check for 6GHz support with wifi disabled
+ setWifiEnabled(false);
+ PollingCheck.check(
+ "Wifi not disabled!",
+ 20000,
+ () -> !mWifiManager.isWifiEnabled());
+ boolean isSupportedDisabled = mWifiManager.is6GHzBandSupported();
+
+ // If Support is true when WiFi is disable, then it has to be true when it is enabled.
+ // Note, the reverse is a valid case.
+ if (isSupportedDisabled) {
+ assertTrue(isSupportedEnabled);
+ }
+ }
+
+ /**
+ * Test that {@link WifiManager#isWifiStandardSupported()} returns successfully in
+ * both Wifi enabled/disabled states. The test is to be performed on
+ * {@link WifiAnnotations}'s {@code WIFI_STANDARD_}
+ * Note that the response depends on device support and hence both true/false
+ * are valid responses.
+ */
+ public void testIsWifiStandardsSupported() throws Exception {
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ return;
+ }
+
+ // Check for WiFi standards support with wifi enabled
+ setWifiEnabled(true);
+ PollingCheck.check(
+ "Wifi not enabled!",
+ 20000,
+ () -> mWifiManager.isWifiEnabled());
+ boolean isLegacySupportedEnabled =
+ mWifiManager.isWifiStandardSupported(ScanResult.WIFI_STANDARD_LEGACY);
+ boolean is11nSupporedEnabled =
+ mWifiManager.isWifiStandardSupported(ScanResult.WIFI_STANDARD_11N);
+ boolean is11acSupportedEnabled =
+ mWifiManager.isWifiStandardSupported(ScanResult.WIFI_STANDARD_11AC);
+ boolean is11axSupportedEnabled =
+ mWifiManager.isWifiStandardSupported(ScanResult.WIFI_STANDARD_11AX);
+
+ // Check for WiFi standards support with wifi disabled
+ setWifiEnabled(false);
+ PollingCheck.check(
+ "Wifi not disabled!",
+ 20000,
+ () -> !mWifiManager.isWifiEnabled());
+
+ boolean isLegacySupportedDisabled =
+ mWifiManager.isWifiStandardSupported(ScanResult.WIFI_STANDARD_LEGACY);
+ boolean is11nSupportedDisabled =
+ mWifiManager.isWifiStandardSupported(ScanResult.WIFI_STANDARD_11N);
+ boolean is11acSupportedDisabled =
+ mWifiManager.isWifiStandardSupported(ScanResult.WIFI_STANDARD_11AC);
+ boolean is11axSupportedDisabled =
+ mWifiManager.isWifiStandardSupported(ScanResult.WIFI_STANDARD_11AX);
+
+ if (isLegacySupportedDisabled) {
+ assertTrue(isLegacySupportedEnabled);
+ }
+
+ if (is11nSupportedDisabled) {
+ assertTrue(is11nSupporedEnabled);
+ }
+
+ if (is11acSupportedDisabled) {
+ assertTrue(is11acSupportedEnabled);
+ }
+
+ if (is11axSupportedDisabled) {
+ assertTrue(is11axSupportedEnabled);
+ }
+ }
+
+ private static PasspointConfiguration createPasspointConfiguration() {
+ PasspointConfiguration config = new PasspointConfiguration();
+ HomeSp homeSp = new HomeSp();
+ homeSp.setFqdn("test.com");
+ homeSp.setFriendlyName("friendly name");
+ homeSp.setRoamingConsortiumOis(new long[]{0x55, 0x66});
+ config.setHomeSp(homeSp);
+ Credential.SimCredential simCred = new Credential.SimCredential();
+ simCred.setImsi("123456*");
+ simCred.setEapType(23 /* EAP_AKA */);
+ Credential cred = new Credential();
+ cred.setRealm("realm");
+ cred.setSimCredential(simCred);
+ config.setCredential(cred);
+
+ return config;
+ }
+
+ /**
+ * Tests {@link WifiManager#addOrUpdatePasspointConfiguration(PasspointConfiguration)}
+ * adds a Passpoint configuration correctly by getting it once it is added, and comparing it
+ * to the local copy of the configuration.
+ */
+ public void testAddOrUpdatePasspointConfiguration() throws Exception {
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ return;
+ }
+
+ // Create and install a Passpoint configuration
+ PasspointConfiguration passpointConfiguration = createPasspointConfiguration();
+ mWifiManager.addOrUpdatePasspointConfiguration(passpointConfiguration);
+
+ // Compare configurations
+ List<PasspointConfiguration> configurations = mWifiManager.getPasspointConfigurations();
+ assertNotNull(configurations);
+ assertEquals(passpointConfiguration, configurations.get(0));
+
+ // Clean up
+ mWifiManager.removePasspointConfiguration(passpointConfiguration.getHomeSp().getFqdn());
+ }
+
+ /**
+ * Tests that
+ * {@link WifiManager#startSubscriptionProvisioning(OsuProvider, Executor, ProvisioningCallback)}
+ * starts a subscription provisioning, and confirm a status callback invoked once.
+ */
+ public void testStartSubscriptionProvisioning() throws Exception {
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ return;
+ }
+
+ // Using Java reflection to construct an OsuProvider instance because its constructor is
+ // hidden and not available to apps.
+ Class<?> osuProviderClass = Class.forName("android.net.wifi.hotspot2.OsuProvider");
+ Constructor<?> osuProviderClassConstructor = osuProviderClass.getConstructor(String.class,
+ Map.class, String.class, Uri.class, String.class, List.class);
+
+ OsuProvider osuProvider = (OsuProvider) osuProviderClassConstructor.newInstance(TEST_SSID,
+ TEST_FRIENDLY_NAMES, TEST_SERVICE_DESCRIPTION, TEST_SERVER_URI, TEST_NAI,
+ TEST_METHOD_LIST);
+
+ UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
+ try {
+ uiAutomation.adoptShellPermissionIdentity();
+ synchronized (mLock) {
+ // Start a subscription provisioning for a non-existent Passpoint R2 AP
+ mWifiManager.startSubscriptionProvisioning(osuProvider, mExecutor,
+ mProvisioningCallback);
+ mLock.wait(TEST_WAIT_DURATION_MS);
+ }
+ } finally {
+ uiAutomation.dropShellPermissionIdentity();
+ }
+
+ // Expect only a single callback event, connecting. Since AP doesn't exist, it ends here
+ assertEquals(ProvisioningCallback.OSU_STATUS_AP_CONNECTING, mProvisioningStatus);
+ // No failure callbacks expected
+ assertEquals(0, mProvisioningFailureStatus);
+ // No completion callback expected
+ assertFalse(mProvisioningComplete);
+ }
}
diff --git a/tests/tests/net/src/android/net/wifi/cts/WifiMigrationTest.java b/tests/tests/net/src/android/net/wifi/cts/WifiMigrationTest.java
index 6e19a21..7d94ad3 100644
--- a/tests/tests/net/src/android/net/wifi/cts/WifiMigrationTest.java
+++ b/tests/tests/net/src/android/net/wifi/cts/WifiMigrationTest.java
@@ -16,16 +16,9 @@
package android.net.wifi.cts;
-import static org.junit.Assert.assertNotNull;
-
-import android.net.wifi.SoftApConfiguration;
-import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiMigration;
import android.test.AndroidTestCase;
-import java.util.Arrays;
-import java.util.List;
-
public class WifiMigrationTest extends AndroidTestCase {
private static final String TEST_SSID_UNQUOTED = "testSsid1";
@@ -49,42 +42,7 @@
}
/**
- * Tests {@link android.net.wifi.WifiMigration.ConfigStoreMigrationData} class.
- */
- public void testWifiMigrationConfigStoreDataBuilder() throws Exception {
- if (!WifiFeature.isWifiSupported(getContext())) {
- // skip the test if WiFi is not supported
- return;
- }
- WifiConfiguration savedNetwork1 = new WifiConfiguration();
- savedNetwork1.SSID = "\"test1\"";
- WifiConfiguration savedNetwork2 = new WifiConfiguration();
- savedNetwork1.SSID = "\"test2\"";
- List<WifiConfiguration> savedNetworks = Arrays.asList(savedNetwork1, savedNetwork2);
-
- SoftApConfiguration softApConfiguration = new SoftApConfiguration.Builder()
- .setSsid("\"test3\"")
- .build();
-
- WifiMigration.ConfigStoreMigrationData migrationData =
- new WifiMigration.ConfigStoreMigrationData.Builder()
- .setUserSavedNetworkConfigurations(savedNetworks)
- .setUserSoftApConfiguration(softApConfiguration)
- .build();
-
- assertNotNull(migrationData);
- assertEquals(savedNetworks.size(),
- migrationData.getUserSavedNetworkConfigurations().size());
- assertEquals(savedNetwork1.SSID,
- migrationData.getUserSavedNetworkConfigurations().get(0).SSID);
- assertEquals(savedNetwork2.SSID,
- migrationData.getUserSavedNetworkConfigurations().get(1).SSID);
- assertEquals(softApConfiguration.getSsid(),
- migrationData.getUserSoftApConfiguration().getSsid());
- }
-
- /**
- * Tests {@link android.net.wifi.WifiMigration.ConfigStoreMigrationData} class.
+ * Tests {@link android.net.wifi.WifiMigration.SettingsMigrationData.Builder} class.
*/
public void testWifiMigrationSettingsDataBuilder() throws Exception {
if (!WifiFeature.isWifiSupported(getContext())) {
@@ -111,4 +69,15 @@
assertTrue(migrationData.isVerboseLoggingEnabled());
assertEquals(TEST_SSID_UNQUOTED, migrationData.getP2pDeviceName());
}
+
+ /**
+ * Tests {@link android.net.wifi.WifiMigration.SettingsMigrationData} class.
+ */
+ public void testWifiMigrationSettings() throws Exception {
+ try {
+ // ensure that this does not crash.
+ WifiMigration.loadFromSettings(getContext());
+ } catch (Exception ignore) {
+ }
+ }
}
diff --git a/tests/tests/net/src/android/net/wifi/cts/WifiNetworkSpecifierTest.java b/tests/tests/net/src/android/net/wifi/cts/WifiNetworkSpecifierTest.java
index 96cf45f..2065bb0 100644
--- a/tests/tests/net/src/android/net/wifi/cts/WifiNetworkSpecifierTest.java
+++ b/tests/tests/net/src/android/net/wifi/cts/WifiNetworkSpecifierTest.java
@@ -31,6 +31,7 @@
import android.net.NetworkRequest;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiEnterpriseConfig;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiManager.NetworkRequestMatchCallback;
@@ -506,4 +507,44 @@
.build();
testUserRejectionWithSpecifier(specifier);
}
+
+ /**
+ * Tests the builder for WPA2 enterprise networks.
+ * Note: Can't do end to end tests for such networks in CTS environment.
+ */
+ public void testBuilderForWpa2Enterprise() {
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ return;
+ }
+ WifiNetworkSpecifier specifier1 = new WifiNetworkSpecifier.Builder()
+ .setSsid(WifiInfo.sanitizeSsid(mTestNetwork.SSID))
+ .setWpa2EnterpriseConfig(new WifiEnterpriseConfig())
+ .build();
+ WifiNetworkSpecifier specifier2 = new WifiNetworkSpecifier.Builder()
+ .setSsid(WifiInfo.sanitizeSsid(mTestNetwork.SSID))
+ .setWpa2EnterpriseConfig(new WifiEnterpriseConfig())
+ .build();
+ assertThat(specifier1.satisfiedBy(specifier2)).isTrue();
+ }
+
+ /**
+ * Tests the builder for WPA3 enterprise networks.
+ * Note: Can't do end to end tests for such networks in CTS environment.
+ */
+ public void testBuilderForWpa3Enterprise() {
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ return;
+ }
+ WifiNetworkSpecifier specifier1 = new WifiNetworkSpecifier.Builder()
+ .setSsid(WifiInfo.sanitizeSsid(mTestNetwork.SSID))
+ .setWpa3EnterpriseConfig(new WifiEnterpriseConfig())
+ .build();
+ WifiNetworkSpecifier specifier2 = new WifiNetworkSpecifier.Builder()
+ .setSsid(WifiInfo.sanitizeSsid(mTestNetwork.SSID))
+ .setWpa3EnterpriseConfig(new WifiEnterpriseConfig())
+ .build();
+ assertThat(specifier1.satisfiedBy(specifier2)).isTrue();
+ }
}
diff --git a/tests/tests/net/src/android/net/wifi/cts/WifiNetworkSuggestionTest.java b/tests/tests/net/src/android/net/wifi/cts/WifiNetworkSuggestionTest.java
index 994b6c9..e73abb8 100644
--- a/tests/tests/net/src/android/net/wifi/cts/WifiNetworkSuggestionTest.java
+++ b/tests/tests/net/src/android/net/wifi/cts/WifiNetworkSuggestionTest.java
@@ -17,6 +17,7 @@
package android.net.wifi.cts;
import static android.net.wifi.WifiEnterpriseConfig.Eap.AKA;
+import static android.net.wifi.WifiEnterpriseConfig.Eap.WAPI_CERT;
import android.net.MacAddress;
import android.net.wifi.WifiEnterpriseConfig;
@@ -199,6 +200,28 @@
}
/**
+ * Tests {@link android.net.wifi.WifiNetworkSuggestion.Builder} class.
+ */
+ public void testBuilderWithWapiEnterprise() throws Exception {
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ return;
+ }
+ WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig();
+ enterpriseConfig.setEapMethod(WAPI_CERT);
+ WifiNetworkSuggestion suggestion =
+ createBuilderWithCommonParams()
+ .setWapiEnterpriseConfig(enterpriseConfig)
+ .build();
+ validateCommonParams(suggestion);
+ assertNull(suggestion.getPassphrase());
+ assertNotNull(suggestion.getEnterpriseConfig());
+ assertEquals(enterpriseConfig.getEapMethod(),
+ suggestion.getEnterpriseConfig().getEapMethod());
+ assertNull(suggestion.getPasspointConfig());
+ }
+
+ /**
* Helper function for creating a {@link PasspointConfiguration} for testing.
*
* @return {@link PasspointConfiguration}
diff --git a/tests/tests/net/src/android/net/wifi/nl80211/cts/DeviceWiphyCapabilitiesTest.java b/tests/tests/net/src/android/net/wifi/nl80211/cts/DeviceWiphyCapabilitiesTest.java
new file mode 100644
index 0000000..d8f5e57
--- /dev/null
+++ b/tests/tests/net/src/android/net/wifi/nl80211/cts/DeviceWiphyCapabilitiesTest.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2020 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.net.wifi.nl80211.cts;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assume.assumeTrue;
+
+import android.content.Context;
+import android.net.wifi.ScanResult;
+import android.net.wifi.cts.WifiFeature;
+import android.net.wifi.nl80211.DeviceWiphyCapabilities;
+import android.os.Parcel;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/** CTS tests for {@link DeviceWiphyCapabilities}. */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class DeviceWiphyCapabilitiesTest {
+
+ @Before
+ public void setUp() {
+ Context context = InstrumentationRegistry.getInstrumentation().getContext();
+ // skip tests if Wifi is not supported
+ assumeTrue(WifiFeature.isWifiSupported(context));
+ }
+
+ /**
+ * Test that a {@link DeviceWiphyCapabilities} object can be serialized and deserialized,
+ * while keeping its values unchanged.
+ */
+ @Test
+ public void canSerializeAndDeserialize() {
+ DeviceWiphyCapabilities capa = new DeviceWiphyCapabilities();
+
+ capa.setWifiStandardSupport(ScanResult.WIFI_STANDARD_11N, true);
+ capa.setWifiStandardSupport(ScanResult.WIFI_STANDARD_11AC, true);
+ capa.setWifiStandardSupport(ScanResult.WIFI_STANDARD_11AX, false);
+
+ Parcel parcel = Parcel.obtain();
+ capa.writeToParcel(parcel, 0);
+ // Rewind the pointer to the head of the parcel.
+ parcel.setDataPosition(0);
+ DeviceWiphyCapabilities capaDeserialized =
+ DeviceWiphyCapabilities.CREATOR.createFromParcel(parcel);
+
+ assertThat(capaDeserialized.isWifiStandardSupported(ScanResult.WIFI_STANDARD_11N)).isTrue();
+ assertThat(capaDeserialized.isWifiStandardSupported(ScanResult.WIFI_STANDARD_11AC))
+ .isTrue();
+ assertThat(capaDeserialized.isWifiStandardSupported(ScanResult.WIFI_STANDARD_11AX))
+ .isFalse();
+ assertThat(capaDeserialized).isEqualTo(capa);
+ assertThat(capaDeserialized.hashCode()).isEqualTo(capa.hashCode());
+ }
+
+ /** Test mapping wifi standard support into channel width support */
+ @Test
+ public void testMappingWifiStandardIntoChannelWidthSupport() {
+ DeviceWiphyCapabilities capa = new DeviceWiphyCapabilities();
+
+ capa.setWifiStandardSupport(ScanResult.WIFI_STANDARD_11N, false);
+ capa.setWifiStandardSupport(ScanResult.WIFI_STANDARD_11AC, false);
+ capa.setWifiStandardSupport(ScanResult.WIFI_STANDARD_11AX, false);
+ assertThat(capa.isChannelWidthSupported(ScanResult.CHANNEL_WIDTH_20MHZ)).isTrue();
+ assertThat(capa.isChannelWidthSupported(ScanResult.CHANNEL_WIDTH_40MHZ)).isFalse();
+ assertThat(capa.isChannelWidthSupported(ScanResult.CHANNEL_WIDTH_80MHZ)).isFalse();
+
+ capa.setWifiStandardSupport(ScanResult.WIFI_STANDARD_11N, true);
+ assertThat(capa.isChannelWidthSupported(ScanResult.CHANNEL_WIDTH_20MHZ)).isTrue();
+ assertThat(capa.isChannelWidthSupported(ScanResult.CHANNEL_WIDTH_40MHZ)).isTrue();
+ assertThat(capa.isChannelWidthSupported(ScanResult.CHANNEL_WIDTH_80MHZ)).isFalse();
+
+ capa.setWifiStandardSupport(ScanResult.WIFI_STANDARD_11AC, true);
+ assertThat(capa.isChannelWidthSupported(ScanResult.CHANNEL_WIDTH_20MHZ)).isTrue();
+ assertThat(capa.isChannelWidthSupported(ScanResult.CHANNEL_WIDTH_40MHZ)).isTrue();
+ assertThat(capa.isChannelWidthSupported(ScanResult.CHANNEL_WIDTH_80MHZ)).isTrue();
+ }
+}
diff --git a/tests/tests/net/src/android/net/wifi/nl80211/cts/NativeWifiClientTest.java b/tests/tests/net/src/android/net/wifi/nl80211/cts/NativeWifiClientTest.java
new file mode 100644
index 0000000..3149b54
--- /dev/null
+++ b/tests/tests/net/src/android/net/wifi/nl80211/cts/NativeWifiClientTest.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2020 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.net.wifi.nl80211.cts;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assume.assumeTrue;
+
+import android.content.Context;
+import android.net.MacAddress;
+import android.net.wifi.cts.WifiFeature;
+import android.net.wifi.nl80211.NativeWifiClient;
+import android.os.Parcel;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/** CTS tests for {@link NativeWifiClient}. */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class NativeWifiClientTest {
+
+ private static final byte[] TEST_MAC = { 1, 2, 3, 4, 5, 6 };
+
+ @Before
+ public void setUp() {
+ Context context = InstrumentationRegistry.getInstrumentation().getContext();
+ // skip tests if Wifi is not supported
+ assumeTrue(WifiFeature.isWifiSupported(context));
+ }
+
+ @Test
+ public void testGetters() {
+ NativeWifiClient client = new NativeWifiClient(MacAddress.fromBytes(TEST_MAC));
+
+ assertThat(client.getMacAddress().toByteArray()).isEqualTo(TEST_MAC);
+ }
+
+ @Test
+ public void canSerializeAndDeserialize() {
+ NativeWifiClient client = new NativeWifiClient(MacAddress.fromBytes(TEST_MAC));
+
+ Parcel parcel = Parcel.obtain();
+ client.writeToParcel(parcel, 0);
+ // Rewind the pointer to the head of the parcel.
+ parcel.setDataPosition(0);
+ NativeWifiClient clientDeserialized = NativeWifiClient.CREATOR.createFromParcel(parcel);
+
+ assertThat(clientDeserialized.getMacAddress().toByteArray()).isEqualTo(TEST_MAC);
+ assertThat(clientDeserialized).isEqualTo(client);
+ assertThat(clientDeserialized.hashCode()).isEqualTo(client.hashCode());
+ }
+
+ @Test
+ public void testEquals() {
+ NativeWifiClient client = new NativeWifiClient(MacAddress.fromBytes(TEST_MAC));
+ NativeWifiClient client2 =
+ new NativeWifiClient(MacAddress.fromBytes(new byte[] { 7, 8, 9, 10, 11, 12 }));
+
+ assertThat(client2).isNotEqualTo(client);
+ }
+}
diff --git a/tests/tests/net/src/android/net/wifi/nl80211/cts/PnoNetworkTest.java b/tests/tests/net/src/android/net/wifi/nl80211/cts/PnoNetworkTest.java
new file mode 100644
index 0000000..f3a8f05
--- /dev/null
+++ b/tests/tests/net/src/android/net/wifi/nl80211/cts/PnoNetworkTest.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2020 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.net.wifi.nl80211.cts;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assume.assumeTrue;
+
+import android.content.Context;
+import android.net.wifi.cts.WifiFeature;
+import android.net.wifi.nl80211.PnoNetwork;
+import android.os.Parcel;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/** CTS tests for {@link PnoNetwork}. */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class PnoNetworkTest {
+
+ private static final byte[] TEST_SSID = { 's', 's', 'i', 'd' };
+ private static final int[] TEST_FREQUENCIES = { 2412, 2417, 5035 };
+
+ @Before
+ public void setUp() {
+ Context context = InstrumentationRegistry.getInstrumentation().getContext();
+ // skip tests if Wifi is not supported
+ assumeTrue(WifiFeature.isWifiSupported(context));
+ }
+
+ @Test
+ public void testGetters() {
+ PnoNetwork network = new PnoNetwork();
+ network.setSsid(TEST_SSID);
+ network.setFrequenciesMhz(TEST_FREQUENCIES);
+ network.setHidden(true);
+
+ assertThat(network.getSsid()).isEqualTo(TEST_SSID);
+ assertThat(network.getFrequenciesMhz()).isEqualTo(TEST_FREQUENCIES);
+ assertThat(network.isHidden()).isTrue();
+ }
+
+ @Test
+ public void canSerializeAndDeserialize() {
+ PnoNetwork network = new PnoNetwork();
+ network.setSsid(TEST_SSID);
+ network.setFrequenciesMhz(TEST_FREQUENCIES);
+ network.setHidden(true);
+
+ Parcel parcel = Parcel.obtain();
+ network.writeToParcel(parcel, 0);
+ // Rewind the pointer to the head of the parcel.
+ parcel.setDataPosition(0);
+ PnoNetwork networkDeserialized = PnoNetwork.CREATOR.createFromParcel(parcel);
+
+ assertThat(networkDeserialized.getSsid()).isEqualTo(TEST_SSID);
+ assertThat(networkDeserialized.getFrequenciesMhz()).isEqualTo(TEST_FREQUENCIES);
+ assertThat(networkDeserialized.isHidden()).isTrue();
+ assertThat(networkDeserialized).isEqualTo(network);
+ assertThat(networkDeserialized.hashCode()).isEqualTo(network.hashCode());
+ }
+
+ @Test
+ public void testEquals() {
+ PnoNetwork network = new PnoNetwork();
+ network.setSsid(TEST_SSID);
+ network.setFrequenciesMhz(TEST_FREQUENCIES);
+ network.setHidden(true);
+
+ PnoNetwork network2 = new PnoNetwork();
+ network.setSsid(new byte[] { 'a', 's', 'd', 'f'});
+ network.setFrequenciesMhz(new int[] { 1, 2, 3 });
+ network.setHidden(false);
+
+ assertThat(network2).isNotEqualTo(network);
+ }
+}
diff --git a/tests/tests/net/src/android/net/wifi/nl80211/cts/PnoSettingsTest.java b/tests/tests/net/src/android/net/wifi/nl80211/cts/PnoSettingsTest.java
new file mode 100644
index 0000000..59f5d99
--- /dev/null
+++ b/tests/tests/net/src/android/net/wifi/nl80211/cts/PnoSettingsTest.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2020 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.net.wifi.nl80211.cts;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assume.assumeTrue;
+
+import android.content.Context;
+import android.net.wifi.cts.WifiFeature;
+import android.net.wifi.nl80211.PnoNetwork;
+import android.net.wifi.nl80211.PnoSettings;
+import android.os.Parcel;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Arrays;
+import java.util.List;
+
+/** CTS tests for {@link PnoSettings}. */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class PnoSettingsTest {
+
+ private static List<PnoNetwork> createTestNetworks() {
+ PnoNetwork network1 = new PnoNetwork();
+ network1.setSsid(new byte[] { 's', 's', 'i', 'd' });
+ network1.setFrequenciesMhz(new int[] { 2412, 2417, 5035 });
+ network1.setHidden(true);
+
+ PnoNetwork network2 = new PnoNetwork();
+ network2.setSsid(new byte[] { 'a', 's', 'd', 'f' });
+ network2.setFrequenciesMhz(new int[] { 2422, 2427, 5040 });
+ network2.setHidden(false);
+
+ return Arrays.asList(network1, network2);
+ }
+
+ @Before
+ public void setUp() {
+ Context context = InstrumentationRegistry.getInstrumentation().getContext();
+ // skip tests if Wifi is not supported
+ assumeTrue(WifiFeature.isWifiSupported(context));
+ }
+
+ @Test
+ public void testGetters() {
+ PnoSettings settings = new PnoSettings();
+ settings.setIntervalMillis(1000);
+ settings.setMin2gRssiDbm(-70);
+ settings.setMin5gRssiDbm(-60);
+ settings.setMin6gRssiDbm(-50);
+ settings.setPnoNetworks(createTestNetworks());
+
+ assertThat(settings.getIntervalMillis()).isEqualTo(1000);
+ assertThat(settings.getMin2gRssiDbm()).isEqualTo(-70);
+ assertThat(settings.getMin5gRssiDbm()).isEqualTo(-60);
+ assertThat(settings.getMin6gRssiDbm()).isEqualTo(-50);
+ assertThat(settings.getPnoNetworks()).isEqualTo(createTestNetworks());
+ }
+
+ @Test
+ public void canSerializeAndDeserialize() {
+ PnoSettings settings = new PnoSettings();
+ settings.setIntervalMillis(1000);
+ settings.setMin2gRssiDbm(-70);
+ settings.setMin5gRssiDbm(-60);
+ settings.setMin6gRssiDbm(-50);
+ settings.setPnoNetworks(createTestNetworks());
+
+ Parcel parcel = Parcel.obtain();
+ settings.writeToParcel(parcel, 0);
+ // Rewind the pointer to the head of the parcel.
+ parcel.setDataPosition(0);
+ PnoSettings settingsDeserialized = PnoSettings.CREATOR.createFromParcel(parcel);
+
+ assertThat(settingsDeserialized.getIntervalMillis()).isEqualTo(1000);
+ assertThat(settingsDeserialized.getMin2gRssiDbm()).isEqualTo(-70);
+ assertThat(settingsDeserialized.getMin5gRssiDbm()).isEqualTo(-60);
+ assertThat(settingsDeserialized.getMin6gRssiDbm()).isEqualTo(-50);
+ assertThat(settingsDeserialized.getPnoNetworks()).isEqualTo(createTestNetworks());
+ assertThat(settingsDeserialized).isEqualTo(settings);
+ assertThat(settingsDeserialized.hashCode()).isEqualTo(settings.hashCode());
+ }
+
+ @Test
+ public void testEquals() {
+ PnoSettings settings = new PnoSettings();
+ settings.setIntervalMillis(1000);
+ settings.setMin2gRssiDbm(-70);
+ settings.setMin5gRssiDbm(-60);
+ settings.setMin6gRssiDbm(-50);
+ settings.setPnoNetworks(createTestNetworks());
+
+ PnoSettings settings2 = new PnoSettings();
+ settings.setIntervalMillis(2000);
+ settings.setMin2gRssiDbm(-70);
+ settings.setMin5gRssiDbm(-60);
+ settings.setMin6gRssiDbm(-50);
+ settings.setPnoNetworks(createTestNetworks());
+
+ assertThat(settings2).isNotEqualTo(settings);
+ }
+}
diff --git a/tests/tests/net/src/android/net/wifi/nl80211/cts/RadioChainInfoTest.java b/tests/tests/net/src/android/net/wifi/nl80211/cts/RadioChainInfoTest.java
new file mode 100644
index 0000000..0a76bdb
--- /dev/null
+++ b/tests/tests/net/src/android/net/wifi/nl80211/cts/RadioChainInfoTest.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2020 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.net.wifi.nl80211.cts;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assume.assumeTrue;
+
+import android.content.Context;
+import android.net.wifi.cts.WifiFeature;
+import android.net.wifi.nl80211.RadioChainInfo;
+import android.os.Parcel;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/** CTS tests for {@link RadioChainInfo}. */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class RadioChainInfoTest {
+
+ private static final int TEST_CHAIN_ID = 1;
+ private static final int TEST_CHAIN_ID2 = 2;
+ private static final int TEST_LEVEL_DBM = -50;
+ private static final int TEST_LEVEL_DBM2 = -80;
+
+ @Before
+ public void setUp() {
+ Context context = InstrumentationRegistry.getInstrumentation().getContext();
+ // skip tests if Wifi is not supported
+ assumeTrue(WifiFeature.isWifiSupported(context));
+ }
+
+ @Test
+ public void testGetters() {
+ RadioChainInfo info = new RadioChainInfo(TEST_CHAIN_ID, TEST_LEVEL_DBM);
+ assertThat(info.getChainId()).isEqualTo(TEST_CHAIN_ID);
+ assertThat(info.getLevelDbm()).isEqualTo(TEST_LEVEL_DBM);
+ }
+
+ @Test
+ public void canSerializeAndDeserialize() {
+ RadioChainInfo info = new RadioChainInfo(TEST_CHAIN_ID, TEST_LEVEL_DBM);
+
+ Parcel parcel = Parcel.obtain();
+ info.writeToParcel(parcel, 0);
+ // Rewind the pointer to the head of the parcel.
+ parcel.setDataPosition(0);
+ RadioChainInfo infoDeserialized = RadioChainInfo.CREATOR.createFromParcel(parcel);
+
+ assertThat(infoDeserialized.getChainId()).isEqualTo(TEST_CHAIN_ID);
+ assertThat(infoDeserialized.getLevelDbm()).isEqualTo(TEST_LEVEL_DBM);
+ assertThat(infoDeserialized).isEqualTo(info);
+ assertThat(infoDeserialized.hashCode()).isEqualTo(info.hashCode());
+ }
+
+ @Test
+ public void testEquals() {
+ RadioChainInfo info = new RadioChainInfo(TEST_CHAIN_ID, TEST_LEVEL_DBM);
+ RadioChainInfo info2 = new RadioChainInfo(TEST_CHAIN_ID2, TEST_LEVEL_DBM2);
+
+ assertThat(info2).isNotEqualTo(info);
+ }
+}
diff --git a/tests/tests/net/src/android/net/wifi/nl80211/cts/WifiNl80211ManagerTest.java b/tests/tests/net/src/android/net/wifi/nl80211/cts/WifiNl80211ManagerTest.java
new file mode 100644
index 0000000..f1f3010
--- /dev/null
+++ b/tests/tests/net/src/android/net/wifi/nl80211/cts/WifiNl80211ManagerTest.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2020 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.net.wifi.nl80211.cts;
+
+import static android.net.wifi.nl80211.WifiNl80211Manager.OemSecurityType;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assume.assumeTrue;
+
+import android.content.Context;
+import android.net.wifi.ScanResult;
+import android.net.wifi.cts.WifiFeature;
+import android.net.wifi.nl80211.WifiNl80211Manager;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Arrays;
+
+/** CTS tests for {@link WifiNl80211Manager}. */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class WifiNl80211ManagerTest {
+
+ private Context mContext;
+
+ @Before
+ public void setUp() {
+ mContext = InstrumentationRegistry.getInstrumentation().getContext();
+ // skip tests if Wifi is not supported
+ assumeTrue(WifiFeature.isWifiSupported(mContext));
+ }
+
+ @Test
+ public void testOemSecurityTypeConstructor() {
+ OemSecurityType securityType = new OemSecurityType(
+ ScanResult.PROTOCOL_WPA,
+ Arrays.asList(ScanResult.KEY_MGMT_PSK, ScanResult.KEY_MGMT_SAE),
+ Arrays.asList(ScanResult.CIPHER_NONE, ScanResult.CIPHER_TKIP),
+ ScanResult.CIPHER_CCMP);
+
+ assertThat(securityType.protocol).isEqualTo(ScanResult.PROTOCOL_WPA);
+ assertThat(securityType.keyManagement)
+ .isEqualTo(Arrays.asList(ScanResult.KEY_MGMT_PSK, ScanResult.KEY_MGMT_SAE));
+ assertThat(securityType.pairwiseCipher)
+ .isEqualTo(Arrays.asList(ScanResult.CIPHER_NONE, ScanResult.CIPHER_TKIP));
+ assertThat(securityType.groupCipher).isEqualTo(ScanResult.CIPHER_CCMP);
+ }
+
+ @Test
+ public void testSendMgmtFrame() {
+ try {
+ WifiNl80211Manager manager = mContext.getSystemService(WifiNl80211Manager.class);
+ manager.sendMgmtFrame("wlan0", new byte[]{}, -1, Runnable::run,
+ new WifiNl80211Manager.SendMgmtFrameCallback() {
+ @Override
+ public void onAck(int elapsedTimeMs) {}
+
+ @Override
+ public void onFailure(int reason) {}
+ });
+ } catch (Exception ignore) {}
+ }
+}
diff --git a/tests/tests/net/src/android/net/wifi/p2p/cts/WifiP2pDeviceTest.java b/tests/tests/net/src/android/net/wifi/p2p/cts/WifiP2pDeviceTest.java
new file mode 100644
index 0000000..1510d7c
--- /dev/null
+++ b/tests/tests/net/src/android/net/wifi/p2p/cts/WifiP2pDeviceTest.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2020 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.net.wifi.p2p.cts;
+
+import android.net.InetAddresses;
+import android.net.wifi.p2p.WifiP2pDevice;
+import android.test.AndroidTestCase;
+
+public class WifiP2pDeviceTest extends AndroidTestCase {
+
+ public void testDefaultWpsMethodSupportCheck() {
+ WifiP2pDevice dev = new WifiP2pDevice();
+
+ assertFalse(dev.wpsPbcSupported());
+ assertFalse(dev.wpsDisplaySupported());
+ assertFalse(dev.wpsKeypadSupported());
+ }
+
+ public void testDefaultDeviceCapabilityCheck() {
+ WifiP2pDevice dev = new WifiP2pDevice();
+
+ assertFalse(dev.isServiceDiscoveryCapable());
+ }
+}
diff --git a/tests/tests/net/src/android/net/wifi/p2p/cts/WifiP2pServiceRequestTest.java b/tests/tests/net/src/android/net/wifi/p2p/cts/WifiP2pServiceRequestTest.java
new file mode 100644
index 0000000..b363b1e
--- /dev/null
+++ b/tests/tests/net/src/android/net/wifi/p2p/cts/WifiP2pServiceRequestTest.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2020 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.net.wifi.p2p.cts;
+
+import android.net.wifi.p2p.nsd.WifiP2pServiceInfo;
+import android.net.wifi.p2p.nsd.WifiP2pServiceRequest;
+import android.net.wifi.p2p.nsd.WifiP2pUpnpServiceRequest;
+import android.test.AndroidTestCase;
+import android.util.Log;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Locale;
+import java.util.stream.Collectors;
+
+public class WifiP2pServiceRequestTest extends AndroidTestCase {
+
+ private final int TEST_UPNP_VERSION = 0x10;
+ private final String TEST_UPNP_QUERY = "ssdp:all";
+
+ private String bin2HexStr(byte[] data) {
+ StringBuffer sb = new StringBuffer();
+ for (byte b: data) {
+ sb.append(String.format(Locale.US, "%02x", b & 0xff));
+ }
+ return sb.toString();
+ }
+
+ public void testValidRawRequest() throws IllegalArgumentException {
+ StringBuffer sb = new StringBuffer();
+ sb.append(String.format(Locale.US, "%02x", TEST_UPNP_VERSION));
+ sb.append(bin2HexStr(TEST_UPNP_QUERY.getBytes()));
+
+ WifiP2pServiceRequest rawRequest =
+ WifiP2pServiceRequest.newInstance(
+ WifiP2pServiceInfo.SERVICE_TYPE_UPNP,
+ sb.toString());
+
+ WifiP2pUpnpServiceRequest upnpRequest =
+ WifiP2pUpnpServiceRequest.newInstance(
+ TEST_UPNP_QUERY);
+
+ assertEquals(rawRequest, upnpRequest);
+ }
+
+ public void testInvalidRawRequest() {
+ StringBuffer sb = new StringBuffer();
+ sb.append(String.format(Locale.US, "%02x", TEST_UPNP_VERSION));
+ sb.append(bin2HexStr(TEST_UPNP_QUERY.getBytes()));
+ sb.append("x");
+
+ try {
+ WifiP2pServiceRequest request =
+ WifiP2pServiceRequest.newInstance(
+ WifiP2pServiceInfo.SERVICE_TYPE_UPNP, sb.toString());
+ fail("Expected IllegalArgumentException");
+ } catch (IllegalArgumentException ex) {
+ return;
+ }
+ }
+}
diff --git a/tests/tests/os/src/android/os/cts/StrictModeTest.java b/tests/tests/os/src/android/os/cts/StrictModeTest.java
index 1a4f0ef..b750e707 100644
--- a/tests/tests/os/src/android/os/cts/StrictModeTest.java
+++ b/tests/tests/os/src/android/os/cts/StrictModeTest.java
@@ -626,10 +626,11 @@
.penaltyLog()
.build());
+ final String wmClassName = WindowManager.class.getSimpleName();
inspectViolation(
() -> getContext().getApplicationContext().getSystemService(WindowManager.class),
info -> assertThat(info.getStackTrace()).contains(
- "Tried to access visual service " + WINDOW_SERVICE));
+ "Tried to access visual service " + wmClassName));
final Display display = getContext().getSystemService(DisplayManager.class)
.getDisplay(DEFAULT_DISPLAY);
diff --git a/tests/tests/os/src/android/os/cts/VibratorTest.java b/tests/tests/os/src/android/os/cts/VibratorTest.java
index 09ba0fa..f597612 100644
--- a/tests/tests/os/src/android/os/cts/VibratorTest.java
+++ b/tests/tests/os/src/android/os/cts/VibratorTest.java
@@ -144,25 +144,36 @@
mVibrator.hasAmplitudeControl();
}
+ /**
+ * For devices with vibrator we assert the IsVibrating state, for devices without vibrator just
+ * ensure it won't crash with IsVibrating call.
+ */
+ private void assertIsVibrating(boolean expected) {
+ final boolean isVibrating = mVibrator.isVibrating();
+ if (mVibrator.hasVibrator()) {
+ assertEquals(isVibrating, expected);
+ }
+ }
+
@Test
public void testVibratorIsVibrating() {
final UiAutomation ui = InstrumentationRegistry.getInstrumentation().getUiAutomation();
ui.adoptShellPermissionIdentity("android.permission.ACCESS_VIBRATOR_STATE");
- assertEquals(mVibrator.isVibrating(), false);
+ assertIsVibrating(false);
mVibrator.vibrate(1000);
- assertEquals(mVibrator.isVibrating(), true);
+ assertIsVibrating(true);
mVibrator.cancel();
- assertEquals(mVibrator.isVibrating(), false);
+ assertIsVibrating(false);
}
@Test
public void testVibratorVibratesNoLongerThanDuration() {
final UiAutomation ui = InstrumentationRegistry.getInstrumentation().getUiAutomation();
ui.adoptShellPermissionIdentity("android.permission.ACCESS_VIBRATOR_STATE");
- assertEquals(mVibrator.isVibrating(), false);
+ assertIsVibrating(false);
mVibrator.vibrate(100);
SystemClock.sleep(150);
- assertEquals(mVibrator.isVibrating(), false);
+ assertIsVibrating(false);
}
@Test
@@ -179,7 +190,7 @@
.times(1)).onVibratorStateChanged(false);
mVibrator.vibrate(1000);
- assertEquals(mVibrator.isVibrating(), true);
+ assertIsVibrating(true);
verify(mListener1, timeout(CALLBACK_TIMEOUT_MILLIS)
.times(1)).onVibratorStateChanged(true);
@@ -193,7 +204,7 @@
mVibrator.removeVibratorStateListener(mListener2);
mVibrator.cancel();
- assertEquals(mVibrator.isVibrating(), false);
+ assertIsVibrating(false);
}
private static void sleep(long millis) {
diff --git a/tests/tests/packageinstaller/nopermission/AndroidTest.xml b/tests/tests/packageinstaller/nopermission/AndroidTest.xml
index 2229230..08ae8cc 100644
--- a/tests/tests/packageinstaller/nopermission/AndroidTest.xml
+++ b/tests/tests/packageinstaller/nopermission/AndroidTest.xml
@@ -36,6 +36,10 @@
<option name="test-file-name" value="CtsNoPermissionTestCases.apk" />
</target_preparer>
+ <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+ <option name="run-command" value="appops set android.packageinstaller.nopermission.cts REQUEST_INSTALL_PACKAGES allow" />
+ </target_preparer>
+
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="android.packageinstaller.nopermission.cts" />
<option name="runtime-hint" value="1m" />
diff --git a/tests/tests/packageinstaller/nopermission/src/android.packageinstaller.nopermission.cts/NoPermissionTests.kt b/tests/tests/packageinstaller/nopermission/src/android.packageinstaller.nopermission.cts/NoPermissionTests.kt
index 022d598..024d1ad 100644
--- a/tests/tests/packageinstaller/nopermission/src/android.packageinstaller.nopermission.cts/NoPermissionTests.kt
+++ b/tests/tests/packageinstaller/nopermission/src/android.packageinstaller.nopermission.cts/NoPermissionTests.kt
@@ -15,7 +15,6 @@
*/
package android.packageinstaller.nopermission.cts
-import android.app.AppOpsManager.MODE_ALLOWED
import android.app.PendingIntent
import android.content.BroadcastReceiver
import android.content.Context
@@ -33,7 +32,6 @@
import android.support.test.uiautomator.UiDevice
import android.support.test.uiautomator.Until
import androidx.core.content.FileProvider
-import com.android.compatibility.common.util.AppOpsUtils
import org.junit.After
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
@@ -54,7 +52,6 @@
private const val ACTION = "NoPermissionTests.install_cb"
private const val WAIT_FOR_UI_TIMEOUT = 5000L
-private const val APP_OP_STR = "REQUEST_INSTALL_PACKAGES"
@RunWith(AndroidJUnit4::class)
@MediumTest
@@ -92,12 +89,6 @@
}
@Before
- fun allowToInstallPackages() {
- // To make sure no other blocking dialogs appear
- AppOpsUtils.setOpMode(context.packageName, APP_OP_STR, MODE_ALLOWED)
- }
-
- @Before
fun registerInstallResultReceiver() {
context.registerReceiver(receiver, IntentFilter(ACTION))
}
diff --git a/tests/tests/permission/src/android/permission/cts/SecureElementPermissionTest.java b/tests/tests/permission/src/android/permission/cts/SecureElementPermissionTest.java
index cb857f0..0940d5f 100644
--- a/tests/tests/permission/src/android/permission/cts/SecureElementPermissionTest.java
+++ b/tests/tests/permission/src/android/permission/cts/SecureElementPermissionTest.java
@@ -35,7 +35,7 @@
public final class SecureElementPermissionTest {
// Needed because SECURE_ELEMENT_PRIVILEGED_PERMISSION is a systemapi
public static final String SECURE_ELEMENT_PRIVILEGED_PERMISSION =
- "android.permission.SECURE_ELEMENT_PRIVILEGED";
+ "android.permission.SECURE_ELEMENT_PRIVILEGED_OPERATION";
@Test
public void testSecureElementPrivilegedPermission() {
@@ -59,8 +59,8 @@
.collect(Collectors.toList());
if (nonSpecialPackages.size() > 1) {
- fail("Only one app on the device is allowed to hold the SECURE_ELEMENT_PRIVILEGED " +
- "permission.");
+ fail("Only one app on the device is allowed to hold the "
+ + "SECURE_ELEMENT_PRIVILEGED_OPERATION permission.");
}
}
}
diff --git a/tests/tests/permission2/res/raw/android_manifest.xml b/tests/tests/permission2/res/raw/android_manifest.xml
index 2cc1e81..7dcf97b 100644
--- a/tests/tests/permission2/res/raw/android_manifest.xml
+++ b/tests/tests/permission2/res/raw/android_manifest.xml
@@ -730,7 +730,7 @@
<!-- @SystemApi Allows accessing the messages on ICC
@hide Used internally. -->
<permission android:name="android.permission.ACCESS_MESSAGES_ON_ICC"
- android:protectionLevel="signature|telephony" />
+ android:protectionLevel="signature" />
<!-- Used for runtime permissions related to user's SMS messages. -->
<permission-group android:name="android.permission-group.SMS"
@@ -1102,13 +1102,12 @@
grants your app this permission. If you don't need this permission, be sure your <a
href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
targetSdkVersion}</a> is 4 or higher.
- <p>Protection level: dangerous
+ <p>Protection level: normal
-->
<permission android:name="android.permission.READ_PHONE_STATE"
- android:permissionGroup="android.permission-group.UNDEFINED"
android:label="@string/permlab_readPhoneState"
android:description="@string/permdesc_readPhoneState"
- android:protectionLevel="dangerous" />
+ android:protectionLevel="normal" />
<!-- Allows read access to the device's phone number(s). This is a subset of the capabilities
granted by {@link #READ_PHONE_STATE} but is exposed to instant applications.
@@ -1680,13 +1679,17 @@
<permission android:name="android.permission.NETWORK_FACTORY"
android:protectionLevel="signature" />
+ <!-- @SystemApi @hide Allows applications to access network stats provider -->
+ <permission android:name="android.permission.NETWORK_STATS_PROVIDER"
+ android:protectionLevel="signature" />
+
<!-- Allows Settings and SystemUI to call methods in Networking services
<p>Not for use by third-party or privileged applications.
@SystemApi
@hide This should only be used by Settings and SystemUI.
-->
<permission android:name="android.permission.NETWORK_SETTINGS"
- android:protectionLevel="signature|telephony" />
+ android:protectionLevel="signature" />
<!-- Allows holder to request bluetooth/wifi scan bypassing global "use location" setting and
location permissions.
@@ -1829,7 +1832,7 @@
<!-- @SystemApi Allows an internal user to use privileged SecureElement APIs.
@hide -->
- <permission android:name="android.permission.SECURE_ELEMENT_PRIVILEGED"
+ <permission android:name="android.permission.SECURE_ELEMENT_PRIVILEGED_OPERATION"
android:protectionLevel="signature|privileged" />
<!-- @deprecated This permission used to allow too broad access to sensitive methods and all its
@@ -2120,7 +2123,7 @@
<!-- @SystemApi Allows granting runtime permissions to telephony related components.
@hide -->
<permission android:name="android.permission.GRANT_RUNTIME_PERMISSIONS_TO_TELEPHONY_DEFAULTS"
- android:protectionLevel="signature|telephony" />
+ android:protectionLevel="signature" />
<!-- Allows modification of the telephony state - power on, mmi, etc.
Does not include placing calls.
@@ -2148,7 +2151,7 @@
<!-- @SystemApi Allows listen permission to always reported signal strength.
@hide Used internally. -->
<permission android:name="android.permission.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH"
- android:protectionLevel="signature|telephony" />
+ android:protectionLevel="signature" />
<!-- @SystemApi Protects the ability to register any PhoneAccount with
PhoneAccount#CAPABILITY_SIM_SUBSCRIPTION. This capability indicates that the PhoneAccount
@@ -2261,21 +2264,21 @@
<!-- Must be required by a telephony data service to ensure that only the
system can bind to it.
- <p>Protection level: signature|telephony
+ <p>Protection level: signature
@SystemApi
@hide
-->
<permission android:name="android.permission.BIND_TELEPHONY_DATA_SERVICE"
- android:protectionLevel="signature|telephony" />
+ android:protectionLevel="signature" />
<!-- Must be required by a NetworkService to ensure that only the
system can bind to it.
- <p>Protection level: signature|telephony
+ <p>Protection level: signature
@SystemApi
@hide
-->
<permission android:name="android.permission.BIND_TELEPHONY_NETWORK_SERVICE"
- android:protectionLevel="signature|telephony" />
+ android:protectionLevel="signature" />
<!-- @SystemApi Allows an application to manage embedded subscriptions (those on a eUICC)
through EuiccManager APIs.
@@ -2287,19 +2290,19 @@
<!-- @SystemApi Must be required by an EuiccService to ensure that only the system can bind to
it.
- <p>Protection level: signature|telephony
+ <p>Protection level: signature
@hide
-->
<permission android:name="android.permission.BIND_EUICC_SERVICE"
- android:protectionLevel="signature|telephony" />
+ android:protectionLevel="signature" />
<!-- Required for reading information about carrier apps from SystemConfigManager.
- <p>Protection level: signature|telephony
+ <p>Protection level: signature
@SystemApi
@hide
-->
<permission android:name="android.permission.READ_CARRIER_APP_INFO"
- android:protectionLevel="signature|telephony" />
+ android:protectionLevel="signature" />
<!-- ================================== -->
<!-- Permissions for sdcard interaction -->
@@ -2419,7 +2422,7 @@
types of interactions
@hide -->
<permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL"
- android:protectionLevel="signature|installer|telephony" />
+ android:protectionLevel="signature|installer" />
<uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
<!-- Allows interaction across profiles in the same profile group. -->
@@ -2657,7 +2660,7 @@
@hide
-->
<permission android:name="android.permission.SUGGEST_TELEPHONY_TIME_AND_ZONE"
- android:protectionLevel="signature|telephony" />
+ android:protectionLevel="signature" />
<!-- Allows applications like settings to suggest the user's manually chosen time / time zone.
<p>Not for use by third-party applications.
@@ -3081,7 +3084,7 @@
@hide -->
// TODO: remove telephony once decouple settings activity from phone process
<permission android:name="android.permission.STATUS_BAR_SERVICE"
- android:protectionLevel="signature|telephony" />
+ android:protectionLevel="signature" />
<!-- Allows an application to bind to third party quick settings tiles.
<p>Should only be requested by the System, should be required by
@@ -3139,7 +3142,7 @@
@hide
-->
<permission android:name="android.permission.INTERNAL_SYSTEM_WINDOW"
- android:protectionLevel="signature|telephony" />
+ android:protectionLevel="signature" />
<!-- @SystemApi Allows an application to use
{@link android.view.WindowManager.LayoutsParams#SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS}
@@ -3216,7 +3219,7 @@
@hide
-->
<permission android:name="android.permission.SET_ACTIVITY_WATCHER"
- android:protectionLevel="signature|telephony" />
+ android:protectionLevel="signature" />
<!-- @SystemApi Allows an application to call the activity manager shutdown() API
to put the higher-level system there into a shutdown state.
@@ -3740,6 +3743,12 @@
<permission android:name="android.permission.WHITELIST_RESTRICTED_PERMISSIONS"
android:protectionLevel="signature|installer" />
+ <!-- @SystemApi Allows an application to an exempt an app from having its permission be
+ auto-revoked when unused for an extended period of time.
+ @hide -->
+ <permission android:name="android.permission.WHITELIST_AUTO_REVOKE_PERMISSIONS"
+ android:protectionLevel="signature|installer" />
+
<!-- @hide Allows an application to observe permission changes. -->
<permission android:name="android.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS"
android:protectionLevel="signature|privileged" />
@@ -3753,7 +3762,7 @@
@hide
STOPSHIP b/145526313: Remove wellbeing protection flag from MANAGE_ROLE_HOLDERS. -->
<permission android:name="android.permission.MANAGE_ROLE_HOLDERS"
- android:protectionLevel="signature|installer|telephony|wellbeing" />
+ android:protectionLevel="signature|installer|wellbeing" />
<!-- @SystemApi Allows an application to observe role holder changes.
@hide -->
@@ -3990,7 +3999,7 @@
@hide
-->
<permission android:name="android.permission.DEVICE_POWER"
- android:protectionLevel="signature|telephony" />
+ android:protectionLevel="signature" />
<!-- Allows toggling battery saver on the system.
Superseded by DEVICE_POWER permission. @hide @SystemApi
@@ -4025,13 +4034,13 @@
<p>Not for use by third-party applications.
-->
<permission android:name="android.permission.BROADCAST_SMS"
- android:protectionLevel="signature|telephony" />
+ android:protectionLevel="signature" />
<!-- Allows an application to broadcast a WAP PUSH receipt notification.
<p>Not for use by third-party applications.
-->
<permission android:name="android.permission.BROADCAST_WAP_PUSH"
- android:protectionLevel="signature|telephony" />
+ android:protectionLevel="signature" />
<!-- @SystemApi Allows an application to broadcast privileged networking requests.
<p>Not for use by third-party applications.
@@ -4697,13 +4706,13 @@
{@link android.provider.BlockedNumberContract}.
@hide -->
<permission android:name="android.permission.READ_BLOCKED_NUMBERS"
- android:protectionLevel="signature|telephony" />
+ android:protectionLevel="signature" />
<!-- Allows the holder to write blocked numbers. See
{@link android.provider.BlockedNumberContract}.
@hide -->
<permission android:name="android.permission.WRITE_BLOCKED_NUMBERS"
- android:protectionLevel="signature|telephony" />
+ android:protectionLevel="signature" />
<!-- Must be required by an {@link android.service.vr.VrListenerService}, to ensure that only
the system can bind to it.
@@ -4863,7 +4872,7 @@
<!-- @hide Permission that allows configuring appops.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.MANAGE_APPOPS"
- android:protectionLevel="signature|telephony" />
+ android:protectionLevel="signature" />
<!-- @hide Permission that allows background clipboard access.
<p>Not for use by third-party applications. -->
diff --git a/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java b/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java
index 3024a49..82e2a2a 100644
--- a/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java
+++ b/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java
@@ -402,9 +402,6 @@
case "runtime": {
protectionLevel |= PermissionInfo.PROTECTION_FLAG_RUNTIME_ONLY;
} break;
- case "telephony": {
- protectionLevel |= PermissionInfo.PROTECTION_FLAG_TELEPHONY;
- } break;
case "companion": {
protectionLevel |= PermissionInfo.PROTECTION_FLAG_COMPANION;
} break;
diff --git a/tests/tests/permission2/src/android/permission2/cts/RuntimePermissionProperties.kt b/tests/tests/permission2/src/android/permission2/cts/RuntimePermissionProperties.kt
index 26c6cc8..96c04d5 100644
--- a/tests/tests/permission2/src/android/permission2/cts/RuntimePermissionProperties.kt
+++ b/tests/tests/permission2/src/android/permission2/cts/RuntimePermissionProperties.kt
@@ -34,7 +34,6 @@
import android.Manifest.permission.READ_CONTACTS
import android.Manifest.permission.READ_EXTERNAL_STORAGE
import android.Manifest.permission.READ_PHONE_NUMBERS
-import android.Manifest.permission.READ_PHONE_STATE
import android.Manifest.permission.READ_SMS
import android.Manifest.permission.RECEIVE_MMS
import android.Manifest.permission.RECEIVE_SMS
@@ -123,7 +122,7 @@
WRITE_CALENDAR, SEND_SMS, RECEIVE_SMS, READ_SMS, RECEIVE_MMS, RECEIVE_WAP_PUSH,
READ_CELL_BROADCASTS, READ_EXTERNAL_STORAGE, WRITE_EXTERNAL_STORAGE,
ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION, READ_CALL_LOG, WRITE_CALL_LOG,
- PROCESS_OUTGOING_CALLS, READ_PHONE_STATE, READ_PHONE_NUMBERS, CALL_PHONE,
+ PROCESS_OUTGOING_CALLS, READ_PHONE_NUMBERS, CALL_PHONE,
ADD_VOICEMAIL, USE_SIP, ANSWER_PHONE_CALLS, ACCEPT_HANDOVER, RECORD_AUDIO, CAMERA,
BODY_SENSORS)
diff --git a/tests/tests/permission3/src/android/permission3/cts/PermissionTest23.kt b/tests/tests/permission3/src/android/permission3/cts/PermissionTest23.kt
index cecdd38..8a61da7 100644
--- a/tests/tests/permission3/src/android/permission3/cts/PermissionTest23.kt
+++ b/tests/tests/permission3/src/android/permission3/cts/PermissionTest23.kt
@@ -16,6 +16,7 @@
package android.permission3.cts
+import androidx.test.filters.FlakyTest
import org.junit.Before
import org.junit.Test
@@ -228,6 +229,7 @@
assertAppHasPermission(android.Manifest.permission.READ_CONTACTS, false)
}
+ @FlakyTest
@Test
fun testNoResidualPermissionsOnUninstall() {
// Grant all permissions
@@ -309,7 +311,6 @@
android.Manifest.permission.WRITE_CALENDAR,
android.Manifest.permission.WRITE_CONTACTS,
android.Manifest.permission.READ_SMS,
- android.Manifest.permission.READ_PHONE_STATE,
android.Manifest.permission.READ_CALL_LOG,
android.Manifest.permission.WRITE_CALL_LOG,
android.Manifest.permission.ADD_VOICEMAIL,
diff --git a/tests/tests/provider/src/android/provider/cts/SettingsPanelTest.java b/tests/tests/provider/src/android/provider/cts/SettingsPanelTest.java
index 4c5f898..357e5e8 100644
--- a/tests/tests/provider/src/android/provider/cts/SettingsPanelTest.java
+++ b/tests/tests/provider/src/android/provider/cts/SettingsPanelTest.java
@@ -55,6 +55,13 @@
private static final String RESOURCE_DONE = "done";
private static final String RESOURCE_SEE_MORE = "see_more";
private static final String RESOURCE_TITLE = "panel_title";
+ private static final String RESOURCE_HEADER = "header_title";
+ private static final String TEST_PACKAGE_NAME = "test_package_name";
+ private static final String MEDIA_OUTPUT_TITLE_NAME = "Media";
+ private static final String ACTION_MEDIA_OUTPUT =
+ "com.android.settings.panel.action.MEDIA_OUTPUT";
+ private static final String EXTRA_PACKAGE_NAME =
+ "com.android.settings.panel.extra.PACKAGE_NAME";
private String mSettingsPackage;
private String mLauncherPackage;
@@ -120,6 +127,24 @@
}
@Test
+ public void mediaOutputPanel_withPackageNameExtra_correctPackage() {
+ launchMediaOutputPanel(TEST_PACKAGE_NAME);
+
+ String currentPackage = mDevice.getCurrentPackageName();
+
+ assertThat(currentPackage).isEqualTo(mSettingsPackage);
+ }
+
+ @Test
+ public void mediaOutputPanel_noPutPackageNameExtra_correctPackage() {
+ launchMediaOutputPanel(null /* packageName */);
+
+ String currentPackage = mDevice.getCurrentPackageName();
+
+ assertThat(currentPackage).isEqualTo(mSettingsPackage);
+ }
+
+ @Test
public void wifiPanel_correctPackage() {
launchWifiPanel();
@@ -129,6 +154,14 @@
}
@Test
+ public void mediaOutputPanel_correctTitle() {
+ launchMediaOutputPanel(TEST_PACKAGE_NAME);
+
+ final UiObject2 titleView = mDevice.findObject(By.res(mSettingsPackage, RESOURCE_HEADER));
+
+ assertThat(titleView.getText()).isEqualTo(MEDIA_OUTPUT_TITLE_NAME);
+ }
+ @Test
public void internetPanel_doneClosesPanel() {
// Launch panel
launchInternetPanel();
@@ -189,6 +222,22 @@
}
@Test
+ public void mediaOutputPanel_doneClosesPanel() {
+ // Launch panel
+ launchMediaOutputPanel(TEST_PACKAGE_NAME);
+ String currentPackage = mDevice.getCurrentPackageName();
+ assertThat(currentPackage).isEqualTo(mSettingsPackage);
+
+ // Click the done button
+ mDevice.findObject(By.res(currentPackage, RESOURCE_DONE)).click();
+ mDevice.wait(Until.hasObject(By.pkg(mLauncherPackage).depth(0)), TIMEOUT);
+
+ // Assert that we have left the panel
+ currentPackage = mDevice.getCurrentPackageName();
+ assertThat(currentPackage).isNotEqualTo(mSettingsPackage);
+ }
+
+ @Test
public void internetPanel_seeMoreButton_launchesIntoSettings() {
// Launch panel
launchInternetPanel();
@@ -261,6 +310,19 @@
assertThat(titleView).isNull();
}
+ @Test
+ public void mediaOutputPanel_seeMoreButton_doNothing() {
+ // Launch panel
+ launchMediaOutputPanel(TEST_PACKAGE_NAME);
+ String currentPackage = mDevice.getCurrentPackageName();
+ assertThat(currentPackage).isEqualTo(mSettingsPackage);
+
+ // Find the see more button
+ // SeeMoreIntent is null in MediaOutputPanel, so the see more button will not visible.
+ UiObject2 seeMoreView = mDevice.findObject(By.res(mSettingsPackage, RESOURCE_SEE_MORE));
+ assertThat(seeMoreView).isNull();
+ }
+
private void launchVolumePanel() {
launchPanel(Settings.Panel.ACTION_VOLUME);
}
@@ -269,6 +331,10 @@
launchPanel(Settings.Panel.ACTION_INTERNET_CONNECTIVITY);
}
+ private void launchMediaOutputPanel(String packageName) {
+ launchPanel(ACTION_MEDIA_OUTPUT, packageName);
+ }
+
private void launchNfcPanel() {
assumeTrue(mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_NFC));
launchPanel(Settings.Panel.ACTION_NFC);
@@ -280,6 +346,10 @@
}
private void launchPanel(String action) {
+ launchPanel(action, null /* packageName */);
+ }
+
+ private void launchPanel(String action, String packageName) {
// Start from the home screen
mDevice.pressHome();
mDevice.wait(Until.hasObject(By.pkg(mLauncherPackage).depth(0)), TIMEOUT);
@@ -287,6 +357,7 @@
Intent intent = new Intent(action);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_CLEAR_TASK); // Clear out any previous instances
+ intent.putExtra(EXTRA_PACKAGE_NAME, packageName);
mContext.startActivity(intent);
// Wait for the app to appear
diff --git a/tests/tests/security/src/android/security/cts/ActivityManagerTest.java b/tests/tests/security/src/android/security/cts/ActivityManagerTest.java
index 5a035dd..47730e1 100644
--- a/tests/tests/security/src/android/security/cts/ActivityManagerTest.java
+++ b/tests/tests/security/src/android/security/cts/ActivityManagerTest.java
@@ -15,11 +15,15 @@
*/
package android.security.cts;
+import android.app.ActivityManager;
import android.os.IBinder;
import android.platform.test.annotations.SecurityTest;
+import android.util.Log;
import junit.framework.TestCase;
+import java.lang.reflect.InvocationTargetException;
+
@SecurityTest
public class ActivityManagerTest extends TestCase {
@@ -44,4 +48,32 @@
// Patched devices should throw this exception
}
}
+
+ // b/144285917
+ @SecurityTest(minPatchLevel = "2020-05")
+ public void testActivityManager_attachNullApplication() {
+ SecurityException securityException = null;
+ Exception unexpectedException = null;
+ try {
+ final Object iam = ActivityManager.class.getDeclaredMethod("getService").invoke(null);
+ Class.forName("android.app.IActivityManager").getDeclaredMethod("attachApplication",
+ Class.forName("android.app.IApplicationThread"), long.class)
+ .invoke(iam, null /* thread */, 0 /* startSeq */);
+ } catch (SecurityException e) {
+ securityException = e;
+ } catch (InvocationTargetException e) {
+ if (e.getCause() instanceof SecurityException) {
+ securityException = (SecurityException) e.getCause();
+ } else {
+ unexpectedException = e;
+ }
+ } catch (Exception e) {
+ unexpectedException = e;
+ }
+ if (unexpectedException != null) {
+ Log.w("ActivityManagerTest", "Unexpected exception", unexpectedException);
+ }
+
+ assertNotNull("Expect SecurityException by attaching null application", securityException);
+ }
}
diff --git a/tests/tests/security/src/android/security/cts/CertificateTest.java b/tests/tests/security/src/android/security/cts/CertificateTest.java
index 54bacc9..2d88988 100644
--- a/tests/tests/security/src/android/security/cts/CertificateTest.java
+++ b/tests/tests/security/src/android/security/cts/CertificateTest.java
@@ -93,7 +93,7 @@
* For questions, comments, and code reviews please contact security@android.com.
*/
public void testNoRemovedWfaCertificates() throws Exception {
- if (!supportPasspoint()) {
+ if (!isWifiSupported()) {
return;
}
Set<String> expectedCertificates = new HashSet<>(
@@ -104,7 +104,7 @@
}
public void testNoAddedWfaCertificates() throws Exception {
- if (!supportPasspoint()) {
+ if (!isWifiSupported()) {
return;
}
Set<String> expectedCertificates = new HashSet<String>(
@@ -114,8 +114,8 @@
assertEquals("Unknown WFA CA certificates", Collections.EMPTY_SET, deviceWfaCertificates);
}
- private boolean supportPasspoint() {
- return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_PASSPOINT);
+ private boolean isWifiSupported() {
+ return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI);
}
private KeyStore createWfaKeyStore() throws CertificateException, IOException,
diff --git a/tests/tests/security/src/android/security/cts/StagefrightTest.java b/tests/tests/security/src/android/security/cts/StagefrightTest.java
index 6b122da..875bc91 100644
--- a/tests/tests/security/src/android/security/cts/StagefrightTest.java
+++ b/tests/tests/security/src/android/security/cts/StagefrightTest.java
@@ -111,17 +111,17 @@
@SecurityTest(minPatchLevel = "2016-08")
public void testStagefright_cve_2016_3829() throws Exception {
- doStagefrightTest(R.raw.cve_2016_3829, false);
+ doStagefrightTest(R.raw.cve_2016_3829, new CrashUtils.Config().checkMinAddress(false));
}
@SecurityTest(minPatchLevel = "2017-06")
public void testStagefright_cve_2017_0643() throws Exception {
- doStagefrightTest(R.raw.cve_2017_0643, false);
+ doStagefrightTest(R.raw.cve_2017_0643, new CrashUtils.Config().checkMinAddress(false));
}
@SecurityTest(minPatchLevel = "2017-08")
public void testStagefright_cve_2017_0728() throws Exception {
- doStagefrightTest(R.raw.cve_2017_0728, false);
+ doStagefrightTest(R.raw.cve_2017_0728, new CrashUtils.Config().checkMinAddress(false));
}
@SecurityTest(minPatchLevel = "2017-10")
@@ -161,7 +161,7 @@
@SecurityTest(minPatchLevel = "2017-06")
public void testStagefright_bug_35763994() throws Exception {
- doStagefrightTest(R.raw.bug_35763994, false);
+ doStagefrightTest(R.raw.bug_35763994, new CrashUtils.Config().checkMinAddress(false));
}
@SecurityTest(minPatchLevel = "2017-03")
@@ -171,7 +171,7 @@
@SecurityTest(minPatchLevel = "2017-07")
public void testStagefright_cve_2016_2507() throws Exception {
- doStagefrightTest(R.raw.cve_2016_2507, false);
+ doStagefrightTest(R.raw.cve_2016_2507, new CrashUtils.Config().checkMinAddress(false));
}
@SecurityTest(minPatchLevel = "2017-03")
@@ -266,13 +266,14 @@
@SecurityTest(minPatchLevel = "2017-02")
public void testStagefright_cve_2016_2429_b_27211885() throws Exception {
- doStagefrightTest(R.raw.cve_2016_2429_b_27211885, false);
+ doStagefrightTest(R.raw.cve_2016_2429_b_27211885,
+ new CrashUtils.Config().checkMinAddress(false));
}
@SecurityTest(minPatchLevel = "2017-08")
public void testStagefright_bug_34031018() throws Exception {
- doStagefrightTest(R.raw.bug_34031018_32bit, false);
- doStagefrightTest(R.raw.bug_34031018_64bit, false);
+ doStagefrightTest(R.raw.bug_34031018_32bit, new CrashUtils.Config().checkMinAddress(false));
+ doStagefrightTest(R.raw.bug_34031018_64bit, new CrashUtils.Config().checkMinAddress(false));
}
/***********************************************************
@@ -297,7 +298,8 @@
@SecurityTest(minPatchLevel = "2018-01")
public void testStagefright_cve_2017_0852_b_62815506() throws Exception {
- doStagefrightTest(R.raw.cve_2017_0852_b_62815506, false);
+ doStagefrightTest(R.raw.cve_2017_0852_b_62815506,
+ new CrashUtils.Config().checkMinAddress(false));
}
@SecurityTest(minPatchLevel = "2018-02")
@@ -323,7 +325,7 @@
@SecurityTest(minPatchLevel = "2016-10")
public void testStagefright_cve_2016_3920() throws Exception {
- doStagefrightTest(R.raw.cve_2016_3920, false);
+ doStagefrightTest(R.raw.cve_2016_3920, new CrashUtils.Config().checkMinAddress(false));
}
@SecurityTest(minPatchLevel = "2018-06")
@@ -338,7 +340,7 @@
@SecurityTest(minPatchLevel = "2016-08")
public void testStagefright_cve_2016_3821() throws Exception {
- doStagefrightTest(R.raw.cve_2016_3821, false);
+ doStagefrightTest(R.raw.cve_2016_3821, new CrashUtils.Config().checkMinAddress(false));
}
@SecurityTest(minPatchLevel = "2018-04")
@@ -358,12 +360,12 @@
@SecurityTest(minPatchLevel = "2017-09")
public void testStagefright_bug_38115076() throws Exception {
- doStagefrightTest(R.raw.bug_38115076, false);
+ doStagefrightTest(R.raw.bug_38115076, new CrashUtils.Config().checkMinAddress(false));
}
@SecurityTest(minPatchLevel = "2017-05")
public void testStagefright_bug_34618607() throws Exception {
- doStagefrightTest(R.raw.bug_34618607, false);
+ doStagefrightTest(R.raw.bug_34618607, new CrashUtils.Config().checkMinAddress(false));
}
@SecurityTest(minPatchLevel = "2018-02")
@@ -388,13 +390,14 @@
@SecurityTest(minPatchLevel = "2017-05")
public void testStagefright_cve_2017_0600() throws Exception {
- doStagefrightTest(R.raw.cve_2017_0600, false);
+ doStagefrightTest(R.raw.cve_2017_0600, new CrashUtils.Config().checkMinAddress(false));
}
@SecurityTest(minPatchLevel = "2017-08")
public void testBug_38014992() throws Exception {
int[] frameSizes = getFrameSizes(R.raw.bug_38014992_framelen);
- doStagefrightTestRawBlob(R.raw.bug_38014992_avc, "video/avc", 640, 480, frameSizes, false);
+ doStagefrightTestRawBlob(R.raw.bug_38014992_avc, "video/avc", 640, 480, frameSizes,
+ new CrashUtils.Config().checkMinAddress(false));
}
@SecurityTest(minPatchLevel = "2017-07")
@@ -424,7 +427,8 @@
@SecurityTest(minPatchLevel = "2017-03")
public void testBug_33387820() throws Exception {
int[] frameSizes = {45, 3202, 430, 2526};
- doStagefrightTestRawBlob(R.raw.bug_33387820_avc, "video/avc", 320, 240, frameSizes, false);
+ doStagefrightTestRawBlob(R.raw.bug_33387820_avc, "video/avc", 320, 240, frameSizes,
+ new CrashUtils.Config().checkMinAddress(false));
}
@SecurityTest(minPatchLevel = "2017-07")
@@ -461,13 +465,15 @@
public void testBug_28816956() throws Exception {
int[] frameSizes = getFrameSizes(R.raw.bug_28816956_framelen);
doStagefrightTestRawBlob(
- R.raw.bug_28816956_hevc, "video/hevc", 352, 288, frameSizes, false);
+ R.raw.bug_28816956_hevc, "video/hevc", 352, 288, frameSizes,
+ new CrashUtils.Config().checkMinAddress(false));
}
@SecurityTest(minPatchLevel = "2017-03")
public void testBug_33818500() throws Exception {
int[] frameSizes = getFrameSizes(R.raw.bug_33818500_framelen);
- doStagefrightTestRawBlob(R.raw.bug_33818500_avc, "video/avc", 64, 32, frameSizes, false);
+ doStagefrightTestRawBlob(R.raw.bug_33818500_avc, "video/avc", 64, 32, frameSizes,
+ new CrashUtils.Config().checkMinAddress(false));
}
@SecurityTest(minPatchLevel = "2018-01")
@@ -496,7 +502,7 @@
@SecurityTest(minPatchLevel = "2017-05")
public void testStagefright_cve_2017_0599() throws Exception {
- doStagefrightTest(R.raw.cve_2017_0599, false);
+ doStagefrightTest(R.raw.cve_2017_0599, new CrashUtils.Config().checkMinAddress(false));
}
@SecurityTest(minPatchLevel = "2017-09")
@@ -526,7 +532,7 @@
@SecurityTest(minPatchLevel = "2017-09")
public void testStagefright_cve_2016_6712() throws Exception {
- doStagefrightTest(R.raw.cve_2016_6712, false);
+ doStagefrightTest(R.raw.cve_2016_6712, new CrashUtils.Config().checkMinAddress(false));
}
@SecurityTest(minPatchLevel = "2017-04")
@@ -552,12 +558,12 @@
@SecurityTest(minPatchLevel = "2017-06")
public void testStagefright_bug_33818508() throws Exception {
- doStagefrightTest(R.raw.bug_33818508, false);
+ doStagefrightTest(R.raw.bug_33818508, new CrashUtils.Config().checkMinAddress(false));
}
@SecurityTest(minPatchLevel = "2017-08")
public void testStagefright_bug_32873375() throws Exception {
- doStagefrightTest(R.raw.bug_32873375, false);
+ doStagefrightTest(R.raw.bug_32873375, new CrashUtils.Config().checkMinAddress(false));
}
@SecurityTest(minPatchLevel = "2018-02")
@@ -620,7 +626,7 @@
@SecurityTest(minPatchLevel = "2016-06")
public void testStagefright_cve_2016_2428() throws Exception {
- doStagefrightTest(R.raw.cve_2016_2428, false);
+ doStagefrightTest(R.raw.cve_2016_2428, new CrashUtils.Config().checkMinAddress(false));
}
@SecurityTest(minPatchLevel = "2016-07")
@@ -658,7 +664,8 @@
@Override
public void run() {
try {
- doStagefrightTestMediaCodec(tempFile.getAbsolutePath(), false);
+ doStagefrightTestMediaCodec(tempFile.getAbsolutePath(),
+ new CrashUtils.Config().checkMinAddress(false));
} catch (Exception | AssertionError e) {
if (!tempFile.delete()) {
Log.e(TAG, "Failed to delete temporary PoC file");
@@ -683,7 +690,7 @@
@SecurityTest(minPatchLevel = "2017-06")
public void testStagefright_bug_32322258() throws Exception {
- doStagefrightTest(R.raw.bug_32322258, false);
+ doStagefrightTest(R.raw.bug_32322258, new CrashUtils.Config().checkMinAddress(false));
}
@SecurityTest(minPatchLevel = "2015-10")
@@ -713,7 +720,8 @@
@SecurityTest(minPatchLevel = "2015-10")
public void testStagefright_cve_2015_3862_b_22954006() throws Exception {
- doStagefrightTest(R.raw.cve_2015_3862_b_22954006, false);
+ doStagefrightTest(R.raw.cve_2015_3862_b_22954006,
+ new CrashUtils.Config().checkMinAddress(false));
}
@SecurityTest(minPatchLevel = "2015-10")
@@ -778,12 +786,13 @@
@SecurityTest(minPatchLevel = "2016-07")
public void testStagefright_cve_2016_3755() throws Exception {
- doStagefrightTest(R.raw.cve_2016_3755, false);
+ doStagefrightTest(R.raw.cve_2016_3755, new CrashUtils.Config().checkMinAddress(false));
}
@SecurityTest(minPatchLevel = "2016-09")
public void testStagefright_cve_2016_3878_b_29493002() throws Exception {
- doStagefrightTest(R.raw.cve_2016_3878_b_29493002, false);
+ doStagefrightTest(R.raw.cve_2016_3878_b_29493002,
+ new CrashUtils.Config().checkMinAddress(false));
}
@SecurityTest(minPatchLevel = "2017-08")
@@ -803,12 +812,12 @@
@SecurityTest(minPatchLevel = "2016-06")
public void testStagefright_bug_27855419_CVE_2016_2463() throws Exception {
- doStagefrightTest(R.raw.bug_27855419, false);
+ doStagefrightTest(R.raw.bug_27855419, new CrashUtils.Config().checkMinAddress(false));
}
@SecurityTest(minPatchLevel = "2015-11")
public void testStagefright_bug_19779574() throws Exception {
- doStagefrightTest(R.raw.bug_19779574, false);
+ doStagefrightTest(R.raw.bug_19779574, new CrashUtils.Config().checkMinAddress(false));
}
/***********************************************************
@@ -823,7 +832,7 @@
@SecurityTest(minPatchLevel = "2017-07")
public void testStagefright_bug_36279112() throws Exception {
- doStagefrightTest(R.raw.bug_36279112, false);
+ doStagefrightTest(R.raw.bug_36279112, new CrashUtils.Config().checkMinAddress(false));
}
@SecurityTest(minPatchLevel = "2017-06")
@@ -905,7 +914,8 @@
};
server.start();
String uri = "http://127.0.0.1:8080/bug_68342866.m3u8";
- final MediaPlayerCrashListener mpcl = new MediaPlayerCrashListener(false);
+ final MediaPlayerCrashListener mpcl =
+ new MediaPlayerCrashListener(new CrashUtils.Config().checkMinAddress(false));
LooperThread t = new LooperThread(new Runnable() {
@Override
public void run() {
@@ -1071,7 +1081,7 @@
@SecurityTest(minPatchLevel = "2016-12")
public void testStagefright_cve_2016_6764() throws Exception {
- doStagefrightTest(R.raw.cve_2016_6764, false);
+ doStagefrightTest(R.raw.cve_2016_6764, new CrashUtils.Config().checkMinAddress(false));
}
@SecurityTest(minPatchLevel = "2018-01")
@@ -1081,7 +1091,7 @@
@SecurityTest(minPatchLevel = "2017-06")
public void testStagefright_bug_35467107() throws Exception {
- doStagefrightTest(R.raw.bug_35467107, false);
+ doStagefrightTest(R.raw.bug_35467107, new CrashUtils.Config().checkMinAddress(false));
}
/***********************************************************
@@ -1217,12 +1227,12 @@
@SecurityTest(minPatchLevel = "2016-12")
public void testStagefright_cve_2016_6765() throws Exception {
- doStagefrightTest(R.raw.cve_2016_6765, false);
+ doStagefrightTest(R.raw.cve_2016_6765, new CrashUtils.Config().checkMinAddress(false));
}
@SecurityTest(minPatchLevel = "2016-07")
public void testStagefright_cve_2016_2508() throws Exception {
- doStagefrightTest(R.raw.cve_2016_2508, false);
+ doStagefrightTest(R.raw.cve_2016_2508, new CrashUtils.Config().checkMinAddress(false));
}
@SecurityTest(minPatchLevel = "2016-11")
@@ -1242,19 +1252,19 @@
@SecurityTest(minPatchLevel = "2016-09")
public void testStagefright_cve_2016_3879() throws Exception {
- doStagefrightTest(R.raw.cve_2016_3879, false);
+ doStagefrightTest(R.raw.cve_2016_3879, new CrashUtils.Config().checkMinAddress(false));
}
private void doStagefrightTest(final int rid) throws Exception {
- doStagefrightTest(rid, true); // check addresss by default
+ doStagefrightTest(rid, null);
}
- private void doStagefrightTest(final int rid, boolean checkMinCrashAddress) throws Exception {
+ private void doStagefrightTest(final int rid, CrashUtils.Config config) throws Exception {
NetworkSecurityPolicy policy = NetworkSecurityPolicy.getInstance();
policy.setCleartextTrafficPermitted(true);
- doStagefrightTestMediaPlayer(rid, checkMinCrashAddress);
- doStagefrightTestMediaCodec(rid, checkMinCrashAddress);
- doStagefrightTestMediaMetadataRetriever(rid, checkMinCrashAddress);
+ doStagefrightTestMediaPlayer(rid, config);
+ doStagefrightTestMediaCodec(rid, config);
+ doStagefrightTestMediaMetadataRetriever(rid, config);
Context context = getInstrumentation().getContext();
CtsTestServer server = null;
@@ -1270,10 +1280,10 @@
String rname = resources.getResourceEntryName(rid);
String url = server.getAssetUrl("raw/" + rname);
verifyServer(rid, url);
- doStagefrightTestMediaPlayer(url, checkMinCrashAddress);
- doStagefrightTestMediaCodec(url, checkMinCrashAddress);
- doStagefrightTestMediaMetadataRetriever(url, checkMinCrashAddress);
policy.setCleartextTrafficPermitted(false);
+ doStagefrightTestMediaPlayer(url, config);
+ doStagefrightTestMediaCodec(url, config);
+ doStagefrightTestMediaMetadataRetriever(url, config);
server.shutdown();
}
@@ -1303,16 +1313,16 @@
}
private void doStagefrightTest(final int rid, int timeout) throws Exception {
- doStagefrightTest(rid, true, timeout); // check crash address by default
+ doStagefrightTest(rid, null, timeout);
}
private void doStagefrightTest(
- final int rid, boolean checkMinCrashAddress, int timeout) throws Exception {
+ final int rid, CrashUtils.Config config, int timeout) throws Exception {
runWithTimeout(new Runnable() {
@Override
public void run() {
try {
- doStagefrightTest(rid, checkMinCrashAddress);
+ doStagefrightTest(rid, config);
} catch (Exception e) {
fail(e.toString());
}
@@ -1321,12 +1331,12 @@
}
private void doStagefrightTestANR(final int rid) throws Exception {
- doStagefrightTestANR(rid, true); // check crash address by default
+ doStagefrightTestANR(rid, null);
}
private void doStagefrightTestANR(
- final int rid, boolean checkMinCrashAddress) throws Exception {
- doStagefrightTestMediaPlayerANR(rid, null);
+ final int rid, CrashUtils.Config config) throws Exception {
+ doStagefrightTestMediaPlayerANR(rid, null, config);
}
public JSONArray getCrashReport(String testname, long timeout)
@@ -1360,7 +1370,7 @@
MediaPlayer.OnPreparedListener,
MediaPlayer.OnCompletionListener {
- boolean checkMinAddress = true;
+ CrashUtils.Config config;
private final Pattern[] validProcessPatterns = {
Pattern.compile("adsprpcd"),
@@ -1384,10 +1394,16 @@
};
MediaPlayerCrashListener() {
+ this(null);
}
- MediaPlayerCrashListener(boolean checkMinAddress) {
- this.checkMinAddress = checkMinAddress;
+ MediaPlayerCrashListener(CrashUtils.Config config) {
+ if (config == null) {
+ config = new CrashUtils.Config();
+ }
+ // if a different process is needed for a test, it should be added to the main list.
+ config.setProcessPatterns(validProcessPatterns);
+ this.config = config;
}
@Override
@@ -1435,8 +1451,7 @@
if (crashes == null) {
Log.e(TAG, "Crash results not found for test " + getName());
return what;
- } else if (CrashUtils.securityCrashDetected(
- crashes, checkMinAddress, validProcessPatterns)) {
+ } else if (CrashUtils.securityCrashDetected(crashes, config)) {
return what;
} else {
Log.i(TAG, "Crash ignored due to no security crash found for test " +
@@ -1484,21 +1499,21 @@
}
private void doStagefrightTestMediaPlayer(final int rid) throws Exception {
- doStagefrightTestMediaPlayer(rid, true); // check crash address by default
+ doStagefrightTestMediaPlayer(rid, null, null);
}
private void doStagefrightTestMediaPlayer(
- final int rid, boolean checkMinCrashAddress) throws Exception {
- doStagefrightTestMediaPlayer(rid, null, checkMinCrashAddress);
+ final int rid, CrashUtils.Config config) throws Exception {
+ doStagefrightTestMediaPlayer(rid, null, config);
}
private void doStagefrightTestMediaPlayer(final String url) throws Exception {
- doStagefrightTestMediaPlayer(url, true); // check crash address by default
+ doStagefrightTestMediaPlayer(url, null);
}
private void doStagefrightTestMediaPlayer(
- final String url, boolean checkMinCrashAddress) throws Exception {
- doStagefrightTestMediaPlayer(-1, url, checkMinCrashAddress);
+ final String url, CrashUtils.Config config) throws Exception {
+ doStagefrightTestMediaPlayer(-1, url, config);
}
private void closeQuietly(AutoCloseable closeable) {
@@ -1513,17 +1528,17 @@
}
private void doStagefrightTestMediaPlayer(final int rid, final String uri) throws Exception {
- doStagefrightTestMediaPlayer(rid, uri, true); // check crash address by default
+ doStagefrightTestMediaPlayer(rid, uri, null);
}
private void doStagefrightTestMediaPlayer(final int rid, final String uri,
- boolean checkMinCrashAddress) throws Exception {
+ CrashUtils.Config config) throws Exception {
String name = uri != null ? uri :
getInstrumentation().getContext().getResources().getResourceEntryName(rid);
Log.i(TAG, "start mediaplayer test for: " + name);
- final MediaPlayerCrashListener mpcl = new MediaPlayerCrashListener(checkMinCrashAddress);
+ final MediaPlayerCrashListener mpcl = new MediaPlayerCrashListener(config);
LooperThread t = new LooperThread(new Runnable() {
@Override
@@ -1644,31 +1659,31 @@
}
private void doStagefrightTestMediaCodec(final int rid) throws Exception {
- doStagefrightTestMediaCodec(rid, true); // check crash address by default
+ doStagefrightTestMediaCodec(rid, null, null);
}
private void doStagefrightTestMediaCodec(
- final int rid, boolean checkMinCrashAddress) throws Exception {
- doStagefrightTestMediaCodec(rid, null, checkMinCrashAddress);
+ final int rid, CrashUtils.Config config) throws Exception {
+ doStagefrightTestMediaCodec(rid, null, config);
}
private void doStagefrightTestMediaCodec(final String url) throws Exception {
- doStagefrightTestMediaCodec(url, true); // check crash address by default
+ doStagefrightTestMediaCodec(url, null);
}
private void doStagefrightTestMediaCodec(
- final String url, boolean checkMinCrashAddress) throws Exception {
- doStagefrightTestMediaCodec(-1, url, checkMinCrashAddress);
+ final String url, CrashUtils.Config config) throws Exception {
+ doStagefrightTestMediaCodec(-1, url, config);
}
private void doStagefrightTestMediaCodec(final int rid, final String url) throws Exception {
- doStagefrightTestMediaCodec(rid, url, true); // check crash address by default
+ doStagefrightTestMediaCodec(rid, url, null);
}
private void doStagefrightTestMediaCodec(
- final int rid, final String url, boolean checkMinCrashAddress) throws Exception {
+ final int rid, final String url, CrashUtils.Config config) throws Exception {
- final MediaPlayerCrashListener mpcl = new MediaPlayerCrashListener(checkMinCrashAddress);
+ final MediaPlayerCrashListener mpcl = new MediaPlayerCrashListener(config);
LooperThread thr = new LooperThread(new Runnable() {
@Override
@@ -1826,31 +1841,31 @@
}
private void doStagefrightTestMediaMetadataRetriever(final int rid) throws Exception {
- doStagefrightTestMediaMetadataRetriever(rid, true); // check crash address by default
+ doStagefrightTestMediaMetadataRetriever(rid, null, null);
}
private void doStagefrightTestMediaMetadataRetriever(
- final int rid, boolean checkMinCrashAddress) throws Exception {
- doStagefrightTestMediaMetadataRetriever(rid, null, checkMinCrashAddress);
+ final int rid, CrashUtils.Config config) throws Exception {
+ doStagefrightTestMediaMetadataRetriever(rid, null, config);
}
private void doStagefrightTestMediaMetadataRetriever(final String url) throws Exception {
- doStagefrightTestMediaMetadataRetriever(url, true); // check crash address by default
+ doStagefrightTestMediaMetadataRetriever(url, null);
}
private void doStagefrightTestMediaMetadataRetriever(
- final String url, boolean checkMinCrashAddress) throws Exception {
- doStagefrightTestMediaMetadataRetriever(-1, url, checkMinCrashAddress);
+ final String url, CrashUtils.Config config) throws Exception {
+ doStagefrightTestMediaMetadataRetriever(-1, url, config);
}
private void doStagefrightTestMediaMetadataRetriever(
final int rid, final String url) throws Exception {
- doStagefrightTestMediaMetadataRetriever(rid, url, true); // check crash address by default
+ doStagefrightTestMediaMetadataRetriever(rid, url, null);
}
private void doStagefrightTestMediaMetadataRetriever(
- final int rid, final String url, boolean checkMinCrashAddress) throws Exception {
+ final int rid, final String url, CrashUtils.Config config) throws Exception {
- final MediaPlayerCrashListener mpcl = new MediaPlayerCrashListener(checkMinCrashAddress);
+ final MediaPlayerCrashListener mpcl = new MediaPlayerCrashListener(config);
LooperThread thr = new LooperThread(new Runnable() {
@Override
@@ -1925,12 +1940,14 @@
@SecurityTest(minPatchLevel = "2017-08")
public void testBug36816007() throws Exception {
- doStagefrightTestRawBlob(R.raw.bug_36816007, "video/avc", 320, 240, false);
+ doStagefrightTestRawBlob(R.raw.bug_36816007, "video/avc", 320, 240,
+ new CrashUtils.Config().checkMinAddress(false));
}
@SecurityTest(minPatchLevel = "2017-05")
public void testBug36895511() throws Exception {
- doStagefrightTestRawBlob(R.raw.bug_36895511, "video/hevc", 320, 240, false);
+ doStagefrightTestRawBlob(R.raw.bug_36895511, "video/hevc", 320, 240,
+ new CrashUtils.Config().checkMinAddress(false));
}
@SecurityTest(minPatchLevel = "2017-11")
@@ -1960,7 +1977,8 @@
@SecurityTest(minPatchLevel = "2018-04")
public void testBug_70897394() throws Exception {
- doStagefrightTestRawBlob(R.raw.bug_70897394_avc, "video/avc", 320, 240, false);
+ doStagefrightTestRawBlob(R.raw.bug_70897394_avc, "video/avc", 320, 240,
+ new CrashUtils.Config().checkMinAddress(false));
}
@SecurityTest(minPatchLevel = "Unknown")
@@ -2032,14 +2050,13 @@
private void doStagefrightTestRawBlob(
int rid, String mime, int initWidth, int initHeight) throws Exception {
- // check crash address by default
- doStagefrightTestRawBlob(rid, mime, initWidth, initHeight, true);
+ doStagefrightTestRawBlob(rid, mime, initWidth, initHeight, new CrashUtils.Config());
}
private void doStagefrightTestRawBlob(int rid, String mime, int initWidth, int initHeight,
- boolean checkMinCrashAddress) throws Exception {
+ CrashUtils.Config config) throws Exception {
- final MediaPlayerCrashListener mpcl = new MediaPlayerCrashListener(checkMinCrashAddress);
+ final MediaPlayerCrashListener mpcl = new MediaPlayerCrashListener(config);
final Context context = getInstrumentation().getContext();
final Resources resources = context.getResources();
@@ -2154,13 +2171,13 @@
private void doStagefrightTestRawBlob(int rid, String mime, int initWidth, int initHeight,
int frameSizes[]) throws Exception {
// check crash address by default
- doStagefrightTestRawBlob(rid, mime, initWidth, initHeight, frameSizes, true);
+ doStagefrightTestRawBlob(rid, mime, initWidth, initHeight, frameSizes, new CrashUtils.Config());
}
private void doStagefrightTestRawBlob(int rid, String mime, int initWidth, int initHeight,
- int frameSizes[], boolean checkMinCrashAddress) throws Exception {
+ int frameSizes[], CrashUtils.Config config) throws Exception {
- final MediaPlayerCrashListener mpcl = new MediaPlayerCrashListener(checkMinCrashAddress);
+ final MediaPlayerCrashListener mpcl = new MediaPlayerCrashListener(config);
final Context context = getInstrumentation().getContext();
final Resources resources = context.getResources();
@@ -2294,16 +2311,16 @@
}
private void doStagefrightTestMediaPlayerANR(final int rid, final String uri) throws Exception {
- doStagefrightTestMediaPlayerANR(rid, uri, true); // check crash address by default
+ doStagefrightTestMediaPlayerANR(rid, uri, null);
}
private void doStagefrightTestMediaPlayerANR(final int rid, final String uri,
- boolean checkMinCrashAddress) throws Exception {
+ CrashUtils.Config config) throws Exception {
String name = uri != null ? uri :
getInstrumentation().getContext().getResources().getResourceEntryName(rid);
Log.i(TAG, "start mediaplayerANR test for: " + name);
- final MediaPlayerCrashListener mpl = new MediaPlayerCrashListener(checkMinCrashAddress);
+ final MediaPlayerCrashListener mpl = new MediaPlayerCrashListener(config);
LooperThread t = new LooperThread(new Runnable() {
@Override
@@ -2347,12 +2364,12 @@
}
private void doStagefrightTestExtractorSeek(final int rid, final long offset) throws Exception {
- doStagefrightTestExtractorSeek(rid, offset, true); // check crash address by default
+ doStagefrightTestExtractorSeek(rid, offset, new CrashUtils.Config()); // check crash address by default
}
private void doStagefrightTestExtractorSeek(final int rid, final long offset,
- boolean checkMinCrashAddress) throws Exception {
- final MediaPlayerCrashListener mpcl = new MediaPlayerCrashListener(checkMinCrashAddress);
+ CrashUtils.Config config) throws Exception {
+ final MediaPlayerCrashListener mpcl = new MediaPlayerCrashListener(config);
LooperThread thr = new LooperThread(new Runnable() {
@Override
public void run() {
diff --git a/tests/tests/sharesheet/AndroidManifest.xml b/tests/tests/sharesheet/AndroidManifest.xml
index c99b38a..e501caf 100644
--- a/tests/tests/sharesheet/AndroidManifest.xml
+++ b/tests/tests/sharesheet/AndroidManifest.xml
@@ -24,17 +24,45 @@
failure -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
- <application android:requestLegacyExternalStorage="true">
- <uses-library android:name="android.test.runner" />
+ <application
+ android:requestLegacyExternalStorage="true"
+ android:label="@string/test_app_label">
- <!-- Add activities, services, etc here to test sharesheet API -->
-
- <activity android:name="CtsSharesheetDeviceActivity" >
+ <uses-library android:name="android.test.runner" />
+
+ <activity android:name=".CtsSharesheetDeviceActivity">
+
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
+
+ <intent-filter>
+ <action android:name="android.intent.action.SEND" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <data android:mimeType="test/cts" />
+ </intent-filter>
+
+ <!-- Used to provide Sharing Shortcuts -->
+ <meta-data android:name="android.app.shortcuts"
+ android:resource="@xml/shortcuts"/>
+
+ <meta-data android:name="android.service.chooser.chooser_target_service"
+ android:value=".CtsSharesheetChooserTargetService"/>
+
</activity>
+
+ <service android:name=".CtsSharesheetChooserTargetService"
+ android:permission="android.permission.BIND_CHOOSER_TARGET_SERVICE">
+ <intent-filter>
+ <action android:name="android.service.chooser.ChooserTargetService" />
+ </intent-filter>
+ </service>
+
+ <activity-alias android:name=".ExtraInitialIntentTestActivity"
+ android:label="@string/test_extra_initial_intents_label"
+ android:targetActivity=".CtsSharesheetDeviceActivity"/>
+
</application>
<instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
diff --git a/tests/tests/sharesheet/AndroidTest.xml b/tests/tests/sharesheet/AndroidTest.xml
index bac02d8..59a4c97 100644
--- a/tests/tests/sharesheet/AndroidTest.xml
+++ b/tests/tests/sharesheet/AndroidTest.xml
@@ -17,7 +17,8 @@
<configuration description="Config for CTS Sharesheet test cases">
<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" />
+ <!-- Instant apps can't access ShortcutManager -->
+ <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
<option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
<option name="not-shardable" value="true" />
@@ -25,6 +26,9 @@
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
<option name="test-file-name" value="CtsSharesheetTestCases.apk" />
+ <option name="test-file-name" value="CtsSharesheetActivityLabelTester.apk" />
+ <option name="test-file-name" value="CtsSharesheetIntentFilterLabelTester.apk" />
+ <option name="test-file-name" value="CtsSharesheetExcludeTester.apk" />
</target_preparer>
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
@@ -38,4 +42,5 @@
<option name="collect-on-run-ended-only" value="true" />
<option name="clean-up" value="false" />
</metrics_collector>
+
</configuration>
diff --git a/tests/tests/sharesheet/OWNERS b/tests/tests/sharesheet/OWNERS
index 47f9b3b..8bea7af 100644
--- a/tests/tests/sharesheet/OWNERS
+++ b/tests/tests/sharesheet/OWNERS
@@ -2,4 +2,5 @@
digman@google.com
asc@google.com
dsandler@google.com
-mpietal@google.com
\ No newline at end of file
+mpietal@google.com
+arangelov@google.com
\ No newline at end of file
diff --git a/tests/tests/sharesheet/packages/Android.bp b/tests/tests/sharesheet/packages/Android.bp
new file mode 100644
index 0000000..12a6838
--- /dev/null
+++ b/tests/tests/sharesheet/packages/Android.bp
@@ -0,0 +1,64 @@
+// Copyright (C) 2020 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_helper_app {
+ name: "CtsSharesheetActivityLabelTester",
+ defaults: ["cts_defaults"],
+ srcs: ["packages/src/**/*.java"],
+ // tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ ],
+ aaptflags: [
+ "--rename-manifest-package",
+ "android.sharesheet.cts.packages.activitylabeltester",
+ ],
+ manifest: "AndroidManifest-ActivityLabelTester.xml",
+}
+
+android_test_helper_app {
+ name: "CtsSharesheetIntentFilterLabelTester",
+ defaults: ["cts_defaults"],
+ srcs: ["packages/src/**/*.java"],
+ // tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ ],
+ aaptflags: [
+ "--rename-manifest-package",
+ "android.sharesheet.cts.packages.intentfilterlabeltester",
+ ],
+ manifest: "AndroidManifest-IntentFilterLabelTester.xml",
+}
+
+android_test_helper_app {
+ name: "CtsSharesheetExcludeTester",
+ defaults: ["cts_defaults"],
+ srcs: ["packages/src/**/*.java"],
+ // tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ ],
+ aaptflags: [
+ "--rename-manifest-package",
+ "android.sharesheet.cts.packages.excludetester",
+ ],
+ manifest: "AndroidManifest-ExcludeTester.xml",
+}
\ No newline at end of file
diff --git a/tests/tests/sharesheet/packages/AndroidManifest-ActivityLabelTester.xml b/tests/tests/sharesheet/packages/AndroidManifest-ActivityLabelTester.xml
new file mode 100644
index 0000000..9da4a37
--- /dev/null
+++ b/tests/tests/sharesheet/packages/AndroidManifest-ActivityLabelTester.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2020 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.sharesheet.cts.packages">
+
+ <application android:label="App A">
+
+ <activity android:name=".LabelTestActivity" android:label="Activity A">
+
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+
+ <intent-filter>
+ <action android:name="android.intent.action.SEND" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <data android:mimeType="test/cts" />
+ </intent-filter>
+
+ </activity>
+
+ </application>
+
+</manifest>
+
diff --git a/tests/tests/sharesheet/packages/AndroidManifest-ExcludeTester.xml b/tests/tests/sharesheet/packages/AndroidManifest-ExcludeTester.xml
new file mode 100644
index 0000000..ca2e79e
--- /dev/null
+++ b/tests/tests/sharesheet/packages/AndroidManifest-ExcludeTester.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 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.sharesheet.cts.packages">
+
+ <application android:label="Bl Label">
+
+ <activity android:name=".LabelTestActivity">
+
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+
+ <intent-filter>
+ <action android:name="android.intent.action.SEND" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <data android:mimeType="test/cts" />
+ </intent-filter>
+
+ </activity>
+
+ </application>
+
+</manifest>
+
diff --git a/tests/tests/sharesheet/packages/AndroidManifest-IntentFilterLabelTester.xml b/tests/tests/sharesheet/packages/AndroidManifest-IntentFilterLabelTester.xml
new file mode 100644
index 0000000..1169b49
--- /dev/null
+++ b/tests/tests/sharesheet/packages/AndroidManifest-IntentFilterLabelTester.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 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.sharesheet.cts.packages">
+
+ <application android:label="App If">
+
+ <activity android:name=".LabelTestActivity" android:label="Activity If">
+
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+
+ <intent-filter android:label="IntentFilter If">
+ <action android:name="android.intent.action.SEND" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <data android:mimeType="test/cts" />
+ </intent-filter>
+
+ </activity>
+
+ </application>
+
+</manifest>
+
diff --git a/tests/tests/sharesheet/packages/src/android/sharesheet/cts/packages/LabelTestActivity.java b/tests/tests/sharesheet/packages/src/android/sharesheet/cts/packages/LabelTestActivity.java
new file mode 100644
index 0000000..564c269
--- /dev/null
+++ b/tests/tests/sharesheet/packages/src/android/sharesheet/cts/packages/LabelTestActivity.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2020 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.sharesheet.cts.packages;
+
+import android.app.Activity;
+import android.content.Context;
+import android.os.Bundle;
+
+import java.lang.Override;
+
+public class LabelTestActivity extends Activity {
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ // This activity may be opened to ensure click behavior functions properly.
+ // To ensure test repeatability do not stay open.
+ finish();
+ }
+}
\ No newline at end of file
diff --git a/tests/tests/sharesheet/res/drawable-nodpi/black_64x64.png b/tests/tests/sharesheet/res/drawable-nodpi/black_64x64.png
new file mode 100644
index 0000000..7cc9373
--- /dev/null
+++ b/tests/tests/sharesheet/res/drawable-nodpi/black_64x64.png
Binary files differ
diff --git a/tests/tests/sharesheet/res/values/strings.xml b/tests/tests/sharesheet/res/values/strings.xml
new file mode 100644
index 0000000..62529b6
--- /dev/null
+++ b/tests/tests/sharesheet/res/values/strings.xml
@@ -0,0 +1,31 @@
+<!--
+ ~ Copyright (C) 2020 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.
+ -->
+<resources>
+ <!-- All strings are intentionally short to avoid potential issues with truncation -->
+ <string name="test_app_label">App 1</string>
+ <string name="test_activity_label_app">App A</string>
+ <string name="test_activity_label_activity">Activity A</string>
+ <string name="test_intent_filter_label_app">App If</string>
+ <string name="test_intent_filter_label_activity">Activity If</string>
+ <string name="test_intent_filter_label_intentfilter">IntentFilter If</string>
+ <string name="test_blacklist_label">Bl Label</string>
+ <string name="test_chooser_target_service_label">CTS target</string>
+ <string name="test_sharing_shortcut_label">ShS target</string>
+ <string name="test_extra_chooser_targets_label">ECT target</string>
+ <string name="test_extra_initial_intents_label">EII target</string>
+ <string name="test_preview_title">Preview title</string>
+ <string name="test_preview_text">Preview text</string>
+</resources>
diff --git a/tests/tests/sharesheet/res/xml/shortcuts.xml b/tests/tests/sharesheet/res/xml/shortcuts.xml
new file mode 100644
index 0000000..684ebb4
--- /dev/null
+++ b/tests/tests/sharesheet/res/xml/shortcuts.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shortcuts xmlns:android="http://schemas.android.com/apk/res/android">
+ <share-target android:targetClass="android.sharesheet.cts.CtsSharesheetDeviceActivity">
+ <data android:mimeType="test/cts"/>
+ <category android:name="CATEGORY_CTS_TEST"/>
+ </share-target>
+</shortcuts>
\ No newline at end of file
diff --git a/tests/tests/sharesheet/src/android/sharesheet/cts/CtsSharesheetChooserTargetService.java b/tests/tests/sharesheet/src/android/sharesheet/cts/CtsSharesheetChooserTargetService.java
new file mode 100644
index 0000000..5fda05f
--- /dev/null
+++ b/tests/tests/sharesheet/src/android/sharesheet/cts/CtsSharesheetChooserTargetService.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2020 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.sharesheet.cts;
+
+import android.content.ComponentName;
+import android.content.IntentFilter;
+import android.graphics.drawable.Icon;
+import android.os.Bundle;
+import android.service.chooser.ChooserTarget;
+import android.service.chooser.ChooserTargetService;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class CtsSharesheetChooserTargetService extends ChooserTargetService {
+
+ @Override
+ public List<ChooserTarget> onGetChooserTargets(ComponentName componentName,
+ IntentFilter intentFilter) {
+
+ ChooserTarget ct = new ChooserTarget(
+ getString(R.string.test_chooser_target_service_label),
+ Icon.createWithResource(this, R.drawable.black_64x64),
+ 1f,
+ componentName,
+ new Bundle());
+
+ ChooserTarget[] ret = {ct};
+ return Arrays.asList(ret);
+ }
+}
\ No newline at end of file
diff --git a/tests/tests/sharesheet/src/android/sharesheet/cts/CtsSharesheetDeviceActivity.java b/tests/tests/sharesheet/src/android/sharesheet/cts/CtsSharesheetDeviceActivity.java
index 55a7e1b..f22a1cf 100644
--- a/tests/tests/sharesheet/src/android/sharesheet/cts/CtsSharesheetDeviceActivity.java
+++ b/tests/tests/sharesheet/src/android/sharesheet/cts/CtsSharesheetDeviceActivity.java
@@ -21,13 +21,13 @@
import java.lang.Override;
-/**
- * TODO: Add JavaDoc.
- */
public class CtsSharesheetDeviceActivity extends Activity {
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
+ // This activity may be opened to ensure click behavior functions properly.
+ // To ensure test repeatability do not stay open.
+ finish();
}
}
\ No newline at end of file
diff --git a/tests/tests/sharesheet/src/android/sharesheet/cts/CtsSharesheetDeviceTest.java b/tests/tests/sharesheet/src/android/sharesheet/cts/CtsSharesheetDeviceTest.java
index 1824d96..52bb7bc 100644
--- a/tests/tests/sharesheet/src/android/sharesheet/cts/CtsSharesheetDeviceTest.java
+++ b/tests/tests/sharesheet/src/android/sharesheet/cts/CtsSharesheetDeviceTest.java
@@ -15,13 +15,47 @@
*/
package android.sharesheet.cts;
-import android.platform.test.annotations.Presubmit;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
-import androidx.test.rule.ActivityTestRule;
+import android.app.ActivityManager;
+import android.app.Instrumentation;
+import android.app.PendingIntent;
+import android.app.UiAutomation;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.LabeledIntent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ShortcutInfo;
+import android.content.pm.ShortcutManager;
+import android.graphics.drawable.Icon;
+import android.os.Bundle;
+import android.service.chooser.ChooserTarget;
+import android.support.test.uiautomator.By;
+import android.support.test.uiautomator.BySelector;
+import android.support.test.uiautomator.UiDevice;
+import android.support.test.uiautomator.UiObject2;
+import android.support.test.uiautomator.Until;
+
+import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
-import org.junit.Assert;
-import org.junit.Rule;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+
+import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -33,25 +67,522 @@
public static final String TAG = CtsSharesheetDeviceTest.class.getSimpleName();
- @Rule
- public ActivityTestRule<CtsSharesheetDeviceActivity> mActivityRule =
- new ActivityTestRule(CtsSharesheetDeviceActivity.class);
+ private static final int WAIT_AND_ASSERT_FOUND_TIMEOUT_MS = 5000;
+ private static final int WAIT_AND_ASSERT_NOT_FOUND_TIMEOUT_MS = 2500;
+ private static final int WAIT_FOR_IDLE_TIMEOUT_MS = 5000;
+
+ private static final int MAX_EXTRA_INITIAL_INTENTS_SHOWN = 2;
+ private static final int MAX_EXTRA_CHOOSER_TARGETS_SHOWN = 2;
+
+ private static final String ACTION_INTENT_SENDER_FIRED_ON_CLICK =
+ "android.sharesheet.cts.ACTION_INTENT_SENDER_FIRED_ON_CLICK";
+
+ static final String CTS_DATA_TYPE = "test/cts"; // Special CTS mime type
+ static final String CATEGORY_CTS_TEST = "CATEGORY_CTS_TEST";
+
+ private Context mContext;
+ private Instrumentation mInstrumentation;
+ private UiAutomation mAutomation;
+ public UiDevice mDevice;
+
+ private String mPkg, mExcludePkg, mActivityLabelTesterPkg, mIntentFilterLabelTesterPkg;
+ private String mSharesheetPkg;
+
+ private ActivityManager mActivityManager;
+ private ShortcutManager mShortcutManager;
+
+ private String mAppLabel,
+ mActivityTesterAppLabel, mActivityTesterActivityLabel,
+ mIntentFilterTesterAppLabel, mIntentFilterTesterActivityLabel,
+ mIntentFilterTesterIntentFilterLabel,
+ mBlacklistLabel,
+ mChooserTargetServiceLabel, mSharingShortcutLabel, mExtraChooserTargetsLabelBase,
+ mExtraInitialIntentsLabelBase, mPreviewTitle, mPreviewText;
+
+ private Set<ComponentName> mTargetsToExclude;
/**
- * TODO: Add JavaDoc
- * This test runs on presubmit
+ * To validate Sharesheet API and API behavior works as intended UI test sare required. It is
+ * impossible to know the how the Sharesheet UI will be modified by end partners so these tests
+ * attempt to assume use the minimum needed assumptions to make the tests work.
+ *
+ * We cannot assume a scrolling direction or starting point because of potential UI variations.
+ * Because of limits of the UiAutomator pipeline only content visible on screen can be tested.
+ * These two constraints mean that all automated Sharesheet tests must be for content we
+ * reasonably expect to be visible after the sheet is opened without any direct interaction.
+ *
+ * Extra care is taken to ensure tested content is reasonably visible by:
+ * - Splitting tests across multiple Sharesheet calls
+ * - Excluding all packages not relevant to the test
+ * - Assuming a max of three targets per row of apps
*/
- @Presubmit
- @Test
- public void foo() throws Exception {
- Assert.assertNotNull(mActivityRule.getActivity());
+
+ @Before
+ public void init() throws Exception {
+ mInstrumentation = InstrumentationRegistry.getInstrumentation();
+ mContext = mInstrumentation.getTargetContext();
+ mPkg = mContext.getPackageName();
+ mExcludePkg = mPkg + ".packages.excludetester";
+ mActivityLabelTesterPkg = mPkg + ".packages.activitylabeltester";
+ mIntentFilterLabelTesterPkg = mPkg + ".packages.intentfilterlabeltester";
+
+ mDevice = UiDevice.getInstance(mInstrumentation);
+ mAutomation = mInstrumentation.getUiAutomation();
+
+ mActivityManager = mContext.getSystemService(ActivityManager.class);
+ mShortcutManager = mContext.getSystemService(ShortcutManager.class);
+ PackageManager pm = mContext.getPackageManager();
+ assertNotNull(mActivityManager);
+ assertNotNull(mShortcutManager);
+ assertNotNull(pm);
+
+ // Load in string to match against
+ mBlacklistLabel = mContext.getString(R.string.test_blacklist_label);
+ mAppLabel = mContext.getString(R.string.test_app_label);
+ mActivityTesterAppLabel = mContext.getString(R.string.test_activity_label_app);
+ mActivityTesterActivityLabel = mContext.getString(R.string.test_activity_label_activity);
+ mIntentFilterTesterAppLabel = mContext.getString(R.string.test_intent_filter_label_app);
+ mIntentFilterTesterActivityLabel =
+ mContext.getString(R.string.test_intent_filter_label_activity);
+ mIntentFilterTesterIntentFilterLabel =
+ mContext.getString(R.string.test_intent_filter_label_intentfilter);
+ mChooserTargetServiceLabel = mContext.getString(R.string.test_chooser_target_service_label);
+ mSharingShortcutLabel = mContext.getString(R.string.test_sharing_shortcut_label);
+ mExtraChooserTargetsLabelBase = mContext.getString(R.string.test_extra_chooser_targets_label);
+ mExtraInitialIntentsLabelBase = mContext.getString(R.string.test_extra_initial_intents_label);
+ mPreviewTitle = mContext.getString(R.string.test_preview_title);
+ mPreviewText = mContext.getString(R.string.test_preview_text);
+
+ // We want to only show targets in the sheet put forth by the CTS test. In order to do that
+ // a special type is used but this doesn't prevent apps registered against */* from showing.
+ // To hide */* targets, search for all matching targets and exclude them.
+ List<ResolveInfo> matchingTargets = mContext.getPackageManager().queryIntentActivities(
+ createMatchingIntent(),
+ PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_META_DATA
+ );
+
+ mTargetsToExclude = matchingTargets.stream()
+ .map(ri -> {
+ return new ComponentName(ri.activityInfo.packageName, ri.activityInfo.name);
+ })
+ .filter(cn -> {
+ // Exclude our own test targets
+ String pkg = cn.getPackageName();
+ boolean isInternalPkg = pkg.equals(mPkg) ||
+ pkg.equals(mActivityLabelTesterPkg) ||
+ pkg.equals(mIntentFilterLabelTesterPkg);
+
+ return !isInternalPkg;
+ })
+ .collect(Collectors.toSet());
+
+ // We need to know the package used by the system Sharesheet so we can properly
+ // wait for the UI to load. Do this by resolving which activity consumes the share intent.
+ // There must be a system Sharesheet or fail, otherwise fetch its the package.
+ Intent shareIntent = createShareIntent(false, 0, 0);
+ ResolveInfo shareRi = pm.resolveActivity(shareIntent, PackageManager.MATCH_DEFAULT_ONLY);
+
+ assertNotNull(shareRi);
+ assertNotNull(shareRi.activityInfo);
+
+ mSharesheetPkg = shareRi.activityInfo.packageName;
+ assertNotNull(mSharesheetPkg);
+
+ // Finally ensure the device is awake
+ mDevice.wakeUp();
}
/**
- * TODO: Add JavaDoc
+ * To test all features the Sharesheet will need to be opened and closed a few times. To keep
+ * total run time low, jam as many tests are possible into each visible test portion.
*/
@Test
- public void bar() throws Exception {
- Assert.assertTrue(true);
+ public void bulkTest1() {
+ try {
+ launchSharesheet(createShareIntent(true /* test content preview */,
+ 0 /* do not test EIIs */,
+ 0 /* do not test ECTs */));
+
+ doesExcludeComponents();
+ showsApplicationLabel();
+ showsAppAndActivityLabel();
+ showsAppAndIntentFilterLabel();
+ showsContentPreviewTitle();
+ showsContentPreviewText();
+ isChooserTargetServiceDirectShareEnabled();
+
+ // Must be run last, partial completion closes the Sharesheet
+ firesIntentSenderWithExtraChosenComponent();
+
+ } catch (Exception e) {
+ // No-op
+ } finally {
+ // The Sharesheet may or may not be open depending on test success, close it if it is
+ closeSharesheetIfNeeded();
+ }
+ }
+
+ @Test
+ public void bulkTest2() {
+ try {
+ addShortcuts(1);
+ launchSharesheet(createShareIntent(false /* do not test preview */,
+ MAX_EXTRA_INITIAL_INTENTS_SHOWN + 1 /* test EIIs at 1 above cap */,
+ MAX_EXTRA_CHOOSER_TARGETS_SHOWN + 1 /* test ECTs at 1 above cap */));
+ // Note: EII and ECT cap is not tested here
+
+ showsExtraInitialIntents();
+ showsExtraChooserTargets();
+ isSharingShortcutDirectShareEnabled();
+
+ } catch (Exception e) {
+ // No-op
+ } finally {
+ closeSharesheet();
+ clearShortcuts();
+ }
+ }
+
+ /*
+ Test methods
+ */
+
+ /**
+ * Tests API compliance for Intent.EXTRA_EXCLUDE_COMPONENTS. This test is necessary for other
+ * tests to run as expected.
+ */
+ public void doesExcludeComponents() {
+ // The excluded component should not be found on screen
+ waitAndAssertNoTextContains(mBlacklistLabel);
+ }
+
+ /**
+ * Tests API behavior compliance for security to always show application label
+ */
+ public void showsApplicationLabel() {
+ // For each app target the providing app's application manifest label should be shown
+ waitAndAssertTextContains(mAppLabel);
+ }
+
+ /**
+ * Tests API behavior compliance to show application and activity label when available
+ */
+ public void showsAppAndActivityLabel() {
+ waitAndAssertTextContains(mActivityTesterAppLabel);
+ waitAndAssertTextContains(mActivityTesterActivityLabel);
+ }
+
+ /**
+ * Tests API behavior compliance to show application and intent filter label when available
+ */
+ public void showsAppAndIntentFilterLabel() {
+ // NOTE: it is not necessary to show any set Activity label if an IntentFilter label is set
+ waitAndAssertTextContains(mIntentFilterTesterAppLabel);
+ waitAndAssertTextContains(mIntentFilterTesterIntentFilterLabel);
+ }
+
+ /**
+ * Tests API compliance for Intent.EXTRA_INITIAL_INTENTS
+ */
+ public void showsExtraInitialIntents() {
+ // Should show extra initial intents but must limit them, can't test limit here
+ waitAndAssertTextContains(mExtraInitialIntentsLabelBase);
+ }
+
+ /**
+ * Tests API compliance for Intent.EXTRA_CHOOSER_TARGETS
+ */
+ public void showsExtraChooserTargets() {
+ // Should show chooser targets but must limit them, can't test limit here
+ waitAndAssertTextContains(mExtraChooserTargetsLabelBase);
+ }
+
+ /**
+ * Tests API behavior compliance for Intent.EXTRA_TITLE
+ */
+ public void showsContentPreviewTitle() {
+ waitAndAssertTextContains(mPreviewTitle);
+ }
+
+ /**
+ * Tests API behavior compliance for Intent.EXTRA_TEXT
+ */
+ public void showsContentPreviewText() {
+ waitAndAssertTextContains(mPreviewText);
+ }
+
+ /**
+ * Tests API compliance for Intent.EXTRA_CHOSEN_COMPONENT_INTENT_SENDER and related APIs
+ * UI assumption: target labels are clickable, clicking opens target
+ */
+ public void firesIntentSenderWithExtraChosenComponent() throws Exception {
+ // To receive the extra chosen component a target must be clicked. Clicking the target
+ // will close the Sharesheet. Run this last in any sequence of tests.
+
+ // First find the target to click. This will fail if the showsApplicationLabel() test fails.
+ UiObject2 shareTarget = findTextContains(mAppLabel);
+ assertNotNull(shareTarget);
+
+ ComponentName clickedComponent = new ComponentName(mContext,
+ CtsSharesheetDeviceActivity.class);
+
+ final CountDownLatch latch = new CountDownLatch(1);
+ final Intent[] response = {null}; // Must be final so use an array
+
+ // Listen for the PendingIntent broadcast on click
+ BroadcastReceiver br = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ response[0] = intent;
+ latch.countDown();
+ }
+ };
+ mContext.registerReceiver(br, new IntentFilter(ACTION_INTENT_SENDER_FIRED_ON_CLICK));
+
+ // Start the event sequence and wait for results
+ shareTarget.click();
+
+ // The latch may fail for a number of reasons but we still need to unregister the
+ // BroadcastReceiver, so capture and rethrow any errors.
+ Exception delayedException = null;
+ try {
+ latch.await(1000, TimeUnit.MILLISECONDS);
+ } catch (Exception e) {
+ delayedException = e;
+ } finally {
+ mContext.unregisterReceiver(br);
+ }
+ if (delayedException != null) throw delayedException;
+
+ // Finally validate the received Intent
+ validateChosenComponentIntent(response[0], clickedComponent);
+ }
+
+ private void validateChosenComponentIntent(Intent intent, ComponentName matchingComponent) {
+ assertNotNull(intent);
+
+ assertTrue(intent.hasExtra(Intent.EXTRA_CHOSEN_COMPONENT));
+ Object extra = intent.getParcelableExtra(Intent.EXTRA_CHOSEN_COMPONENT);
+ assertNotNull(extra);
+
+ assertTrue(extra instanceof ComponentName);
+ ComponentName component = (ComponentName) extra;
+
+ assertEquals(component, matchingComponent);
+ }
+
+ /**
+ * Tests API behavior compliance for ChooserTargetService
+ */
+ public void isChooserTargetServiceDirectShareEnabled() {
+ // ChooserTargets can take time to load. To account for this:
+ // * All non-test ChooserTargetServices shouldn't be loaded because of blacklist
+ // * waitAndAssert operations have lengthy timeout periods
+ // * Last time to run in suite so prior operations reduce wait time
+
+ if (mActivityManager.isLowRamDevice()) {
+ // Ensure direct share is disabled on low ram devices
+ waitAndAssertNoTextContains(mChooserTargetServiceLabel);
+ } else {
+ // Ensure direct share is enabled
+ waitAndAssertTextContains(mChooserTargetServiceLabel);
+ }
+ }
+
+ /**
+ * Tests API behavior compliance for Sharing Shortcuts
+ */
+ public void isSharingShortcutDirectShareEnabled() {
+ if (mActivityManager.isLowRamDevice()) {
+ // Ensure direct share is disabled on low ram devices
+ waitAndAssertNoTextContains(mSharingShortcutLabel);
+ } else {
+ // Ensure direct share is enabled
+ waitAndAssertTextContains(mSharingShortcutLabel);
+ }
+ }
+
+ /*
+ Setup methods
+ */
+
+ public void addShortcuts(int size) {
+ mShortcutManager.addDynamicShortcuts(createShortcuts(size));
+ }
+
+ public void clearShortcuts() {
+ mShortcutManager.removeAllDynamicShortcuts();
+ }
+
+ private List<ShortcutInfo> createShortcuts(int size) {
+ List<ShortcutInfo> ret = new ArrayList<>();
+ for (int i=0; i<size; i++) {
+ ret.add(createShortcut(""+i));
+ }
+ return ret;
+ }
+
+ private ShortcutInfo createShortcut(String id) {
+ HashSet<String> categories = new HashSet<>();
+ categories.add(CATEGORY_CTS_TEST);
+
+ return new ShortcutInfo.Builder(mContext, id)
+ .setShortLabel(mSharingShortcutLabel)
+ .setIcon(Icon.createWithResource(mContext, R.drawable.black_64x64))
+ .setCategories(categories)
+ .setIntent(new Intent(Intent.ACTION_DEFAULT)) /* an Intent with an action must be set */
+ .build();
+ }
+
+ private void launchSharesheet(Intent shareIntent) {
+ mContext.startActivity(shareIntent);
+ waitAndAssertPkgVisible(mSharesheetPkg);
+ waitForIdle();
+ }
+
+ private void closeSharesheetIfNeeded() {
+ if (isSharesheetVisible()) closeSharesheet();
+ }
+
+ private void closeSharesheet() {
+ mDevice.pressBack();
+ waitAndAssertPkgNotVisible(mSharesheetPkg);
+ waitForIdle();
+ }
+
+ private boolean isSharesheetVisible() {
+ // This method intentionally does not wait, looks to see if visible on method call
+ return mDevice.findObject(By.pkg(mSharesheetPkg).depth(0)) != null;
+ }
+
+ private Intent createMatchingIntent() {
+ Intent intent = new Intent(Intent.ACTION_SEND);
+ intent.setType(CTS_DATA_TYPE);
+ return intent;
+ }
+
+ private Intent createShareIntent(boolean contentPreview,
+ int numExtraInitialIntents,
+ int numExtraChooserTargets) {
+
+ Intent intent = createMatchingIntent();
+
+ if (contentPreview) {
+ intent.putExtra(Intent.EXTRA_TITLE, mPreviewTitle);
+ intent.putExtra(Intent.EXTRA_TEXT, mPreviewText);
+ }
+
+ PendingIntent pi = PendingIntent.getBroadcast(
+ mContext,
+ 9384 /* number not relevant */ ,
+ new Intent(ACTION_INTENT_SENDER_FIRED_ON_CLICK),
+ PendingIntent.FLAG_UPDATE_CURRENT);
+
+ Intent shareIntent = Intent.createChooser(intent, null, pi.getIntentSender());
+
+ // Intent.EXTRA_EXCLUDE_COMPONENTS is used to ensure only test targets appear
+ List<ComponentName> list = new ArrayList<>(mTargetsToExclude);
+ list.add(new ComponentName(mPkg, mPkg + ".BlacklistTestActivity"));
+ shareIntent.putExtra(Intent.EXTRA_EXCLUDE_COMPONENTS,
+ list.toArray(new ComponentName[0]));
+
+ if (numExtraInitialIntents > 0) {
+ Intent[] eiis = new Intent[numExtraInitialIntents];
+ for (int i = 0; i < eiis.length; i++) {
+ Intent eii = new Intent();
+ eii.setComponent(new ComponentName(mPkg,
+ mPkg + ".ExtraInitialIntentTestActivity"));
+
+ LabeledIntent labeledEii = new LabeledIntent(eii, mPkg,
+ getExtraInitialIntentsLabel(i),
+ 0 /* provide no icon */);
+
+ eiis[i] = labeledEii;
+ }
+
+ shareIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, eiis);
+ }
+
+ if (numExtraChooserTargets > 0) {
+ ChooserTarget[] ects = new ChooserTarget[numExtraChooserTargets];
+ for (int i = 0; i < ects.length; i++) {
+ ects[i] = new ChooserTarget(
+ getExtraChooserTargetLabel(i),
+ Icon.createWithResource(mContext, R.drawable.black_64x64),
+ 1f,
+ new ComponentName(mPkg, mPkg + ".CtsSharesheetDeviceActivity"),
+ new Bundle());
+ }
+
+ shareIntent.putExtra(Intent.EXTRA_CHOOSER_TARGETS, ects);
+ }
+
+ // Ensure the sheet will launch directly from the test
+ shareIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+ return shareIntent;
+ }
+
+ private String getExtraChooserTargetLabel(int position) {
+ return mExtraChooserTargetsLabelBase + " " + position;
+ }
+
+ private String getExtraInitialIntentsLabel(int position) {
+ return mExtraInitialIntentsLabelBase + " " + position;
+ }
+
+ /*
+ UI testing methods
+ */
+
+ private void waitForIdle() {
+ mDevice.waitForIdle(WAIT_FOR_IDLE_TIMEOUT_MS);
+ }
+
+ private void waitAndAssertPkgVisible(String pkg) {
+ waitAndAssertFound(By.pkg(pkg).depth(0));
+ }
+
+ private void waitAndAssertPkgNotVisible(String pkg) {
+ waitAndAssertNotFound(By.pkg(pkg));
+ }
+
+ private void waitAndAssertTextContains(String containsText) {
+ waitAndAssertFound(By.textContains(containsText));
+ }
+
+ private void waitAndAssertNoTextContains(String containsText) {
+ waitAndAssertNotFound(By.textContains(containsText));
+ }
+
+ /**
+ * waitAndAssertFound will wait until UI defined by the selector is found. If it's never found,
+ * this will wait for the duration of the full timeout. Take care to call this method after
+ * reasonable steps are taken to ensure fast completion.
+ */
+ private void waitAndAssertFound(BySelector selector) {
+ assertNotNull(mDevice.wait(Until.findObject(selector), WAIT_AND_ASSERT_FOUND_TIMEOUT_MS));
+ }
+
+ /**
+ * waitAndAssertNotFound waits for any visible UI to be hidden, validates that it's indeed gone
+ * without waiting more and returns. This means if the UI wasn't visible to start with the
+ * method will return without no timeout. Take care to call this method only once there's reason
+ * to think the UI is in the right state for testing.
+ */
+ private void waitAndAssertNotFound(BySelector selector) {
+ mDevice.wait(Until.gone(selector), WAIT_AND_ASSERT_NOT_FOUND_TIMEOUT_MS);
+ assertNull(mDevice.findObject(selector));
+ }
+
+ /**
+ * findTextContains uses logic similar to waitAndAssertFound to locate UI objects that contain
+ * the provided String.
+ * @param containsText the String to search for, note this is not an exact match only contains
+ * @return UiObject2 that can be used, for example, to execute a click
+ */
+ private UiObject2 findTextContains(String containsText) {
+ return mDevice.wait(Until.findObject(By.textContains(containsText)),
+ WAIT_AND_ASSERT_FOUND_TIMEOUT_MS);
}
}
diff --git a/tests/tests/telecom/src/android/telecom/cts/BasicInCallServiceTest.java b/tests/tests/telecom/src/android/telecom/cts/BasicInCallServiceTest.java
index ef20d33..75b9372 100644
--- a/tests/tests/telecom/src/android/telecom/cts/BasicInCallServiceTest.java
+++ b/tests/tests/telecom/src/android/telecom/cts/BasicInCallServiceTest.java
@@ -18,16 +18,23 @@
import static android.telecom.cts.TestUtils.shouldTestTelecom;
-import android.telecom.cts.MockInCallService.InCallServiceCallbacks;
-
import android.content.Context;
import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.telecom.Call;
import android.telecom.InCallService;
+import android.telecom.TelecomManager;
+import android.telecom.cts.MockInCallService.InCallServiceCallbacks;
import android.test.InstrumentationTestCase;
import android.text.TextUtils;
+import com.android.compatibility.common.util.CddTest;
+
+import org.junit.Test;
+
+import java.util.List;
import java.util.concurrent.TimeUnit;
/**
@@ -56,6 +63,32 @@
super.tearDown();
}
+ @CddTest(requirement = "7.4.1.2/C-1-3")
+ public void testResolveInCallIntent() {
+ if (!shouldTestTelecom(mContext)) {
+ return;
+ }
+ PackageManager packageManager = mContext.getPackageManager();
+ Intent serviceIntent = new Intent(InCallService.SERVICE_INTERFACE);
+ List<ResolveInfo> resolveInfo = packageManager.queryIntentServices(serviceIntent,
+ PackageManager.GET_META_DATA);
+
+ assertNotNull(resolveInfo);
+ assertTrue(resolveInfo.size() >= 1);
+
+ // Ensure at least one InCallService is able to handle the UI for calls.
+ assertTrue(resolveInfo
+ .stream()
+ .filter(r -> r.serviceInfo != null
+ && r.serviceInfo.metaData != null
+ && r.serviceInfo.metaData.containsKey(
+ TelecomManager.METADATA_IN_CALL_SERVICE_UI)
+ && r.serviceInfo.permission.equals(
+ android.Manifest.permission.BIND_INCALL_SERVICE)
+ && r.serviceInfo.name != null)
+ .count() >= 1);
+ }
+
/**
* Tests that when sending a CALL intent via the Telecom -> Telephony stack, Telecom
* binds to the registered {@link InCallService}s and adds a new call. This test will
diff --git a/tests/tests/telecom4/Android.mk b/tests/tests/telecom4/Android.mk
deleted file mode 100644
index 2fc8558..0000000
--- a/tests/tests/telecom4/Android.mk
+++ /dev/null
@@ -1,40 +0,0 @@
-# Copyright (C) 2015 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-# don't include this package in any target
-LOCAL_MODULE_TAGS := optional
-# and when built explicitly put it in the data partition
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
- ctstestrunner-axt \
- compatibility-device-util-axt
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := CtsTelecom4TestCases
-LOCAL_SDK_VERSION := current
-
-# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
-
-LOCAL_JAVA_LIBRARIES += android.test.runner.stubs
-LOCAL_JAVA_LIBRARIES += android.test.base.stubs
-
-include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/telecom4/AndroidManifest.xml b/tests/tests/telecom4/AndroidManifest.xml
deleted file mode 100644
index a887fdf..0000000
--- a/tests/tests/telecom4/AndroidManifest.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?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.telecom4.cts">
-
- <application>
- <uses-library android:name="android.test.runner" />
- </application>
-
- <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
- android:targetPackage="android.telecom4.cts">
- <meta-data android:name="listener"
- android:value="com.android.cts.runner.CtsTestRunListener" />
- </instrumentation>
-
-</manifest>
-
diff --git a/tests/tests/telecom4/AndroidTest.xml b/tests/tests/telecom4/AndroidTest.xml
deleted file mode 100644
index c88f8a6..0000000
--- a/tests/tests/telecom4/AndroidTest.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?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 Telecom test cases">
- <option name="test-suite-tag" value="cts" />
- <option name="config-descriptor:metadata" key="component" value="telecom" />
- <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
- <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
- <option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
- <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="CtsTelecom4TestCases.apk" />
- </target_preparer>
- <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
- <option name="package" value="android.telecom4.cts" />
- <option name="runtime-hint" value="7m30s" />
- </test>
-</configuration>
diff --git a/tests/tests/telecom4/OWNERS b/tests/tests/telecom4/OWNERS
deleted file mode 100644
index 93fe555..0000000
--- a/tests/tests/telecom4/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# Bug component: 20868
-
diff --git a/tests/tests/telecom4/src/android/telecom4/cts/InCallServiceImplTest.java b/tests/tests/telecom4/src/android/telecom4/cts/InCallServiceImplTest.java
deleted file mode 100644
index 0e68c64..0000000
--- a/tests/tests/telecom4/src/android/telecom4/cts/InCallServiceImplTest.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * 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.telecom4.cts;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.util.Log;
-
-import androidx.test.InstrumentationRegistry;
-import androidx.test.runner.AndroidJUnit4;
-
-import com.android.compatibility.common.util.CddTest;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/**
- * Build, install and run the tests by running the commands below:
- * make CtsTelecom4TestCases -j64
- * cts-tradefed run cts -m CtsTelecom4TestCases --test android.telecom4.cts.InCallServiceImplTest
- */
-@RunWith(AndroidJUnit4.class)
-public class InCallServiceImplTest {
- private static final String TAG = "InCallServiceTest";
- private static final String IN_CALL_SERVICE_ACTION = "android.telecom.InCallService";
- private static final String IN_CALL_SERVICE_PERMISSION =
- "android.permission.BIND_INCALL_SERVICE";
-
- private Context mContext;
- private PackageManager mPackageManager;
-
- @Before
- public void setup() {
- mContext = InstrumentationRegistry.getContext();
- mPackageManager = mContext.getPackageManager();
- }
-
- @CddTest(requirement = "7.4.1.2/C-1-3")
- @Test
- public void resolveInCallIntent() {
- if (!hasTelephonyFeature()) {
- Log.d(TAG, "Bypass the test since telephony is not available.");
- return;
- }
-
- Intent intent = new Intent();
- intent.setAction(IN_CALL_SERVICE_ACTION);
- ResolveInfo resolveInfo = mPackageManager.resolveService(intent,
- PackageManager.GET_SERVICES | PackageManager.GET_META_DATA);
-
- assertNotNull(resolveInfo);
- assertNotNull(resolveInfo.serviceInfo);
- assertNotNull(resolveInfo.serviceInfo.packageName);
- assertNotNull(resolveInfo.serviceInfo.name);
- assertEquals(IN_CALL_SERVICE_PERMISSION, resolveInfo.serviceInfo.permission);
- }
-
- private boolean hasTelephonyFeature() {
- return mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY);
- }
-}
diff --git a/tests/tests/telephony/current/preconditions/app/AndroidManifest.xml b/tests/tests/telephony/current/preconditions/app/AndroidManifest.xml
index f84d1ec..9001092 100644
--- a/tests/tests/telephony/current/preconditions/app/AndroidManifest.xml
+++ b/tests/tests/telephony/current/preconditions/app/AndroidManifest.xml
@@ -18,6 +18,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="android.telephony.cts.preconditions.app">
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
+ <uses-permission android:name="android.permission.READ_PHONE_NUMBERS" />
<application>
<uses-library android:name="android.test.runner" />
</application>
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/PhoneStateListenerTest.java b/tests/tests/telephony/current/src/android/telephony/cts/PhoneStateListenerTest.java
index f0a0ccc..864cbac 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/PhoneStateListenerTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/PhoneStateListenerTest.java
@@ -274,6 +274,10 @@
assertTrue(mOnSignalStrengthChangedCalled);
}
+ /**
+ * Due to the corresponding API is hidden in R and will be public in S, this test
+ * is commented and will be un-commented in Android S.
+ *
@Test
public void testOnAlwaysReportedSignalStrengthChanged() throws Throwable {
if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
@@ -294,8 +298,8 @@
}
};
ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
- (tm) -> tm.listen(mListener,
- PhoneStateListener.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH));
+ (tm) -> tm.listen(mListener,
+ PhoneStateListener.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH));
});
synchronized (mLock) {
if (mSignalStrength == null) {
@@ -315,12 +319,16 @@
mSignalStrength.isGsm();
mSignalStrength.getLevel();
}
+ */
/**
+ * Due to the corresponding API is hidden in R and will be public in S, this test
+ * is commented and will be un-commented in Android S.
+ *
* Validate that SecurityException should be thrown when listen
* with LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH without LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH
* permission.
- */
+ *
@Test
public void testOnAlwaysReportedSignalStrengthChangedWithoutPermission() throws Throwable {
if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
@@ -342,7 +350,7 @@
};
try {
mTelephonyManager.listen(mListener,
- PhoneStateListener.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH);
+ PhoneStateListener.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH);
} catch (SecurityException se) {
synchronized (mLock) {
mSecurityExceptionThrown = true;
@@ -359,6 +367,7 @@
assertThat(mSecurityExceptionThrown).isTrue();
assertTrue(mSignalStrength == null);
}
+ */
@Test
public void testOnSignalStrengthsChanged() throws Throwable {
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 67a8864..cabc0e1 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java
@@ -46,6 +46,7 @@
import android.os.IBinder;
import android.os.Looper;
import android.os.PersistableBundle;
+import android.os.Process;
import android.os.RemoteException;
import android.telecom.PhoneAccount;
import android.telecom.PhoneAccountHandle;
@@ -54,7 +55,6 @@
import android.telephony.Annotation.RadioPowerState;
import android.telephony.AvailableNetworkInfo;
import android.telephony.CallAttributes;
-import android.telephony.CallForwardingInfo;
import android.telephony.CallQuality;
import android.telephony.CarrierConfigManager;
import android.telephony.CellLocation;
@@ -84,6 +84,7 @@
import org.junit.After;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
import java.security.MessageDigest;
@@ -536,6 +537,18 @@
ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mTelephonyManager,
(tm) -> tm.resetIms(tm.getSlotIndex()));
+ // Verify TelephonyManager.getCarrierPrivilegeStatus
+ List<Integer> validCarrierPrivilegeStatus = new ArrayList<>();
+ validCarrierPrivilegeStatus.add(TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS);
+ validCarrierPrivilegeStatus.add(TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS);
+ validCarrierPrivilegeStatus.add(
+ TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED);
+ validCarrierPrivilegeStatus.add(
+ TelephonyManager.CARRIER_PRIVILEGE_STATUS_ERROR_LOADING_RULES);
+ int carrierPrivilegeStatusResult = ShellIdentityUtils.invokeMethodWithShellPermissions(
+ mTelephonyManager, (tm) -> tm.getCarrierPrivilegeStatus(Process.myUid()));
+ assertTrue(validCarrierPrivilegeStatus.contains(carrierPrivilegeStatusResult));
+
// Verify TelephonyManager.getCarrierPrivilegedPackagesForAllActiveSubscriptions
List<String> resultForGetCarrierPrivilegedApis =
ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
@@ -545,9 +558,14 @@
assertFalse(TextUtils.isEmpty(result));
}
- TelephonyManager.getDefaultRespondViaMessageApplication(getContext(), false);
+ mTelephonyManager.getDefaultRespondViaMessageApplication();
+ mTelephonyManager.getAndUpdateDefaultRespondViaMessageApplication();
}
+ /**
+ * Due to the corresponding API is hidden in R and will be public in S, this test
+ * is commented and will be un-commented in Android S.
+ *
@Test
public void testGetCallForwarding() {
List<Integer> callForwardingReasons = new ArrayList<>();
@@ -579,7 +597,12 @@
assertTrue(callForwardingInfo.getTimeoutSeconds() >= 0);
}
}
+ */
+ /**
+ * Due to the corresponding API is hidden in R and will be public in S, this test
+ * is commented and will be un-commented in Android S.
+ *
@Test
public void testSetCallForwarding() {
List<Integer> callForwardingReasons = new ArrayList<>();
@@ -596,10 +619,12 @@
CallForwardingInfo.STATUS_ACTIVE,
callForwardingReasonToEnable,
TEST_FORWARD_NUMBER,
- 1 /** time seconds */);
+ // time seconds
+ 1);
Log.d(TAG, "[testSetCallForwarding] Enable Call Forwarding. Status: "
- + CallForwardingInfo.STATUS_ACTIVE + " Reason: " + callForwardingReasonToEnable
- + " Number: " + TEST_FORWARD_NUMBER + " Time Seconds: 1");
+ + CallForwardingInfo.STATUS_ACTIVE + " Reason: "
+ + callForwardingReasonToEnable + " Number: " + TEST_FORWARD_NUMBER
+ + " Time Seconds: 1");
ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
(tm) -> tm.setCallForwarding(callForwardingInfoToEnable));
}
@@ -610,7 +635,8 @@
CallForwardingInfo.STATUS_INACTIVE,
callForwardingReasonToDisable,
TEST_FORWARD_NUMBER,
- 1 /** time seconds */);
+ // time seconds
+ 1);
Log.d(TAG, "[testSetCallForwarding] Disable Call Forwarding. Status: "
+ CallForwardingInfo.STATUS_INACTIVE + " Reason: "
+ callForwardingReasonToDisable + " Number: " + TEST_FORWARD_NUMBER
@@ -619,7 +645,12 @@
(tm) -> tm.setCallForwarding(callForwardingInfoToDisable));
}
}
+ */
+ /**
+ * Due to the corresponding API is hidden in R and will be public in S, this test
+ * is commented and will be un-commented in Android S.
+ *
@Test
public void testGetCallWaitingStatus() {
Set<Integer> callWaitingStatus = new HashSet<Integer>();
@@ -632,7 +663,12 @@
mTelephonyManager, (tm) -> tm.getCallWaitingStatus());
assertTrue(callWaitingStatus.contains(status));
}
+ */
+ /**
+ * Due to the corresponding API is hidden in R and will be public in S, this test
+ * is commented and will be un-commented in Android S.
+ *
@Test
public void testSetCallWaitingStatus() {
ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
@@ -640,6 +676,7 @@
ShellIdentityUtils.invokeMethodWithShellPermissions(mTelephonyManager,
(tm) -> tm.setCallWaitingStatus(false));
}
+ */
@Test
public void testCellLocationFinePermission() {
@@ -1448,6 +1485,7 @@
* Verifies that {@link TelephonyManager#getIsimImpu()} does not throw any exception when called
* and has the correct permissions.
*/
+ @Ignore("API moved back to @hide for Android R.")
@Test
public void testGetIsimImpu() {
if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
@@ -2520,16 +2558,6 @@
}
@Test
- public void testIsDataCapableExists() {
- if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
- return;
- }
-
- //Simple test to make sure that isDataCapable exists and does not crash.
- mTelephonyManager.isDataCapable();
- }
-
- @Test
public void testDisAllowedNetworkTypes() {
if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
return;
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/TelephonyPermissionPolicyTest.java b/tests/tests/telephony/current/src/android/telephony/cts/TelephonyPermissionPolicyTest.java
deleted file mode 100644
index 37228c8..0000000
--- a/tests/tests/telephony/current/src/android/telephony/cts/TelephonyPermissionPolicyTest.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * 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.telephony.cts;
-
-import static org.junit.Assert.assertTrue;
-
-import android.content.pm.PackageManager;
-import android.util.ArraySet;
-
-import androidx.test.InstrumentationRegistry;
-
-import org.junit.Test;
-
-public class TelephonyPermissionPolicyTest {
- private static final ArraySet<String> KNOWN_TELEPHONY_PACKAGES;
-
- static {
- KNOWN_TELEPHONY_PACKAGES = new ArraySet<>();
- KNOWN_TELEPHONY_PACKAGES.add("com.android.phone");
- KNOWN_TELEPHONY_PACKAGES.add("com.android.stk");
- 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
- public void testIsTelephonyPackagesKnown() {
- final PackageManager pm = InstrumentationRegistry.getContext().getPackageManager();
- final String[] configuredTelephonyPackages = pm.getTelephonyPackageNames();
- // make sure only known system telephony apks are configured which will be granted special
- // permissions.
- for (String packageName : configuredTelephonyPackages) {
- assertTrue(KNOWN_TELEPHONY_PACKAGES.contains(packageName));
- }
- }
-}
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 953005e..5e28767 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
@@ -722,8 +722,8 @@
};
final UiAutomation automan = InstrumentationRegistry.getInstrumentation().getUiAutomation();
- // Latch will count down here (we callback on the state during registration).
try {
+ // First try without the correct permissions.
ImsManager imsManager = getContext().getSystemService(ImsManager.class);
ImsMmTelManager mmTelManager = imsManager.getImsMmTelManager(sTestSub);
mmTelManager.registerImsRegistrationCallback(getContext().getMainExecutor(), callback);
@@ -732,6 +732,7 @@
//expected
}
+ // Latch will count down here (we callback on the state during registration).
try {
automan.adoptShellPermissionIdentity();
ImsManager imsManager = getContext().getSystemService(ImsManager.class);
@@ -761,6 +762,16 @@
assertEquals(AccessNetworkConstants.TRANSPORT_TYPE_WLAN, waitForIntResult(mQueue));
assertEquals(ImsReasonInfo.CODE_LOCAL_HO_NOT_FEASIBLE, waitForIntResult(mQueue));
+ // Ensure null ImsReasonInfo still results in non-null callback value.
+ sServiceConnector.getCarrierService().getImsRegistration().onTechnologyChangeFailed(
+ ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN, null);
+ assertEquals(AccessNetworkConstants.TRANSPORT_TYPE_WLAN, waitForIntResult(mQueue));
+ assertEquals(ImsReasonInfo.CODE_UNSPECIFIED, waitForIntResult(mQueue));
+
+ // Ensure null ImsReasonInfo still results in non-null callback.
+ sServiceConnector.getCarrierService().getImsRegistration().onDeregistered(null);
+ assertEquals(ImsReasonInfo.CODE_UNSPECIFIED, waitForIntResult(mQueue));
+
try {
automan.adoptShellPermissionIdentity();
ImsManager imsManager = getContext().getSystemService(ImsManager.class);
@@ -778,7 +789,6 @@
} catch (SecurityException e) {
//expected
}
-
}
@Ignore("RCS APIs not public yet")
@@ -1136,6 +1146,105 @@
}
}
+ /**
+ * We are specifically testing a race case here such that IsAvailable returns the correct
+ * capability status during the callback.
+ */
+ @Test
+ public void testCapabilityStatusWithIsAvailableDuringCallback() throws Exception {
+ if (!ImsUtils.shouldTestImsService()) {
+ return;
+ }
+
+ ImsManager imsManager = getContext().getSystemService(ImsManager.class);
+ ImsMmTelManager mmTelManager = imsManager.getImsMmTelManager(sTestSub);
+
+ triggerFrameworkConnectToCarrierImsService();
+
+ // Wait for the framework to set the capabilities on the ImsService
+ sServiceConnector.getCarrierService().waitForLatchCountdown(
+ TestImsService.LATCH_MMTEL_CAP_SET);
+
+
+ // Make sure we start off with every capability unavailable
+ sServiceConnector.getCarrierService().getImsRegistration().onRegistered(
+ ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
+ MmTelFeature.MmTelCapabilities stdCapabilities = new MmTelFeature.MmTelCapabilities();
+ sServiceConnector.getCarrierService().getMmTelFeature()
+ .notifyCapabilitiesStatusChanged(stdCapabilities);
+
+
+ // Make sure the capabilities match the API getter for capabilities
+ final UiAutomation automan = InstrumentationRegistry.getInstrumentation().getUiAutomation();
+
+ //This lock is to keep the shell permissions from being dropped on a different thread
+ //causing a permission error.
+ Object lockObj = new Object();
+
+ synchronized (lockObj) {
+ try {
+ automan.adoptShellPermissionIdentity();
+ boolean isAvailableBeforeStatusChange = mmTelManager.isAvailable(
+ MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE,
+ ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
+ assertFalse(isAvailableBeforeStatusChange);
+ } finally {
+ automan.dropShellPermissionIdentity();
+ }
+ }
+
+ LinkedBlockingQueue<Boolean> voiceIsAvailable = new LinkedBlockingQueue<>();
+ ImsMmTelManager.CapabilityCallback verifyCapabilityStatusCallaback =
+ new ImsMmTelManager.CapabilityCallback() {
+ @Override
+ public void onCapabilitiesStatusChanged(MmTelFeature.MmTelCapabilities capabilities) {
+ synchronized (lockObj) {
+ try {
+ automan.adoptShellPermissionIdentity();
+ boolean isVoiceAvailable = mmTelManager
+ .isAvailable(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE,
+ ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
+
+ voiceIsAvailable.offer(isVoiceAvailable);
+ } finally {
+ automan.dropShellPermissionIdentity();
+ }
+ }
+ }
+ };
+
+ synchronized (lockObj) {
+ // Latch will count down here (we callback on the state during registration).
+ try {
+ automan.adoptShellPermissionIdentity();
+ mmTelManager.registerMmTelCapabilityCallback(getContext().getMainExecutor(),
+ verifyCapabilityStatusCallaback);
+ } finally {
+ automan.dropShellPermissionIdentity();
+ }
+ }
+
+ // Now enable voice availability
+ Boolean isAvailableDuringRegister = waitForResult(voiceIsAvailable);
+ assertNotNull(isAvailableDuringRegister);
+ assertFalse(isAvailableDuringRegister);
+ sServiceConnector.getCarrierService().getMmTelFeature()
+ .notifyCapabilitiesStatusChanged(new MmTelFeature.MmTelCapabilities(
+ MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE));
+ Boolean isAvailableAfterStatusChange = waitForResult(voiceIsAvailable);
+ assertNotNull(isAvailableAfterStatusChange);
+ assertTrue(isAvailableAfterStatusChange);
+
+ synchronized (lockObj) {
+ try {
+ automan.adoptShellPermissionIdentity();
+ mmTelManager.unregisterMmTelCapabilityCallback(verifyCapabilityStatusCallaback);
+ } finally {
+ automan.dropShellPermissionIdentity();
+ }
+ }
+ }
+
@Test
public void testProvisioningManagerNotifyAutoConfig() throws Exception {
if (!ImsUtils.shouldTestImsService()) {
@@ -1327,6 +1436,49 @@
assertEquals(TEST_CONFIG_VALUE_STRING,
provisioningManager.getProvisioningStringValue(TEST_CONFIG_KEY));
+ automan.adoptShellPermissionIdentity();
+ provisioningManager.unregisterProvisioningChangedCallback(callback);
+ } finally {
+ automan.dropShellPermissionIdentity();
+ }
+ }
+
+ @Ignore("The ProvisioningManager constants were moved back to @hide for now, don't want to "
+ + "completely remove test.")
+ @Test
+ public void testProvisioningManagerConstants() throws Exception {
+ if (!ImsUtils.shouldTestImsService()) {
+ return;
+ }
+
+ triggerFrameworkConnectToCarrierImsService();
+
+ ProvisioningManager provisioningManager =
+ ProvisioningManager.createForSubscriptionId(sTestSub);
+
+ // This is a little bit gross looking, but on P devices, I can not define classes that
+ // extend ProvisioningManager.Callback (because it doesn't exist), so this has to
+ // happen as an anon class here.
+ LinkedBlockingQueue<Pair<Integer, Integer>> mIntQueue = new LinkedBlockingQueue<>();
+ LinkedBlockingQueue<Pair<Integer, String>> mStringQueue = new LinkedBlockingQueue<>();
+ ProvisioningManager.Callback callback = new ProvisioningManager.Callback() {
+ @Override
+ public void onProvisioningIntChanged(int item, int value) {
+ mIntQueue.offer(new Pair<>(item, value));
+ }
+
+ @Override
+ public void onProvisioningStringChanged(int item, String value) {
+ mStringQueue.offer(new Pair<>(item, value));
+ }
+ };
+
+ final UiAutomation automan = InstrumentationRegistry.getInstrumentation().getUiAutomation();
+ try {
+ automan.adoptShellPermissionIdentity();
+ provisioningManager.registerProvisioningChangedCallback(getContext().getMainExecutor(),
+ callback);
+
verifyStringKey(provisioningManager, mStringQueue,
ProvisioningManager.KEY_AMR_CODEC_MODE_SET_VALUES, "1,2");
verifyStringKey(provisioningManager, mStringQueue,
diff --git a/tests/tests/tethering/src/android/tethering/cts/TetheringManagerTest.java b/tests/tests/tethering/src/android/tethering/cts/TetheringManagerTest.java
index 98dbe52..4d72eae 100644
--- a/tests/tests/tethering/src/android/tethering/cts/TetheringManagerTest.java
+++ b/tests/tests/tethering/src/android/tethering/cts/TetheringManagerTest.java
@@ -180,15 +180,15 @@
}
}
- private class StartTetheringCallback extends TetheringManager.StartTetheringCallback {
+ private class StartTetheringCallback implements TetheringManager.StartTetheringCallback {
@Override
public void onTetheringStarted() {
// Do nothing, TetherChangeReceiver will wait until it receives the broadcast.
}
@Override
- public void onTetheringFailed(final int resultCode) {
- fail("startTethering fail: " + resultCode);
+ public void onTetheringFailed(final int error) {
+ fail("startTethering fail: " + error);
}
}
diff --git a/tests/tests/tv/Android.bp b/tests/tests/tv/Android.bp
index 640b963..f24cd1e 100644
--- a/tests/tests/tv/Android.bp
+++ b/tests/tests/tv/Android.bp
@@ -27,8 +27,11 @@
"android.test.base.stubs",
],
static_libs: [
+ "androidx.test.core",
"compatibility-device-util-axt",
"ctstestrunner-axt",
+ "testng",
],
- sdk_version: "test_current",
+ // sdk_version: "test_current",
+ platform_apis: true,
}
diff --git a/tests/tests/tv/AndroidManifest.xml b/tests/tests/tv/AndroidManifest.xml
index 8cb2b79..ce93d9a 100644
--- a/tests/tests/tv/AndroidManifest.xml
+++ b/tests/tests/tv/AndroidManifest.xml
@@ -21,6 +21,9 @@
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<uses-permission android:name="android.permission.INJECT_EVENTS" />
+ <uses-permission android:name="android.permission.ACCESS_TV_DESCRAMBLER" />
+ <uses-permission android:name="android.permission.ACCESS_TV_TUNER" />
+ <uses-permission android:name="android.permission.TUNER_RESOURCE_ACCESS" />
<uses-permission android:name="com.android.providers.tv.permission.WRITE_EPG_DATA" />
diff --git a/tests/tests/tv/src/android/media/tv/tuner/cts/TunerTest.java b/tests/tests/tv/src/android/media/tv/tuner/cts/TunerTest.java
new file mode 100644
index 0000000..4eaafe3
--- /dev/null
+++ b/tests/tests/tv/src/android/media/tv/tuner/cts/TunerTest.java
@@ -0,0 +1,60 @@
+/*
+ * 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.tv.tuner.cts;
+
+import static org.junit.Assert.assertNotNull;
+
+import android.content.Context;
+import android.media.tv.tuner.Descrambler;
+import android.media.tv.tuner.Tuner;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class TunerTest {
+ private static final String TAG = "MediaTunerTest";
+
+ private Context mContext;
+
+ @Before
+ public void setUp() throws Exception {
+ mContext = InstrumentationRegistry.getTargetContext();
+ }
+
+ @After
+ public void tearDown() {
+ }
+
+ @Test
+ public void testTunerConstructor() throws Exception {
+ if (!hasTuner()) return;
+ Tuner tuner = new Tuner(mContext, "123", 1);
+ assertNotNull(tuner);
+ }
+
+ private boolean hasTuner() {
+ return mContext.getPackageManager().hasSystemFeature("android.hardware.tv.tuner");
+ }
+}
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/AutofillHighlightTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/AutofillHighlightTests.java
index e02506f..a936dfa 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/AutofillHighlightTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/AutofillHighlightTests.java
@@ -56,7 +56,8 @@
ActivityTestBase.TEST_HEIGHT);
autofilledDrawable.draw(canvas);
- createTest().addLayout(R.layout.simple_white_layout, view -> view.setAutofilled(true))
+ createTest()
+ .addLayout(R.layout.simple_white_layout, view -> view.setAutofilled(true, false))
.runWithVerifier(new GoldenImageVerifier(goldenBitmap, new MSSIMComparer(0.99)));
}
}
diff --git a/tests/tests/view/src/android/view/cts/PixelCopyTest.java b/tests/tests/view/src/android/view/cts/PixelCopyTest.java
index 51288cf..85c4094 100644
--- a/tests/tests/view/src/android/view/cts/PixelCopyTest.java
+++ b/tests/tests/view/src/android/view/cts/PixelCopyTest.java
@@ -796,12 +796,12 @@
assertBitmapNotColor("Left edge", bitmap, edgeColor, 2, bitmap.getHeight() / 2);
assertBitmapColor("Bottom edge", bitmap, edgeColor,
- bitmap.getWidth() / 2, bitmap.getHeight() - 1);
+ bitmap.getWidth() / 2, bitmap.getHeight() - 2);
assertBitmapNotColor("Bottom edge", bitmap, edgeColor,
bitmap.getWidth() / 2, bitmap.getHeight() - 3);
assertBitmapColor("Right edge", bitmap, edgeColor,
- bitmap.getWidth() - 1, bitmap.getHeight() / 2);
+ bitmap.getWidth() - 2, bitmap.getHeight() / 2);
assertBitmapNotColor("Right edge", bitmap, edgeColor,
bitmap.getWidth() - 3, bitmap.getHeight() / 2);
}
diff --git a/tests/tests/webkit/src/android/webkit/cts/WebViewClientTest.java b/tests/tests/webkit/src/android/webkit/cts/WebViewClientTest.java
index 68b0126..aaccdda 100644
--- a/tests/tests/webkit/src/android/webkit/cts/WebViewClientTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/WebViewClientTest.java
@@ -631,8 +631,7 @@
* Modifications to this test should be reflected in that test as necessary. See
* http://go/modifying-webview-cts.
*/
- // TODO(ntfschr): re-enable when https://crbug.com/1006953 is fixed and dropped into Android.
- public void disabled_testOnSafeBrowsingHitBackToSafety() throws Throwable {
+ public void testOnSafeBrowsingHitBackToSafety() throws Throwable {
if (!NullWebViewUtils.isWebViewAvailable()) {
return;
}
@@ -672,8 +671,7 @@
* Modifications to this test should be reflected in that test as necessary. See
* http://go/modifying-webview-cts.
*/
- // TODO(ntfschr): re-enable when https://crbug.com/1006953 is fixed and dropped into Android.
- public void disabled_testOnSafeBrowsingHitProceed() throws Throwable {
+ public void testOnSafeBrowsingHitProceed() throws Throwable {
if (!NullWebViewUtils.isWebViewAvailable()) {
return;
}
@@ -734,26 +732,22 @@
}
}
- // TODO(ntfschr): re-enable when https://crbug.com/1006953 is fixed and dropped into Android.
- public void disabled_testOnSafeBrowsingMalwareCode() throws Throwable {
+ public void testOnSafeBrowsingMalwareCode() throws Throwable {
testOnSafeBrowsingCode(TEST_SAFE_BROWSING_MALWARE_URL,
WebViewClient.SAFE_BROWSING_THREAT_MALWARE);
}
- // TODO(ntfschr): re-enable when https://crbug.com/1006953 is fixed and dropped into Android.
- public void disabled_testOnSafeBrowsingPhishingCode() throws Throwable {
+ public void testOnSafeBrowsingPhishingCode() throws Throwable {
testOnSafeBrowsingCode(TEST_SAFE_BROWSING_PHISHING_URL,
WebViewClient.SAFE_BROWSING_THREAT_PHISHING);
}
- // TODO(ntfschr): re-enable when https://crbug.com/1006953 is fixed and dropped into Android.
- public void disabled_testOnSafeBrowsingUnwantedSoftwareCode() throws Throwable {
+ public void testOnSafeBrowsingUnwantedSoftwareCode() throws Throwable {
testOnSafeBrowsingCode(TEST_SAFE_BROWSING_UNWANTED_SOFTWARE_URL,
WebViewClient.SAFE_BROWSING_THREAT_UNWANTED_SOFTWARE);
}
- // TODO(ntfschr): re-enable when https://crbug.com/1006953 is fixed and dropped into Android.
- public void disabled_testOnSafeBrowsingBillingCode() throws Throwable {
+ public void testOnSafeBrowsingBillingCode() throws Throwable {
testOnSafeBrowsingCode(TEST_SAFE_BROWSING_BILLING_URL,
WebViewClient.SAFE_BROWSING_THREAT_BILLING);
}
diff --git a/tests/tests/widget/src/android/widget/cts/EditTextTest.java b/tests/tests/widget/src/android/widget/cts/EditTextTest.java
index 29990eb..b6c8548 100644
--- a/tests/tests/widget/src/android/widget/cts/EditTextTest.java
+++ b/tests/tests/widget/src/android/widget/cts/EditTextTest.java
@@ -35,6 +35,7 @@
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.util.Xml;
+import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.EditText;
import android.widget.TextView.BufferType;
@@ -50,6 +51,8 @@
import org.junit.runner.RunWith;
import org.xmlpull.v1.XmlPullParser;
+import java.util.List;
+
@SmallTest
@RunWith(AndroidJUnit4.class)
public class EditTextTest {
@@ -366,6 +369,22 @@
assertEquals(Layout.BREAK_STRATEGY_SIMPLE, editText.getBreakStrategy());
}
+ @UiThreadTest
+ @Test
+ public void testOnInitializeA11yNodeInfo_hasAccessibilityActions() {
+ mEditText1.setText("android");
+ final AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain();
+ mEditText1.onInitializeAccessibilityNodeInfo(info);
+ List<AccessibilityNodeInfo.AccessibilityAction> actionList = info.getActionList();
+ assertTrue("info's isLongClickable should be true",
+ info.isLongClickable());
+ assertTrue("info should have ACTION_LONG_CLICK",
+ actionList.contains(AccessibilityNodeInfo.AccessibilityAction.ACTION_LONG_CLICK));
+ assertTrue("info should have ACTION_SET_TEXT",
+ actionList.contains(AccessibilityNodeInfo.AccessibilityAction.ACTION_SET_TEXT));
+
+ }
+
private class MockEditText extends EditText {
public MockEditText(Context context) {
super(context);
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 216d764..4e2a441 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
@@ -490,6 +490,7 @@
charsKeyNames.add(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP.getName());
charsKeyNames.add(CameraCharacteristics.SCALER_CROPPING_TYPE.getName());
charsKeyNames.add(CameraCharacteristics.SCALER_MANDATORY_STREAM_COMBINATIONS.getName());
+ charsKeyNames.add(CameraCharacteristics.SCALER_MANDATORY_CONCURRENT_STREAM_COMBINATIONS.getName());
charsKeyNames.add(CameraCharacteristics.SCALER_AVAILABLE_ROTATE_AND_CROP_MODES.getName());
charsKeyNames.add(CameraCharacteristics.SENSOR_REFERENCE_ILLUMINANT1.getName());
charsKeyNames.add(CameraCharacteristics.SENSOR_REFERENCE_ILLUMINANT2.getName());