Merge "update attention management test for M release" into mnc-dev
diff --git a/CtsTestCaseList.mk b/CtsTestCaseList.mk
index beb9895..0950994 100644
--- a/CtsTestCaseList.mk
+++ b/CtsTestCaseList.mk
@@ -172,6 +172,7 @@
CtsNativeOpenGLTestCases \
CtsNdefTestCases \
CtsNetTestCases \
+ CtsNetTestCasesLegacyApi22 \
CtsOpenGLTestCases \
CtsOpenGlPerfTestCases \
CtsOsTestCases \
diff --git a/apps/CameraITS/tests/scene1/test_param_noise_reduction.py b/apps/CameraITS/tests/scene1/test_param_noise_reduction.py
index f4f0d56..2c8d73b 100644
--- a/apps/CameraITS/tests/scene1/test_param_noise_reduction.py
+++ b/apps/CameraITS/tests/scene1/test_param_noise_reduction.py
@@ -116,7 +116,11 @@
# Verify MINIMAL(3) is not better than HQ(2)
assert(variances[j][3] >
variances[j][2] * (1.0 - RELATIVE_ERROR_TOLERANCE))
- if its.caps.noise_reduction_mode(props, 4):
+ if its.caps.noise_reduction_mode(props, 4):
+ # Verify ZSL(4) is close to MINIMAL(3)
+ assert(numpy.isclose(variances[j][4], variances[j][3],
+ RELATIVE_ERROR_TOLERANCE))
+ elif its.caps.noise_reduction_mode(props, 4):
# Verify ZSL(4) is close to OFF(0)
assert(numpy.isclose(variances[j][4], variances[j][0],
RELATIVE_ERROR_TOLERANCE))
diff --git a/apps/CameraITS/tests/scene1/test_reprocess_noise_reduction.py b/apps/CameraITS/tests/scene1/test_reprocess_noise_reduction.py
index aeeae33..757dfeb 100644
--- a/apps/CameraITS/tests/scene1/test_reprocess_noise_reduction.py
+++ b/apps/CameraITS/tests/scene1/test_reprocess_noise_reduction.py
@@ -107,10 +107,12 @@
print "Variances with NR mode [0,1,2,3,4]:", variances
# Draw a plot.
- for nr_mode in range(5):
- if not its.caps.noise_reduction_mode(props, nr_mode):
- continue
- pylab.plot(range(3), variances[nr_mode], "rgbcm"[nr_mode])
+ for chan in range(3):
+ line = []
+ for nr_mode in range(5):
+ line.append(variances[nr_mode][chan])
+ pylab.plot(range(5), line, "rgb"[chan])
+
matplotlib.pyplot.savefig("%s_plot_%s_variances.png" %
(NAME, reprocess_format))
@@ -133,9 +135,13 @@
# Verify MINIMAL(3) is not better than HQ(2)
assert(variances[3][j] >
variances[2][j] * (1.0 - RELATIVE_ERROR_TOLERANCE))
- # Verify ZSL(4) is close to OFF(0)
- assert(numpy.isclose(variances[4][j], variances[0][j],
- RELATIVE_ERROR_TOLERANCE))
+ # Verify ZSL(4) is close to MINIMAL(3)
+ assert(numpy.isclose(variances[4][j], variances[3][j],
+ RELATIVE_ERROR_TOLERANCE))
+ else:
+ # Verify ZSL(4) is close to OFF(0)
+ assert(numpy.isclose(variances[4][j], variances[0][j],
+ RELATIVE_ERROR_TOLERANCE))
if __name__ == '__main__':
main()
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index 47eb16f..272e192 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -1369,7 +1369,12 @@
android:theme="@android:style/Theme.NoDisplay"
android:noHistory="true"
android:autoRemoveFromRecents="true"
- android:stateNotNeeded="true"/>
+ android:stateNotNeeded="true">
+ </activity>
+
+ <activity android:name=".managedprovisioning.KeyguardDisabledFeaturesActivity"
+ android:label="@string/provisioning_byod_keyguard_disabled_features">
+ </activity>
<activity android:name=".managedprovisioning.WifiLockdownTestActivity"
android:label="@string/device_owner_wifi_lockdown_test">
@@ -1416,6 +1421,8 @@
<action android:name="com.android.cts.verifier.managedprovisioning.BYOD_CAPTURE_AND_CHECK_IMAGE" />
<action android:name="com.android.cts.verifier.managedprovisioning.BYOD_CAPTURE_AND_CHECK_VIDEO" />
<action android:name="com.android.cts.verifier.managedprovisioning.BYOD_CAPTURE_AND_CHECK_AUDIO" />
+ <action android:name="com.android.cts.verifier.managedprovisioning.BYOD_KEYGUARD_DISABLED_FEATURES" />
+ <action android:name="com.android.cts.verifier.managedprovisioning.BYOD_LOCKNOW" />
<category android:name="android.intent.category.DEFAULT"></category>
</intent-filter>
</activity>
@@ -1455,6 +1462,7 @@
<activity android:name=".managedprovisioning.WorkNotificationTestActivity">
<intent-filter>
<action android:name="com.android.cts.verifier.managedprovisioning.WORK_NOTIFICATION" />
+ <action android:name="com.android.cts.verifier.managedprovisioning.LOCKSCREEN_NOTIFICATION" />
<action android:name="com.android.cts.verifier.managedprovisioning.CLEAR_WORK_NOTIFICATION" />
<category android:name="android.intent.category.DEFAULT"></category>
</intent-filter>
@@ -1632,6 +1640,18 @@
<meta-data android:name="test_excluded_features" android:value="android.hardware.type.television" />
</activity>
+ <activity android:name=".audio.AudioFrequencyLineActivity"
+ android:label="@string/audio_frequency_line_test">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.cts.intent.category.MANUAL_TEST" />
+ </intent-filter>
+ <meta-data android:name="test_category" android:value="@string/test_category_audio" />
+ <meta-data android:name="test_required_features" android:value="android.hardware.microphone" />
+ <meta-data android:name="test_excluded_features" android:value="android.hardware.type.watch" />
+ <meta-data android:name="test_excluded_features" android:value="android.hardware.type.television" />
+ </activity>
+
<service android:name=".tv.MockTvInputService"
android:permission="android.permission.BIND_TV_INPUT">
<intent-filter>
diff --git a/apps/CtsVerifier/res/layout/audio_frequency_line_activity.xml b/apps/CtsVerifier/res/layout/audio_frequency_line_activity.xml
new file mode 100644
index 0000000..69e3bc7
--- /dev/null
+++ b/apps/CtsVerifier/res/layout/audio_frequency_line_activity.xml
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:padding="10dip"
+ android:orientation="vertical">
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:scrollbars="vertical"
+ android:gravity="bottom"
+ android:id="@+id/info_text"
+ android:text="@string/audio_frequency_line_instructions" />
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+ <Button
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:id="@+id/audio_frequency_line_plug_ready_btn"
+ android:text="@string/audio_frequency_line_plug_ready_btn"/>
+
+ <LinearLayout
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:id="@+id/audio_frequency_line_layout">
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/audio_frequency_line_test_btn"
+ android:id="@+id/audio_frequency_line_test_btn"/>
+
+ <ProgressBar
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:id="@+id/audio_frequency_line_progress_bar"/>
+ </LinearLayout>
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/audio_frequency_line_results_text"
+ android:id="@+id/audio_frequency_line_results_text"/>
+
+ </LinearLayout>
+ </LinearLayout>
+
+ <include layout="@layout/pass_fail_buttons" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/apps/CtsVerifier/res/raw/stereo_mono_white_noise_48.mp3 b/apps/CtsVerifier/res/raw/stereo_mono_white_noise_48.mp3
new file mode 100644
index 0000000..e877fc1
--- /dev/null
+++ b/apps/CtsVerifier/res/raw/stereo_mono_white_noise_48.mp3
Binary files differ
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index 3b26458..b8bd395 100644
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -1448,6 +1448,42 @@
\n
Verify that you are prompted with the above choices and both options work as intended. Then mark this test accordingly.
</string>
+ <string name="provisioning_byod_keyguard_disabled_features">Keyguard disabled features</string>
+ <string name="provisioning_byod_keyguard_disabled_features_info">
+ This test exercises Keyguard Disabled Features. Follow instructions above.
+ </string>
+ <string name="provisioning_byod_keyguard_disabled_features_instruction">
+ Please press the \"Prepare test\" button to disable trust agents.\n
+ Then please press through the following verification steps.\n
+ Note: Device password will be set to \"testpassword\". After leaving the screen device password be cleared.
+ </string>
+ <string name="provisioning_byod_keyguard_disabled_features_prepare_button">Prepare test</string>
+ <string name="provisioning_byod_disable_trust_agents">Disable trust agents</string>
+ <string name="provisioning_byod_disable_trust_agents_instruction">
+ Please press the Go button to go to Settings > Security. Then go to Trusted agents and\n
+ check if the agents are shown as disabled by the administrator.
+ Then please press Back and mark the test as \"Pass\" or \"Fail\".
+ </string>
+ <string name="provisioning_byod_fingerprint_disabled_in_settings">Fingerprint is disabled in Settings</string>
+ <string name="provisioning_byod_fingerprint_disabled_in_settings_instruction">
+ Please press the Go button to go to Settings > Security. Then go to Fingerprint and\n
+ check if the screen is shown as disabled by the administrator.
+ Then please press Back and mark the test as \"Pass\" or \"Fail\".
+ </string>
+ <string name="provisioning_byod_disable_fingerprint">Fingerprint disabled on keyguard</string>
+ <string name="provisioning_byod_disable_fingerprint_instruction">
+ Please press the Go button to lock the screen. Then try to log in using the fingerprint reader.\n
+ Expected result is you cannot log in using your fingerprint.\n
+ After you log back in, please navigate back to CtsVerifier and mark the test as \"Pass\" or \"Fail\".
+ </string>
+ <string name="provisioning_byod_disable_notifications">Notifications disabled on keyguard</string>
+ <string name="provisioning_byod_disable_notifications_instruction">
+ Please press the Go button to lock the screen. Wait a couple of seconds and look out for a
+ notification from CtsVerifier.\n
+ Expected result is the notification is shown as \"Contents hidden\", you can not see the contents
+ (Which would read \"This is a work notification\").\n
+ After you log back in, please navigate back to CtsVerifier and mark the test as \"Pass\" or \"Fail\".
+ </string>
<string name="provisioning_byod_work_notification">Work notification is badged</string>
<string name="provisioning_byod_work_notification_instruction">
Please press the Go button to trigger a notification.\n
@@ -1690,6 +1726,40 @@
<string name="activity_not_found">No activity found to handle intent: %s</string>
<string name="open_settings_button_label">Open Application Settings</string>
<string name="finish_button_label">Finish</string>
+ <string name="device_owner_device_admin_visible">Device administrator settings</string>
+ <string name="device_owner_device_admin_visible_info">
+ Please press the Go button to open the Security page in Settings.
+ Navigate to Device administrators and confirm that:\n
+ \n
+ - \"CTS Verifier - AfW Admin\" exists and is activated.\n
+ - \"CTS Verifier - AfW Admin\" cannot be disabled.\n
+ \n
+ Use the Back button to return to this page.
+ </string>
+ <string name="device_owner_disallow_config_bt">Disallow configuring Bluetooth</string>
+ <string name="device_owner_disallow_config_bt_info">
+ Please press the Set restriction button to set the user restriction.
+ Then press Go to open the Bluetooth page in Settings.
+ Confirm that:\n
+ \n
+ - You cannot view Bluetooth devices in range.\n
+ - You cannot edit, add or remove any already paired devices.\n
+ \n
+ Use the Back button to return to this page.
+ </string>
+ <string name="device_owner_disallow_config_wifi">Disallow configuring WiFi</string>
+ <string name="device_owner_disallow_config_wifi_info">
+ Please press the Set restriction button to set the user restriction.
+ Then press Go to open the WiFi page in Settings.
+ Confirm that:\n
+ \n
+ - You cannot view WiFi networks in range.\n
+ - You cannot edit, add or remove any existing WiFi configs.\n
+ \n
+ Use the Back button to return to this page.
+ </string>
+ <string name="device_owner_user_restriction_set">Set restriction</string>
+ <string name="device_owner_settings_go">Go</string>
<!-- Strings for JobScheduler Tests -->
<string name="js_test_description">This test is mostly automated, but requires some user interaction. You can pass this test once the list items below are checked.</string>
@@ -1911,4 +1981,22 @@
<string name="audio_loopback_test_btn">Test</string>
<string name="audio_loopback_results_text">Results...</string>
+ <!-- Audio Frequency Line Test -->
+ <string name="audio_frequency_line_test">Audio Frequency Line Test</string>
+ <string name="audio_frequency_line_info">
+ This test requires the Loopback Plug. Please connect a Loopback Plug on the headset
+ connector, and proceed with the instructions on the screen.
+ The system will measure the input-output audio latency by injecting a pulse on the output,
+ and computing the distance between replicas of the pulse.
+ You can vary the Audio Level slider to ensure the pulse will feed back at adecuate levels.
+ Repeat until a confidence level >= 0.6 is achieved.
+ </string>
+ <string name="audio_frequency_line_instructions">
+ Please connect a "Loopback Plug" and press "Loopback Plug Ready".
+ </string>
+ <string name="audio_frequency_line_plug_ready_btn">Loopback Plug Ready</string>
+
+ <string name="audio_frequency_line_test_btn">Test</string>
+ <string name="audio_frequency_line_results_text">Results...</string>
+
</resources>
diff --git a/apps/CtsVerifier/res/xml/device_admin_byod.xml b/apps/CtsVerifier/res/xml/device_admin_byod.xml
index 61238aa..ce44794 100644
--- a/apps/CtsVerifier/res/xml/device_admin_byod.xml
+++ b/apps/CtsVerifier/res/xml/device_admin_byod.xml
@@ -20,6 +20,8 @@
<encrypted-storage />
<wipe-data />
<reset-password />
+ <disable-keyguard-features />
+ <force-lock />
</uses-policies>
</device-admin>
<!-- END_INCLUDE(meta_data) -->
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioBandSpecs.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioBandSpecs.java
new file mode 100644
index 0000000..9af4af1
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioBandSpecs.java
@@ -0,0 +1,90 @@
+/*
+ * 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;
+
+public class AudioBandSpecs {
+ double mFreqStart;
+ double mFreqStop;
+ double mRippleStartTop;
+ double mRippleStartBottom;
+
+ double mRippleStopTop;
+ double mRippleStopBottom;
+
+ double mOffset;
+
+ public AudioBandSpecs(double fStart, double fStop, double startTop, double startBottom,
+ double stopTop, double stopBottom) {
+ initFreq(fStart, fStop);
+ initRipple(startTop, startBottom, stopTop, stopBottom);
+ setOffset(0);
+ }
+
+ public void initRipple(double startTop, double startBottom, double stopTop, double stopBottom) {
+ mRippleStartTop = startTop;
+ mRippleStartBottom = startBottom;
+ mRippleStopTop = stopTop;
+ mRippleStopBottom = stopBottom;
+ // note: top should be >= bottom, but no check is done here.
+ }
+
+ public void initFreq(double fStart, double fStop) {
+ mFreqStart = fStart;
+ mFreqStop = fStop;
+ }
+
+ public void setOffset(double offset) {
+ mOffset = offset;
+ }
+
+ /**
+ * Check if the given point is in bounds in this band.
+ */
+ public boolean isInBounds(double freq, double value) {
+ if (freq < mFreqStart || freq > mFreqStop) {
+ return false;
+ }
+
+ double d = mFreqStop - mFreqStart;
+ if (d <= 0) {
+ return false;
+ }
+
+ double e = freq - mFreqStart;
+ double vTop = (e / d) * (mRippleStopTop - mRippleStartTop) + mRippleStartTop + mOffset;
+ if (value > vTop) {
+ return false;
+ }
+
+ double vBottom = (e / d) * (mRippleStopBottom - mRippleStartBottom) + mRippleStartBottom
+ + mOffset;
+
+ if (value < vBottom) {
+ return false;
+ }
+ return true;
+ }
+
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append(String.format("Freq %.1f - %.1f |", mFreqStart, mFreqStop));
+ sb.append(String.format("start [%.1f : %.1f] |", mRippleStartTop, mRippleStartBottom));
+ sb.append(String.format("stop [%.1f : %.1f] |", mRippleStopTop, mRippleStopBottom));
+ sb.append(String.format("offset %.1f", mOffset));
+ return sb.toString();
+ }
+}
\ No newline at end of file
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioFrequencyLineActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioFrequencyLineActivity.java
new file mode 100644
index 0000000..d3e2571
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioFrequencyLineActivity.java
@@ -0,0 +1,664 @@
+/*
+ * 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 com.android.cts.verifier.PassFailButtons;
+import com.android.cts.verifier.R;
+import com.android.cts.verifier.audio.wavelib.*;
+import com.android.compatibility.common.util.ReportLog;
+import com.android.compatibility.common.util.ResultType;
+import com.android.compatibility.common.util.ResultUnit;
+import android.content.Context;
+
+import android.media.AudioDeviceCallback;
+import android.media.AudioDeviceInfo;
+import android.media.AudioFormat;
+import android.media.AudioManager;
+import android.media.AudioTrack;
+import android.media.AudioRecord;
+import android.media.MediaRecorder;
+
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.os.SystemClock;
+
+import android.util.Log;
+
+import android.view.View;
+import android.view.View.OnClickListener;
+
+import android.widget.Button;
+import android.widget.TextView;
+import android.widget.SeekBar;
+import android.widget.LinearLayout;
+import android.widget.ProgressBar;
+
+/**
+ * Tests Audio Device roundtrip latency by using a loopback plug.
+ */
+public class AudioFrequencyLineActivity extends PassFailButtons.Activity implements Runnable,
+ AudioRecord.OnRecordPositionUpdateListener {
+ private static final String TAG = "AudioFrequencyLineActivity";
+
+ static final int TEST_STARTED = 900;
+ static final int TEST_ENDED = 901;
+ static final int TEST_MESSAGE = 902;
+ static final double MIN_ENERGY_BAND_1 = -20.0;
+ static final double MIN_FRACTION_POINTS_IN_BAND = 0.3;
+
+ OnBtnClickListener mBtnClickListener = new OnBtnClickListener();
+ Context mContext;
+
+ Button mLoopbackPlugReady;
+ LinearLayout mLinearLayout;
+ Button mTestButton;
+ TextView mResultText;
+ ProgressBar mProgressBar;
+ //recording
+ private boolean mIsRecording = false;
+ private final Object mRecordingLock = new Object();
+ private AudioRecord mRecorder;
+ private int mMinRecordBufferSizeInSamples = 0;
+ private short[] mAudioShortArray;
+ private short[] mAudioShortArray2;
+
+ private final int mBlockSizeSamples = 1024;
+ private final int mSamplingRate = 48000;
+ private final int mSelectedRecordSource = MediaRecorder.AudioSource.VOICE_RECOGNITION;
+ private final int mChannelConfig = AudioFormat.CHANNEL_IN_MONO;
+ private final int mAudioFormat = AudioFormat.ENCODING_PCM_16BIT;
+ private volatile Thread mRecordThread;
+ private boolean mRecordThreadShutdown = false;
+
+ PipeShort mPipe = new PipeShort(65536);
+ SoundPlayerObject mSPlayer;
+
+ private DspBufferComplex mC;
+ private DspBufferDouble mData;
+
+ private DspWindow mWindow;
+ private DspFftServer mFftServer;
+ private VectorAverage mFreqAverageMain = new VectorAverage();
+
+ private VectorAverage mFreqAverage0 = new VectorAverage();
+ private VectorAverage mFreqAverage1 = new VectorAverage();
+
+ private int mCurrentTest = -1;
+ int mBands = 4;
+ AudioBandSpecs[] bandSpecsArray = new AudioBandSpecs[mBands];
+
+ int mMaxLevel;
+ private class OnBtnClickListener implements OnClickListener {
+ @Override
+ public void onClick(View v) {
+ switch (v.getId()) {
+ case R.id.audio_frequency_line_plug_ready_btn:
+ Log.i(TAG, "audio loopback plug ready");
+ //enable all the other views.
+ enableLayout(true);
+ break;
+ case R.id.audio_frequency_line_test_btn:
+ Log.i(TAG, "audio loopback test");
+ startAudioTest();
+ break;
+ }
+ }
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.audio_frequency_line_activity);
+
+ mContext = this;
+
+ mLoopbackPlugReady = (Button)findViewById(R.id.audio_frequency_line_plug_ready_btn);
+ mLoopbackPlugReady.setOnClickListener(mBtnClickListener);
+ mLinearLayout = (LinearLayout)findViewById(R.id.audio_frequency_line_layout);
+ mTestButton = (Button)findViewById(R.id.audio_frequency_line_test_btn);
+ mTestButton.setOnClickListener(mBtnClickListener);
+ mResultText = (TextView)findViewById(R.id.audio_frequency_line_results_text);
+ mProgressBar = (ProgressBar)findViewById(R.id.audio_frequency_line_progress_bar);
+ showWait(false);
+ enableLayout(false); //disabled all content
+
+ mSPlayer = new SoundPlayerObject();
+ mSPlayer.setSoundWithResId(getApplicationContext(), R.raw.stereo_mono_white_noise_48);
+ mSPlayer.setBalance(0.5f);
+
+ //Init FFT stuff
+ mAudioShortArray2 = new short[mBlockSizeSamples*2];
+ mData = new DspBufferDouble(mBlockSizeSamples);
+ mC = new DspBufferComplex(mBlockSizeSamples);
+ mFftServer = new DspFftServer(mBlockSizeSamples);
+
+ int overlap = mBlockSizeSamples / 2;
+
+ mWindow = new DspWindow(DspWindow.WINDOW_HANNING, mBlockSizeSamples, overlap);
+
+ setPassFailButtonClickListeners();
+ getPassButton().setEnabled(false);
+ setInfoResources(R.string.audio_frequency_line_test,
+ R.string.audio_frequency_line_info, -1);
+
+ //Init bands
+ bandSpecsArray[0] = new AudioBandSpecs(
+ 50, 500, /* frequency start,stop */
+ -20.0, -50, /* start top,bottom value */
+ 4.0, -4.0 /* stop top,bottom value */);
+
+ bandSpecsArray[1] = new AudioBandSpecs(
+ 500,4000, /* frequency start,stop */
+ 4.0, -4.0, /* start top,bottom value */
+ 4.0, -4.0 /* stop top,bottom value */);
+
+ bandSpecsArray[2] = new AudioBandSpecs(
+ 4000, 12000, /* frequency start,stop */
+ 4.0, -4.0, /* start top,bottom value */
+ 5.0, -5.0 /* stop top,bottom value */);
+
+ bandSpecsArray[3] = new AudioBandSpecs(
+ 12000, 20000, /* frequency start,stop */
+ 5.0, -5.0, /* start top,bottom value */
+ 5.0, -30.0 /* stop top,bottom value */);
+ }
+
+ /**
+ * enable test ui elements
+ */
+ private void enableLayout(boolean enable) {
+ for (int i = 0; i < mLinearLayout.getChildCount(); i++) {
+ View view = mLinearLayout.getChildAt(i);
+ view.setEnabled(enable);
+ }
+ }
+
+ /**
+ * show active progress bar
+ */
+ private void showWait(boolean show) {
+ if (show) {
+ mProgressBar.setVisibility(View.VISIBLE);
+ } else {
+ mProgressBar.setVisibility(View.INVISIBLE);
+ }
+ }
+
+ private void setMaxLevel() {
+ AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
+ mMaxLevel = am.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
+ am.setStreamVolume(AudioManager.STREAM_MUSIC, (int)(mMaxLevel), 0);
+ }
+
+ /**
+ * Start the loopback audio test
+ */
+ private void startAudioTest() {
+ if (mTestThread != null && !mTestThread.isAlive()) {
+ mTestThread = null; //kill it.
+ }
+
+ if (mTestThread == null) {
+ Log.v(TAG,"Executing test Thread");
+ mTestThread = new Thread(mPlayRunnable);
+ getPassButton().setEnabled(false);
+ if (!mSPlayer.isAlive())
+ mSPlayer.start();
+ mTestThread.start();
+ } else {
+ Log.v(TAG,"test Thread already running.");
+ }
+ }
+
+ Thread mTestThread;
+ Runnable mPlayRunnable = new Runnable() {
+ public void run() {
+ Message msg = Message.obtain();
+ msg.what = TEST_STARTED;
+ mMessageHandler.sendMessage(msg);
+ setMaxLevel();
+
+ sendMessage("Testing Left Capture");
+ mCurrentTest = 0;
+ mFreqAverage0.reset();
+ mSPlayer.setBalance(0.0f);
+ play();
+
+ sendMessage("Testing Right Capture");
+ mCurrentTest = 1;
+ mFreqAverage1.reset();
+ mSPlayer.setBalance(1.0f);
+ play();
+
+ mCurrentTest = -1;
+ sendMessage("Testing Completed");
+
+ Message msg2 = Message.obtain();
+ msg2.what = TEST_ENDED;
+ mMessageHandler.sendMessage(msg2);
+ }
+
+ private void play() {
+ startRecording();
+ mSPlayer.play(true);
+
+ try {
+ Thread.sleep(2000);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+
+ mSPlayer.play(false);
+ stopRecording();
+ }
+
+ private void sendMessage(String str) {
+ Message msg = Message.obtain();
+ msg.what = TEST_MESSAGE;
+ msg.obj = str;
+ mMessageHandler.sendMessage(msg);
+ }
+ };
+
+ private Handler mMessageHandler = new Handler() {
+ public void handleMessage(Message msg) {
+ super.handleMessage(msg);
+ switch (msg.what) {
+ case TEST_STARTED:
+ showWait(true);
+ getPassButton().setEnabled(false);
+ break;
+ case TEST_ENDED:
+ showWait(false);
+ computeResults();
+ break;
+ case TEST_MESSAGE:
+ String str = (String)msg.obj;
+ if (str != null) {
+ mResultText.setText(str);
+ }
+ break;
+ default:
+ Log.e(TAG, String.format("Unknown message: %d", msg.what));
+ }
+ }
+ };
+
+ private class Results {
+ private String mLabel;
+ public double[] mValuesLog;
+ int[] mPointsPerBand = new int[mBands];
+ double[] mAverageEnergyPerBand = new double[mBands];
+ int[] mInBoundPointsPerBand = new int[mBands];
+ public Results(String label) {
+ mLabel = label;
+ }
+
+ //append results
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append(String.format("Channel %s\n", mLabel));
+ sb.append("Level in Band 1 : " + (testLevel() ? "OK" :"FAILED") +"\n");
+ for (int b = 0; b < mBands; b++) {
+ double percent = 0;
+ if (mPointsPerBand[b] > 0) {
+ percent = 100.0 * (double)mInBoundPointsPerBand[b] / mPointsPerBand[b];
+ }
+ sb.append(String.format(
+ " Band %d: Av. Level: %.1f dB InBand: %d/%d (%.1f%%) %s\n",
+ b, mAverageEnergyPerBand[b],
+ mInBoundPointsPerBand[b],
+ mPointsPerBand[b],
+ percent,
+ (testInBand(b) ? "OK" : "FAILED")));
+ }
+ return sb.toString();
+ }
+
+ public boolean testLevel() {
+ if (mAverageEnergyPerBand[1] >= MIN_ENERGY_BAND_1) {
+ return true;
+ }
+ return false;
+ }
+
+ public boolean testInBand(int b) {
+ if (b >= 0 && b < mBands && mPointsPerBand[b] > 0) {
+ if ((double)mInBoundPointsPerBand[b] / mPointsPerBand[b] >
+ MIN_FRACTION_POINTS_IN_BAND)
+ return true;
+ }
+ return false;
+ }
+
+ public boolean testAll() {
+ if (!testLevel()) {
+ return false;
+ }
+ for (int b = 0; b < mBands; b++) {
+ if (!testInBand(b)) {
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+
+ /**
+ * compute test results
+ */
+ private void computeResults() {
+ Results resultsLeft = new Results("Left");
+ computeResultsForVector(mFreqAverage0, resultsLeft);
+ Results resultsRight = new Results("Right");
+ computeResultsForVector(mFreqAverage1, resultsRight);
+ if (resultsLeft.testAll() && resultsRight.testAll()) {
+ //enable button
+ getPassButton().setEnabled(true);
+ }
+ }
+
+ private void computeResultsForVector(VectorAverage freqAverage,Results results) {
+
+ int points = freqAverage.getSize();
+ if (points > 0) {
+ //compute vector in db
+ double[] values = new double[points];
+ freqAverage.getData(values, false);
+ results.mValuesLog = new double[points];
+ for (int i = 0; i < points; i++) {
+ results.mValuesLog[i] = 20 * Math.log10(values[i]);
+ }
+
+ int currentBand = 0;
+ for (int i = 0; i < points; i++) {
+ double freq = (double)mSamplingRate * i / (double)mBlockSizeSamples;
+ if (freq > bandSpecsArray[currentBand].mFreqStop) {
+ currentBand++;
+ if (currentBand >= mBands)
+ break;
+ }
+
+ if (freq >= bandSpecsArray[currentBand].mFreqStart) {
+ results.mAverageEnergyPerBand[currentBand] += results.mValuesLog[i];
+ results.mPointsPerBand[currentBand]++;
+ }
+ }
+
+ for (int b = 0; b < mBands; b++) {
+ if (results.mPointsPerBand[b] > 0) {
+ results.mAverageEnergyPerBand[b] =
+ results.mAverageEnergyPerBand[b] / results.mPointsPerBand[b];
+ }
+ }
+
+ //set offset relative to band 1 level
+ for (int b = 0; b < mBands; b++) {
+ bandSpecsArray[b].setOffset(results.mAverageEnergyPerBand[1]);
+ }
+
+ //test points in band.
+ currentBand = 0;
+ for (int i = 0; i < points; i++) {
+ double freq = (double)mSamplingRate * i / (double)mBlockSizeSamples;
+ if (freq > bandSpecsArray[currentBand].mFreqStop) {
+ currentBand++;
+ if (currentBand >= mBands)
+ break;
+ }
+
+ if (freq >= bandSpecsArray[currentBand].mFreqStart) {
+ double value = results.mValuesLog[i];
+ if (bandSpecsArray[currentBand].isInBounds(freq, value)) {
+ results.mInBoundPointsPerBand[currentBand]++;
+ }
+ }
+ }
+
+ appendResultsToScreen(results.toString());
+ //store results
+ recordTestResults(results);
+ } else {
+ appendResultsToScreen("Failed testing channel " + results.mLabel);
+ }
+ }
+
+ //append results
+ private void appendResultsToScreen(String str) {
+ String currentText = mResultText.getText().toString();
+ mResultText.setText(currentText + "\n" + str);
+ }
+
+ /**
+ * Store test results in log
+ */
+ private void recordTestResults(Results results) {
+ String channelLabel = "channel_" + results.mLabel;
+
+ for (int b = 0; b < mBands; b++) {
+ String bandLabel = String.format(channelLabel + "_%d", b);
+ getReportLog().addValue(
+ bandLabel + "_Level",
+ results.mAverageEnergyPerBand[b],
+ ResultType.HIGHER_BETTER,
+ ResultUnit.NONE);
+
+ getReportLog().addValue(
+ bandLabel + "_pointsinbound",
+ results.mInBoundPointsPerBand[b],
+ ResultType.HIGHER_BETTER,
+ ResultUnit.COUNT);
+
+ getReportLog().addValue(
+ bandLabel + "_pointstotal",
+ results.mPointsPerBand[b],
+ ResultType.NEUTRAL,
+ ResultUnit.COUNT);
+ }
+
+ getReportLog().addValues(channelLabel + "_magnitudeSpectrumLog",
+ results.mValuesLog,
+ ResultType.NEUTRAL,
+ ResultUnit.NONE);
+
+ Log.v(TAG, "Results Recorded");
+ }
+
+ private void startRecording() {
+ synchronized (mRecordingLock) {
+ mIsRecording = true;
+ }
+
+ boolean successful = initRecord();
+ if (successful) {
+ startRecordingForReal();
+ } else {
+ Log.v(TAG, "Recorder initialization error.");
+ synchronized (mRecordingLock) {
+ mIsRecording = false;
+ }
+ }
+ }
+
+ private void startRecordingForReal() {
+ // start streaming
+ if (mRecordThread == null) {
+ mRecordThread = new Thread(AudioFrequencyLineActivity.this);
+ mRecordThread.setName("FrequencyAnalyzerThread");
+ mRecordThreadShutdown = false;
+ }
+ if (!mRecordThread.isAlive()) {
+ mRecordThread.start();
+ }
+
+ mPipe.flush();
+
+ long startTime = SystemClock.uptimeMillis();
+ mRecorder.startRecording();
+ if (mRecorder.getRecordingState() != AudioRecord.RECORDSTATE_RECORDING) {
+ stopRecording();
+ return;
+ }
+ Log.v(TAG, "Start time: " + (long) (SystemClock.uptimeMillis() - startTime) + " ms");
+ }
+
+ private void stopRecording() {
+ synchronized (mRecordingLock) {
+ stopRecordingForReal();
+ mIsRecording = false;
+ }
+ }
+
+ private void stopRecordingForReal() {
+
+ // stop streaming
+ Thread zeThread = mRecordThread;
+ mRecordThread = null;
+ mRecordThreadShutdown = true;
+ if (zeThread != null) {
+ zeThread.interrupt();
+ try {
+ zeThread.join();
+ } catch(InterruptedException e) {
+ Log.v(TAG,"Error shutting down recording thread " + e);
+ //we don't really care about this error, just logging it.
+ }
+ }
+ // release recording resources
+ if (mRecorder != null) {
+ mRecorder.stop();
+ mRecorder.release();
+ mRecorder = null;
+ }
+ }
+
+ private boolean initRecord() {
+ int minRecordBuffSizeInBytes = AudioRecord.getMinBufferSize(mSamplingRate,
+ mChannelConfig, mAudioFormat);
+ Log.v(TAG,"FrequencyAnalyzer: min buff size = " + minRecordBuffSizeInBytes + " bytes");
+ if (minRecordBuffSizeInBytes <= 0) {
+ return false;
+ }
+
+ mMinRecordBufferSizeInSamples = minRecordBuffSizeInBytes / 2;
+ // allocate the byte array to read the audio data
+
+ mAudioShortArray = new short[mMinRecordBufferSizeInSamples];
+
+ Log.v(TAG, "Initiating record:");
+ Log.v(TAG, " using source " + mSelectedRecordSource);
+ Log.v(TAG, " at " + mSamplingRate + "Hz");
+
+ try {
+ mRecorder = new AudioRecord(mSelectedRecordSource, mSamplingRate,
+ mChannelConfig, mAudioFormat, 2 * minRecordBuffSizeInBytes);
+ } catch (IllegalArgumentException e) {
+ return false;
+ }
+ if (mRecorder.getState() != AudioRecord.STATE_INITIALIZED) {
+ mRecorder.release();
+ mRecorder = null;
+ return false;
+ }
+ mRecorder.setRecordPositionUpdateListener(this);
+ mRecorder.setPositionNotificationPeriod(mBlockSizeSamples / 2);
+ return true;
+ }
+
+ // ---------------------------------------------------------
+ // Implementation of AudioRecord.OnPeriodicNotificationListener
+ // --------------------
+ public void onPeriodicNotification(AudioRecord recorder) {
+ int samplesAvailable = mPipe.availableToRead();
+ int samplesNeeded = mBlockSizeSamples;
+ if (samplesAvailable >= samplesNeeded) {
+ mPipe.read(mAudioShortArray2, 0, samplesNeeded);
+
+ //compute stuff.
+ double maxval = Math.pow(2, 15);
+ int clipcount = 0;
+ double cliplevel = (maxval-10) / maxval;
+ double sum = 0;
+ double maxabs = 0;
+ int i;
+ int index = 0;
+
+ for (i = 0; i < samplesNeeded; i++) {
+ double value = mAudioShortArray2[i] / maxval;
+ double valueabs = Math.abs(value);
+
+ if (valueabs > maxabs) {
+ maxabs = valueabs;
+ }
+
+ if (valueabs > cliplevel) {
+ clipcount++;
+ }
+
+ sum += value * value;
+ //fft stuff
+ if (index < mBlockSizeSamples) {
+ mData.mData[index] = value;
+ }
+ index++;
+ }
+
+ //for the current frame, compute FFT and send to the viewer.
+
+ //apply window and pack as complex for now.
+ DspBufferMath.mult(mData, mData, mWindow.mBuffer);
+ DspBufferMath.set(mC, mData);
+ mFftServer.fft(mC, 1);
+
+ double[] halfMagnitude = new double[mBlockSizeSamples / 2];
+ for (i = 0; i < mBlockSizeSamples / 2; i++) {
+ halfMagnitude[i] = Math.sqrt(mC.mReal[i] * mC.mReal[i] + mC.mImag[i] * mC.mImag[i]);
+ }
+
+ mFreqAverageMain.setData(halfMagnitude, false); //average all of them!
+
+ switch(mCurrentTest) {
+ case 0:
+ mFreqAverage0.setData(halfMagnitude, false);
+ break;
+ case 1:
+ mFreqAverage1.setData(halfMagnitude, false);
+ break;
+ }
+ }
+ }
+
+ public void onMarkerReached(AudioRecord track) {
+ }
+
+ // ---------------------------------------------------------
+ // Implementation of Runnable for the audio recording + playback
+ // --------------------
+ public void run() {
+ int nSamplesRead = 0;
+
+ Thread thisThread = Thread.currentThread();
+ while (mRecordThread == thisThread && !mRecordThreadShutdown) {
+ // read from native recorder
+ nSamplesRead = mRecorder.read(mAudioShortArray, 0, mMinRecordBufferSizeInSamples);
+ if (nSamplesRead > 0) {
+ mPipe.write(mAudioShortArray, 0, nSamplesRead);
+ }
+ }
+ }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/SoundPlayerObject.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/SoundPlayerObject.java
new file mode 100644
index 0000000..23b71c0
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/SoundPlayerObject.java
@@ -0,0 +1,215 @@
+/*
+ * 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.content.Context;
+import android.media.AudioFormat;
+import android.media.AudioManager;
+import android.media.AudioTrack;
+import android.media.MediaPlayer;
+import android.net.Uri;
+import android.net.rtp.AudioStream;
+import android.util.Log;
+
+import com.android.cts.verifier.audio.wavelib.PipeShort;
+
+import java.io.IOException;
+
+public class SoundPlayerObject extends Thread {
+ private static final String LOGTAG = "SoundPlayerObject";
+ private MediaPlayer mMediaPlayer;
+ private boolean isInitialized = false;
+ private boolean isRunning = false;
+
+ public PipeShort mPipe = new PipeShort(65536);
+ private short[] mAudioShortArray;
+
+ public AudioTrack mAudioTrack;
+ public int mSamplingRate = 48000;
+ private int mChannelConfigOut = AudioFormat.CHANNEL_OUT_MONO;
+ private int mAudioFormat = AudioFormat.ENCODING_PCM_16BIT;
+ int mMinPlayBufferSizeInBytes = 0;
+ int mMinBufferSizeInSamples = 0;
+
+ private int mStreamType = AudioManager.STREAM_MUSIC;
+ private int mResId = -1;
+ private boolean mUseMediaPlayer = true;
+ private float mBalance = 0.5f; //0 left, 1 right
+
+ public int getCurrentResId() {
+ return mResId;
+ }
+
+ public int getStreamType () {
+ return mStreamType;
+ }
+
+ public void run() {
+ setPriority(Thread.MAX_PRIORITY);
+ isRunning = true;
+ while (isRunning) {
+
+ if (!mUseMediaPlayer && isInitialized && isPlaying()) {
+ int valuesAvailable = mPipe.availableToRead();
+ if (valuesAvailable > 0) {
+
+ int valuesOfInterest = valuesAvailable;
+ if (mMinBufferSizeInSamples < valuesOfInterest) {
+ valuesOfInterest = mMinBufferSizeInSamples;
+ }
+ mPipe.read(mAudioShortArray, 0,valuesOfInterest);
+ //inject into output.
+ mAudioTrack.write(mAudioShortArray, 0, valuesOfInterest);
+ }
+ } else {
+ try {
+ sleep(10);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ public void setBalance(float balance) {
+ mBalance = balance;
+ if (mUseMediaPlayer) {
+ if (mMediaPlayer != null) {
+ float left = Math.min(2.0f * (1.0f - mBalance), 1.0f);
+ float right = Math.min(2.0f * mBalance, 1.0f);
+ mMediaPlayer.setVolume(left, right);
+ log(String.format("Setting balance to %f", mBalance));
+ }
+ }
+ }
+
+ public void setStreamType(int streamType) {
+ mStreamType = streamType;
+ }
+
+ public void rewind() {
+ if (mUseMediaPlayer) {
+ if (mMediaPlayer != null) {
+ mMediaPlayer.seekTo(0);
+ }
+ }
+ }
+
+ public void setSoundWithResId(Context context, int resId) {
+ boolean playing = isPlaying();
+ //release player
+ releasePlayer();
+ mResId = resId;
+ if (mUseMediaPlayer) {
+ mMediaPlayer = new MediaPlayer();
+ try {
+ log("opening resource with stream type: " + mStreamType);
+ mMediaPlayer.setAudioStreamType(mStreamType);
+ mMediaPlayer.setDataSource(context.getApplicationContext(),
+ Uri.parse("android.resource://com.android.cts.verifier/" + resId));
+ mMediaPlayer.prepare();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ mMediaPlayer.setLooping(true);
+ setBalance(mBalance);
+ } else {
+ mMinPlayBufferSizeInBytes = AudioTrack.getMinBufferSize(mSamplingRate,
+ mChannelConfigOut, mAudioFormat);
+
+ mMinBufferSizeInSamples = mMinPlayBufferSizeInBytes / 2;
+ mAudioShortArray = new short[mMinBufferSizeInSamples * 4];
+
+ mAudioTrack = new AudioTrack(mStreamType,
+ mSamplingRate,
+ mChannelConfigOut,
+ mAudioFormat,
+ mMinPlayBufferSizeInBytes,
+ AudioTrack.MODE_STREAM /* FIXME runtime test for API level 9 ,
+ mSessionId */);
+ mPipe.flush();
+ isInitialized = true;
+ }
+
+ log("done preparing media player");
+ if (playing)
+ play(true); //start playing if it was playing before
+ }
+
+ public boolean isPlaying() {
+ boolean result = false;
+ if (mUseMediaPlayer) {
+ if (mMediaPlayer != null) {
+ result = mMediaPlayer.isPlaying();
+ }
+ } else {
+ if (mAudioTrack != null) {
+ result = mAudioTrack.getPlayState() == AudioTrack.PLAYSTATE_PLAYING;
+ }
+ }
+ return result;
+ }
+
+ public void play(boolean play) {
+ if (mUseMediaPlayer) {
+ if (mMediaPlayer != null) {
+ if (play) {
+ mMediaPlayer.start();
+ } else {
+ mMediaPlayer.pause();
+ }
+ }
+ } else {
+ if (mAudioTrack != null && isInitialized) {
+ if (play) {
+ mPipe.flush();
+ mAudioTrack.flush();
+ mAudioTrack.play();
+ } else {
+ mAudioTrack.pause();
+ }
+ }
+ }
+ }
+
+ public void finish() {
+ play(false);
+ releasePlayer();
+ }
+
+ private void releasePlayer() {
+ if (mMediaPlayer != null) {
+ mMediaPlayer.stop();
+ mMediaPlayer.release();
+ mMediaPlayer = null;
+ }
+
+ if (mAudioTrack != null) {
+ mAudioTrack.stop();
+ mAudioTrack.release();
+ mAudioTrack = null;
+ }
+ isInitialized = false;
+ }
+
+ /*
+ Misc
+ */
+ private static void log(String msg) {
+ Log.v(LOGTAG, msg);
+ }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/wavelib/DspBufferBase.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/wavelib/DspBufferBase.java
new file mode 100644
index 0000000..0a8bdde
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/wavelib/DspBufferBase.java
@@ -0,0 +1,46 @@
+/*
+ * 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.wavelib;
+
+public abstract class DspBufferBase {
+ private int mSize;
+
+ public DspBufferBase() {
+ setSize(0);
+ }
+
+ public DspBufferBase(int size) {
+ setSize(size);
+ }
+
+ public int getSize() {
+ return mSize;
+ }
+
+ public void setSize(int size) {
+ mSize = size;
+ }
+
+ public abstract void setValue(int index, double value);
+
+ public abstract void setValues(int index, double... values);
+
+ @Override
+ public String toString() {
+ return String.format("Size: %d", mSize);
+ }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/wavelib/DspBufferComplex.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/wavelib/DspBufferComplex.java
new file mode 100644
index 0000000..2b71343
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/wavelib/DspBufferComplex.java
@@ -0,0 +1,61 @@
+/*
+ * 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.wavelib;
+
+public class DspBufferComplex extends DspBufferBase {
+ public double[] mReal;
+ public double[] mImag;
+
+ public DspBufferComplex(int size) {
+ super(size);
+ }
+
+ @Override
+ public void setSize(int size) {
+ if (size == getSize()) {
+ return;
+ }
+ mReal = new double[size];
+ mImag = new double[size];
+ super.setSize(size);
+ }
+
+ // Warning, these methods don't check for bounds!
+ @Override
+ public void setValues(int index, double... values) {
+ mReal[index] = values[0];
+ mImag[index] = values[1];
+ }
+
+ @Override
+ public void setValue(int index, double value) {
+ mReal[index] = value;
+ mImag[index] = 0;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ int size = getSize();
+ sb.append(String.format("Size: %d { ", size));
+ for (int i = 0; i < size; i++) {
+ sb.append(String.format("(%.3f, %3f) ", mReal[i], mImag[i]));
+ }
+ sb.append("}");
+ return sb.toString();
+ }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/wavelib/DspBufferDouble.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/wavelib/DspBufferDouble.java
new file mode 100644
index 0000000..1b75da6
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/wavelib/DspBufferDouble.java
@@ -0,0 +1,61 @@
+/*
+ * 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.wavelib;
+
+public class DspBufferDouble extends DspBufferBase {
+ public double[] mData;
+
+ public DspBufferDouble(int size) {
+ super(size);
+ }
+
+ @Override
+ public void setSize(int size) {
+ if (size == getSize()) {
+ return;
+ }
+ mData = new double[size];
+ super.setSize(size);
+ }
+
+ // Warning, these methods don't check for bounds!
+ @Override
+ public void setValues(int index, double... values) {
+ mData[index] = values[0];
+ }
+
+ @Override
+ public void setValue(int index, double value) {
+ mData[index] = value;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ int size = getSize();
+ sb.append(String.format("Size: %d { ", size));
+ int i = 0;
+ for (; i < size - 1; i++) {
+ sb.append(String.format("%.3f, ", mData[i]));
+ }
+ for(; i < size; i++) {
+ sb.append(String.format("%.3f", mData[i]));
+ }
+ sb.append(" }");
+ return sb.toString();
+ }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/wavelib/DspBufferMath.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/wavelib/DspBufferMath.java
new file mode 100644
index 0000000..a9cbbd0
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/wavelib/DspBufferMath.java
@@ -0,0 +1,329 @@
+/*
+ * 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.wavelib;
+
+import android.util.Log;
+
+public class DspBufferMath {
+ private static final String TAG = "DspBufferMath";
+ public static final int OPERANDS_TYPE_UNKNOWN = -1;
+ public static final int OPERANDS_TYPE_REAL = 0;
+ public static final int OPERANDS_TYPE_COMPLEX = 1;
+ public static final int OPERANDS_TYPE_MIXED = 2;
+
+ public static final int MATH_RESULT_UNDEFINED = -1;
+ public static final int MATH_RESULT_SUCCESS = 0;
+ public static final int MATH_RESULT_ERROR = 1;
+
+ static private<T extends DspBufferBase> int estimateOperandsType(T a, T b) {
+ if (a instanceof DspBufferComplex) {
+ if (b instanceof DspBufferComplex) {
+ return OPERANDS_TYPE_COMPLEX;
+ } else if (b instanceof DspBufferDouble) {
+ return OPERANDS_TYPE_MIXED;
+ }
+ } else if (a instanceof DspBufferDouble) {
+ if (b instanceof DspBufferComplex) {
+ return OPERANDS_TYPE_MIXED;
+ } else if (b instanceof DspBufferDouble) {
+ return OPERANDS_TYPE_REAL;
+ }
+ }
+ return OPERANDS_TYPE_UNKNOWN;
+ }
+
+ /**
+ * adds r = a + b; element by element
+ *
+ * If the result is double vector, the imaginary part of complex operations is ignored.
+ */
+ static public <T extends DspBufferBase> int add(T r, T a, T b) {
+ int size = Math.min(a.getSize(), b.getSize());
+ r.setSize(size);
+
+ T x = a;
+ T y = b;
+ int opType = estimateOperandsType(a, b);
+
+ if (opType == OPERANDS_TYPE_MIXED) {
+ if (a instanceof DspBufferDouble) {
+ x = b; //Complex first
+ y = a;
+ }
+ }
+
+ if (opType == OPERANDS_TYPE_UNKNOWN) {
+ return MATH_RESULT_UNDEFINED;
+ }
+
+ if (r instanceof DspBufferComplex) {
+ switch (opType) {
+ case OPERANDS_TYPE_REAL:
+ for (int i = 0; i < size; i++) {
+ ((DspBufferComplex) r).mReal[i] =
+ ((DspBufferDouble) x).mData[i] + ((DspBufferDouble) y).mData[i];
+ ((DspBufferComplex) r).mImag[i] = 0;
+ }
+ return MATH_RESULT_SUCCESS;
+ case OPERANDS_TYPE_COMPLEX:
+ for (int i = 0; i < size; i++) {
+ ((DspBufferComplex) r).mReal[i] =
+ ((DspBufferComplex) x).mReal[i] + ((DspBufferComplex) y).mReal[i];
+ ((DspBufferComplex) r).mImag[i] =
+ ((DspBufferComplex) x).mImag[i] + ((DspBufferComplex) y).mImag[i];
+ }
+ return MATH_RESULT_SUCCESS;
+ case OPERANDS_TYPE_MIXED:
+ for (int i = 0; i < size; i++) {
+ ((DspBufferComplex) r).mReal[i] =
+ ((DspBufferComplex) x).mReal[i] + ((DspBufferDouble) y).mData[i];
+ ((DspBufferComplex) r).mImag[i] = ((DspBufferComplex) x).mImag[i];
+ }
+ return MATH_RESULT_SUCCESS;
+ }
+ } else if (r instanceof DspBufferDouble) {
+ switch (opType) {
+ case OPERANDS_TYPE_REAL:
+ for (int i = 0; i < size; i++) {
+ ((DspBufferDouble) r).mData[i] =
+ ((DspBufferDouble) x).mData[i] + ((DspBufferDouble) y).mData[i];
+ }
+ return MATH_RESULT_SUCCESS;
+ case OPERANDS_TYPE_COMPLEX:
+ for (int i = 0; i < size; i++) {
+ ((DspBufferDouble) r).mData[i] =
+ ((DspBufferComplex) x).mReal[i] + ((DspBufferComplex) y).mReal[i];
+ }
+ return MATH_RESULT_SUCCESS;
+ case OPERANDS_TYPE_MIXED:
+ for (int i = 0; i < size; i++) {
+ ((DspBufferDouble) r).mData[i] =
+ ((DspBufferComplex) x).mReal[i] + ((DspBufferDouble) y).mData[i];
+ }
+ return MATH_RESULT_SUCCESS;
+ }
+ }
+ return MATH_RESULT_ERROR;
+ }
+
+ /**
+ * mult r = a * b; element by element
+ */
+ static public <T extends DspBufferBase> int mult(T r, T a, T b) {
+ int size = Math.min(a.getSize(), b.getSize());
+ r.setSize(size);
+
+ T x = a;
+ T y = b;
+ int opType = estimateOperandsType(a, b);
+
+ if (opType == OPERANDS_TYPE_MIXED) {
+ if (a instanceof DspBufferDouble) {
+ x = b; //Complex first
+ y = a;
+ }
+ }
+
+ if (opType == OPERANDS_TYPE_UNKNOWN) {
+ return MATH_RESULT_UNDEFINED;
+ }
+
+ if (r instanceof DspBufferComplex) {
+ switch (opType) {
+ case OPERANDS_TYPE_REAL:
+ for (int i = 0; i < size; i++) {
+ ((DspBufferComplex) r).mReal[i] =
+ ((DspBufferDouble) x).mData[i] * ((DspBufferDouble) y).mData[i];
+ ((DspBufferComplex) r).mImag[i] = 0;
+ }
+ return MATH_RESULT_SUCCESS;
+ case OPERANDS_TYPE_COMPLEX:
+ for (int i = 0; i < size; i++) {
+ double A = ((DspBufferComplex) x).mReal[i];
+ double B = ((DspBufferComplex) x).mImag[i];
+ double C = ((DspBufferComplex) y).mReal[i];
+ double D = ((DspBufferComplex) y).mImag[i];
+ ((DspBufferComplex) r).mReal[i] = (C * A) - (B * D);
+ ((DspBufferComplex) r).mImag[i] = (C * B) + (A * D);
+ }
+ return MATH_RESULT_SUCCESS;
+ case OPERANDS_TYPE_MIXED:
+ for (int i = 0; i < size; i++) {
+ double A = ((DspBufferComplex) x).mReal[i];
+ double B = ((DspBufferComplex) x).mImag[i];
+ double C = ((DspBufferDouble) y).mData[i];
+ //double D = 0;
+ ((DspBufferComplex) r).mReal[i] = C * A;
+ ((DspBufferComplex) r).mImag[i] = C * B;
+ }
+ return MATH_RESULT_SUCCESS;
+ }
+ } else if (r instanceof DspBufferDouble) {
+ switch (opType) {
+ case OPERANDS_TYPE_REAL:
+ for (int i = 0; i < size; i++) {
+ ((DspBufferDouble) r).mData[i] =
+ ((DspBufferDouble) x).mData[i] * ((DspBufferDouble) y).mData[i];
+ }
+ return MATH_RESULT_SUCCESS;
+ case OPERANDS_TYPE_COMPLEX:
+ for (int i = 0; i < size; i++) {
+ double A = ((DspBufferComplex) x).mReal[i];
+ double B = ((DspBufferComplex) x).mImag[i];
+ double C = ((DspBufferComplex) y).mReal[i];
+ double D = ((DspBufferComplex) y).mImag[i];
+ ((DspBufferDouble) r).mData[i] = (C * A) - (B * D);
+ }
+ return MATH_RESULT_SUCCESS;
+ case OPERANDS_TYPE_MIXED:
+ for (int i = 0; i < size; i++) {
+ double A = ((DspBufferComplex) x).mReal[i];
+ double B = ((DspBufferComplex) x).mImag[i];
+ double C = ((DspBufferDouble) y).mData[i];
+ //double D = 0;
+ ((DspBufferDouble) r).mData[i] = C * A;
+ }
+ return MATH_RESULT_SUCCESS;
+ }
+ }
+ return MATH_RESULT_ERROR;
+ }
+
+ /**
+ * mult r = a * v; element by element
+ */
+ static public <T extends DspBufferBase> int mult(T r, T a, double v) {
+ int size = a.getSize();
+ r.setSize(size);
+
+ T x = a;
+ int opType = estimateOperandsType(r, a);
+
+ if (opType == OPERANDS_TYPE_UNKNOWN) {
+ return MATH_RESULT_UNDEFINED;
+ }
+
+ if (r instanceof DspBufferComplex) {
+ switch (opType) {
+ case OPERANDS_TYPE_MIXED:
+ for (int i = 0; i < size; i++) {
+ ((DspBufferComplex) r).mReal[i] = ((DspBufferDouble) x).mData[i] * v;
+ ((DspBufferComplex) r).mImag[i] = 0;
+ }
+ return MATH_RESULT_SUCCESS;
+ case OPERANDS_TYPE_COMPLEX:
+ for (int i = 0; i < size; i++) {
+ ((DspBufferComplex) r).mReal[i] = ((DspBufferComplex) x).mReal[i] * v;
+ ((DspBufferComplex) r).mImag[i] = ((DspBufferComplex) x).mImag[i] * v;
+ }
+ return MATH_RESULT_SUCCESS;
+ }
+ } else if (r instanceof DspBufferDouble) {
+ switch (opType) {
+ case OPERANDS_TYPE_REAL:
+ for (int i = 0; i < size; i++) {
+ ((DspBufferDouble) r).mData[i] = ((DspBufferDouble) x).mData[i] * v;
+ }
+ return MATH_RESULT_SUCCESS;
+ case OPERANDS_TYPE_MIXED:
+ for (int i = 0; i < size; i++) {
+ ((DspBufferDouble) r).mData[i] = ((DspBufferComplex) x).mReal[i] * v;
+ }
+ return MATH_RESULT_SUCCESS;
+ }
+ }
+ return MATH_RESULT_ERROR;
+ }
+
+ /**
+ * set r = a ; element by element
+ */
+ static public <T extends DspBufferBase> int set(T r, T a) {
+ int size = a.getSize();
+ r.setSize(size);
+
+ T x = a;
+ int opType = estimateOperandsType(r, a);
+
+ if (opType == OPERANDS_TYPE_UNKNOWN) {
+ return MATH_RESULT_UNDEFINED;
+ }
+
+ if (r instanceof DspBufferComplex) {
+ switch (opType) {
+ case OPERANDS_TYPE_MIXED:
+ for (int i = 0; i < size; i++) {
+ ((DspBufferComplex) r).mReal[i] = ((DspBufferDouble) x).mData[i];
+ ((DspBufferComplex) r).mImag[i] = 0;
+ }
+ return MATH_RESULT_SUCCESS;
+ case OPERANDS_TYPE_COMPLEX:
+ for (int i = 0; i < size; i++) {
+ ((DspBufferComplex) r).mReal[i] = ((DspBufferComplex) x).mReal[i];
+ ((DspBufferComplex) r).mImag[i] = ((DspBufferComplex) x).mImag[i];
+ }
+ return MATH_RESULT_SUCCESS;
+ }
+ } else if (r instanceof DspBufferDouble) {
+ switch(opType) {
+ case OPERANDS_TYPE_REAL:
+ for (int i = 0; i < size; i++) {
+ ((DspBufferDouble) r).mData[i] = ((DspBufferDouble) x).mData[i];
+ }
+ return MATH_RESULT_SUCCESS;
+ case OPERANDS_TYPE_MIXED:
+ for (int i = 0; i < size; i++) {
+ ((DspBufferDouble) r).mData[i] = ((DspBufferComplex) x).mReal[i];
+ }
+ return MATH_RESULT_SUCCESS;
+ }
+ }
+ return MATH_RESULT_ERROR;
+ }
+
+
+ /**
+ * set r = v ; all elements the same
+ * It keeps the size of the return vector
+ */
+ static public <T extends DspBufferBase> int set(T r, double ...values) {
+ int size = r.getSize();
+
+ double a = 0;
+ double b = 0;
+ if (values.length > 0) {
+ a = values[0];
+ }
+ if (values.length > 1) {
+ b = values[1];
+ }
+
+ if (r instanceof DspBufferComplex) {
+ for (int i = 0; i < size; i++) {
+ ((DspBufferComplex) r).mReal[i] = a;
+ ((DspBufferComplex) r).mImag[i] = b;
+ }
+ return MATH_RESULT_SUCCESS;
+ } else if (r instanceof DspBufferDouble) {
+ for (int i = 0; i < size; i++) {
+ ((DspBufferDouble) r).mData[i] = a;
+ }
+ return MATH_RESULT_SUCCESS;
+ }
+ return MATH_RESULT_ERROR;
+ }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/wavelib/DspFftServer.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/wavelib/DspFftServer.java
new file mode 100644
index 0000000..09337f1
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/wavelib/DspFftServer.java
@@ -0,0 +1,100 @@
+/*
+ * 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.wavelib;
+
+public class DspFftServer {
+ private int mN = 0;
+ private int mOrder = 0;
+
+ DspBufferDouble mCos;
+ DspBufferDouble mSin;
+ public boolean isInitialized = false;
+
+ public DspFftServer(int size) {
+ init(size);
+ }
+
+ public boolean init(int size) {
+ boolean status = false;
+ mN=size;
+
+ mOrder = (int) (Math.log(mN) / Math.log(2));
+ if (mN == (1 << mOrder)) {
+ mCos = new DspBufferDouble(mN / 2);
+ mSin = new DspBufferDouble(mN / 2);
+ for (int i = 0; i < mN / 2; i++) {
+ mCos.mData[i] = Math.cos(-2 * Math.PI * i / mN);
+ mSin.mData[i] = Math.sin(-2 * Math.PI * i / mN);
+ }
+ status = true;
+ } else {
+ mN = 0;
+ throw new RuntimeException("FFT must be power of 2");
+ }
+ isInitialized = status;
+ return status;
+ }
+
+ public void fft(DspBufferComplex r, int sign) {
+ int ii, jj, kk, n1, n2, aa;
+ double cc, ss, t1, t2;
+
+ // Bit-reverse
+ jj = 0;
+ n2 = mN / 2;
+ for (ii = 1; ii < mN - 1; ii++) {
+ n1 = n2;
+ while (jj >= n1) {
+ jj = jj - n1;
+ n1 = n1 / 2;
+ }
+ jj = jj + n1;
+
+ if (ii < jj) {
+ t1 = r.mReal[ii];
+ r.mReal[ii] = r.mReal[jj];
+ r.mReal[jj] = t1;
+ t1 = r.mImag[ii];
+ r.mImag[ii] = r.mImag[jj];
+ r.mImag[jj] = t1;
+ }
+ }
+
+ // FFT
+ n1 = 0;
+ n2 = 1;
+ for (ii = 0; ii < mOrder; ii++) {
+ n1 = n2;
+ n2 = n2 + n2;
+ aa = 0;
+
+ for (jj = 0; jj < n1; jj++) {
+ cc = mCos.mData[aa];
+ ss = sign * mSin.mData[aa];
+ aa += 1 << (mOrder - ii - 1);
+ for (kk = jj; kk < mN; kk = kk + n2) {
+ t1 = cc * r.mReal[kk + n1] - ss * r.mImag[kk + n1];
+ t2 = ss * r.mReal[kk + n1] + cc * r.mImag[kk + n1];
+ r.mReal[kk + n1] = r.mReal[kk] - t1;
+ r.mImag[kk + n1] = r.mImag[kk] - t2;
+ r.mReal[kk] = r.mReal[kk] + t1;
+ r.mImag[kk] = r.mImag[kk] + t2;
+ }
+ }
+ }
+ }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/wavelib/DspWindow.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/wavelib/DspWindow.java
new file mode 100644
index 0000000..3ccca43
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/wavelib/DspWindow.java
@@ -0,0 +1,201 @@
+/*
+ * 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.wavelib;
+
+public class DspWindow {
+ public DspBufferDouble mBuffer;
+ private int mWindowType = WINDOW_RECTANGULAR;
+ private int mSize;
+ private int mOverlap;
+
+ private static final double TWOPI = Math.PI * 2;
+
+ public static final int WINDOW_RECTANGULAR = 0;
+ public static final int WINDOW_TRIANGULAR = 1;
+ public static final int WINDOW_TRIANGULAR_FLAT_TOP = 2;
+ public static final int WINDOW_HAMMING = 3;
+ public static final int WINDOW_HAMMING_FLAT_TOP = 4;
+ public static final int WINDOW_HANNING = 5;
+ public static final int WINDOW_HANNING_FLAT_TOP = 6;
+
+ public DspWindow(int windowType, int size, int overlap) {
+ init(windowType, size, overlap);
+ }
+
+ public DspWindow(int windowType, int size) {
+ init(windowType, size, size / 2);
+ }
+
+ public void init(int windowType, int size, int overlap) {
+ if (size > 0 && overlap > 0) {
+ mSize = size;
+ mOverlap = overlap;
+ if (mOverlap > mSize / 2) {
+ mOverlap = mSize / 2;
+ }
+
+ mBuffer = new DspBufferDouble(mSize);
+ if (fillWindow(mBuffer, windowType, mOverlap)) {
+ mWindowType = windowType;
+ }
+ }
+ }
+
+ public void scale(double scale) {
+ DspBufferMath.mult(mBuffer, mBuffer, scale);
+ }
+
+ public static boolean fillWindow(DspBufferDouble r, int type, int overlap) {
+ boolean status = false;
+ int size = r.getSize();
+ if (overlap > size / 2) {
+ overlap = size / 2;
+ }
+
+ switch(type) {
+ case WINDOW_RECTANGULAR:
+ status = fillRectangular(r);
+ break;
+ case WINDOW_TRIANGULAR:
+ status = fillTriangular(r, size / 2);
+ break;
+ case WINDOW_TRIANGULAR_FLAT_TOP:
+ status = fillTriangular(r, overlap);
+ break;
+ case WINDOW_HAMMING:
+ status = fillHamming(r, size / 2);
+ break;
+ case WINDOW_HAMMING_FLAT_TOP:
+ status = fillHamming(r, overlap);
+ break;
+ case WINDOW_HANNING:
+ status = fillHanning(r, size / 2);
+ break;
+ case WINDOW_HANNING_FLAT_TOP:
+ status = fillHanning(r, overlap);
+ break;
+ }
+ return status;
+ }
+
+ private static boolean fillRectangular(DspBufferDouble r) {
+ if (DspBufferMath.set(r, 1.0) == DspBufferMath.MATH_RESULT_SUCCESS) {
+ return true;
+ }
+ return false;
+ }
+
+ private static boolean fillTriangular(DspBufferDouble b, int overlap) {
+ int size = b.getSize();
+ if (overlap > size / 2) {
+ overlap = size / 2;
+ }
+
+ double value;
+ //ramp up
+ int i = 0;
+ if (overlap > 0) {
+ for (i = 0; i < overlap; i++) {
+ value = (2.0 * i + 1) / (2 * overlap);
+ b.mData[i] = value;
+ }
+ }
+
+ //flat top
+ for (; i < size - overlap; i++) {
+ b.mData[i] = 1.0;
+ }
+
+ //ramp down
+ if (overlap > 0) {
+ for (; i < size; i++) {
+ value = (2.0 * (size - i) - 1) / (2 * overlap);
+ b.mData[i] = value;
+ }
+ }
+ return true;
+ }
+
+ private static boolean fillHamming(DspBufferDouble b, int overlap) {
+ int size = b.getSize();
+ if (overlap > size / 2)
+ overlap = size / 2;
+
+ //create window, then copy
+ double value;
+
+ int twoOverlap = 2 * overlap;
+ //ramp up
+ int i = 0;
+ if (overlap > 0) {
+ for (i = 0; i < overlap; i++) {
+ value = 0.54 - 0.46 * Math.cos(TWOPI * i / (twoOverlap - 1));
+ b.mData[i] = value;
+ }
+ }
+
+ //flat top
+ for (; i < size - overlap; i++) {
+ b.mData[i] = 1.0;
+ }
+
+ //ramp down
+ int k;
+ if (overlap > 0) {
+ for (; i < size; i++) {
+ k = i - (size - 2 * overlap);
+ value = 0.54 - 0.46 * Math.cos(TWOPI * k / (twoOverlap - 1));
+ b.mData[i] = value;
+ }
+ }
+ return true;
+ }
+
+ private static boolean fillHanning(DspBufferDouble b, int overlap) {
+ int size = b.getSize();
+ if (overlap > size / 2)
+ overlap = size / 2;
+
+ //create window, then copy
+ double value;
+
+ int twoOverlap = 2*overlap;
+ //ramp up
+ int i = 0;
+ if (overlap > 0) {
+ for (i = 0; i < overlap; i++) {
+ value = 0.5 * (1.0 - Math.cos(TWOPI * i / (twoOverlap - 1)));
+ b.mData[i] = value;
+ }
+ }
+
+ //flat top
+ for (; i < size - overlap; i++) {
+ b.mData[i] = 1.0;
+ }
+
+ //ramp down
+ if (overlap > 0) {
+ for (; i < size; i++) {
+ int k = i - (size - 2 * overlap);
+ value = 0.5 * (1.0 - Math.cos(TWOPI * k / (twoOverlap - 1)));
+ b.mData[i] = value;
+ }
+ }
+ return true;
+ }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/wavelib/PipeShort.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/wavelib/PipeShort.java
new file mode 100644
index 0000000..83b171f
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/wavelib/PipeShort.java
@@ -0,0 +1,140 @@
+/*
+ * 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.wavelib;
+
+// Non-blocking pipe supports a single writer and single reader.
+// The write side of a pipe permits overruns; flow control is the caller's responsibility.
+
+public class PipeShort {
+ private int mFront;
+ private int mRear;
+ private short mBuffer[];
+ private volatile int mVolatileRear; // written by write(), read by read()
+ private int mMaxValues;
+ private int mBytesOverrun;
+ private int mOverruns;
+ public static final int OVERRUN = -2;
+
+ // maxBytes will be rounded up to a power of 2, and all slots are available. Must be >= 2.
+ public PipeShort(int maxValues)
+ {
+ mMaxValues = roundup(maxValues);
+ mBuffer = new short[mMaxValues];
+ }
+
+ // buffer must != null.
+ // offset must be >= 0.
+ // count is maximum number of bytes to copy, and must be >= 0.
+ // offset + count must be <= buffer.length.
+ // Returns actual number of bytes copied >= 0.
+ public int write(short[] buffer, int offset, int count)
+ {
+ int rear = mRear & (mMaxValues - 1);
+ int written = mMaxValues - rear;
+ if (written > count) {
+ written = count;
+ }
+ System.arraycopy(buffer, offset, mBuffer, rear, written);
+ if (rear + written == mMaxValues) {
+ if ((count -= written) > rear) {
+ count = rear;
+ }
+ if (count > 0) {
+ System.arraycopy(buffer, offset + written, mBuffer, 0, count);
+ written += count;
+ }
+ }
+ mRear += written;
+ mVolatileRear = mRear;
+ return written;
+ }
+
+ public int availableToRead()
+ {
+ int rear = mVolatileRear;
+ int avail = rear - mFront;
+ if (avail > mMaxValues) {
+ // Discard 1/16 of the most recent data in pipe to avoid another overrun immediately
+ int oldFront = mFront;
+ mFront = rear - mMaxValues + (mMaxValues >> 4);
+ mBytesOverrun += mFront - oldFront;
+ ++mOverruns;
+ return OVERRUN;
+ }
+ return avail;
+ }
+
+ // buffer must != null.
+ // offset must be >= 0.
+ // count is maximum number of bytes to copy, and must be >= 0.
+ // offset + count must be <= buffer.length.
+ // Returns actual number of bytes copied >= 0.
+ public int read(short[] buffer, int offset, int count)
+ {
+ int avail = availableToRead();
+ if (avail <= 0) {
+ return avail;
+ }
+ // An overrun can occur from here on and be silently ignored,
+ // but it will be caught at next read()
+ if (count > avail) {
+ count = avail;
+ }
+ int front = mFront & (mMaxValues - 1);
+ int red = mMaxValues - front;
+ if (red > count) {
+ red = count;
+ }
+ // In particular, an overrun during the System.arraycopy will result in reading corrupt data
+ System.arraycopy(mBuffer, front, buffer, offset, red);
+ // We could re-read the rear pointer here to detect the corruption, but why bother?
+ if (front + red == mMaxValues) {
+ if ((count -= red) > front) {
+ count = front;
+ }
+ if (count > 0) {
+ System.arraycopy(mBuffer, 0, buffer, offset + red, count);
+ red += count;
+ }
+ }
+ mFront += red;
+ return red;
+ }
+
+ public void flush()
+ {
+ mRear = mFront;
+ mVolatileRear = mFront;
+ }
+
+ // Round up to the next highest power of 2
+ private static int roundup(int v)
+ {
+ // Integer.numberOfLeadingZeros() returns 32 for zero input
+ if (v == 0) {
+ v = 1;
+ }
+ int lz = Integer.numberOfLeadingZeros(v);
+ int rounded = 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/src/com/android/cts/verifier/audio/wavelib/VectorAverage.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/wavelib/VectorAverage.java
new file mode 100644
index 0000000..41f0411
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/wavelib/VectorAverage.java
@@ -0,0 +1,158 @@
+/*
+ * 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.wavelib;
+
+import android.util.Log;
+
+public class VectorAverage {
+ private static final String LOGTAG = "VectorAverage";
+ private static final int mVersion = 0;
+ private double[] mData;
+ private int mValueCount = 0;
+
+ public void setData(double[] data, boolean replace) {
+ int size = data.length;
+ if (mData == null || mData.length != size) {
+ mData = new double[size];
+ mValueCount = 0;
+ }
+ if (replace || mValueCount == 0) {
+ System.arraycopy(data, 0, mData, 0, size);
+ mValueCount = 1;
+ } else {
+ for (int i = 0; i < size; i++) {
+ mData[i] += data[i];
+ }
+ mValueCount++;
+ }
+ }
+
+ public int getData(double[] data, boolean raw) {
+ int nCount = 0;
+ if (mData != null && mData.length <= data.length) {
+ nCount = mData.length;
+ if (mValueCount == 0) {
+ for (int i = 0; i < nCount; i++) {
+ data[i] = 0;
+ }
+ } else if (!raw && mValueCount > 1) {
+ for (int i = 0; i < nCount; i++) {
+ data[i] = mData[i] / mValueCount;
+ }
+ } else {
+ for (int i = 0; i < nCount; i++) {
+ data[i] = mData[i];
+ }
+ }
+ }
+ return nCount;
+ }
+
+ public int getCount() {
+ return mValueCount;
+ }
+
+ public int getSize() {
+ if (mData != null) {
+ return mData.length;
+ }
+ return 0;
+ }
+
+ public void reset() {
+ mValueCount = 0;
+ }
+
+ private final String SERIALIZED_VERSION = "VECTOR_AVERAGE_VERSION";
+ private final String SERIALIZED_COUNT = "COUNT";
+
+ public String toString() {
+ StringBuffer sb = new StringBuffer();
+
+ //version
+ sb.append(SERIALIZED_VERSION +"="+ mVersion +"\n");
+
+ double[] data = new double[getSize()];
+ getData(data,false);
+
+ //element count
+ int nCount = data.length;
+ sb.append(SERIALIZED_COUNT + "=" + nCount +"\n");
+
+ for (int i = 0; i < nCount; i++) {
+ sb.append(String.format("%f\n",data[i]));
+ }
+
+ return sb.toString();
+ }
+
+ public boolean initFromString(String string) {
+ boolean success = false;
+
+ String[] lines = string.split(System.getProperty("line.separator"));
+
+ int lineCount = lines.length;
+ if (lineCount > 3) {
+ int nVersion = -1;
+ int nCount = -1;
+ int nIndex = 0;
+
+ //search for version:
+ while (nIndex < lineCount) {
+ String[] separated = lines[nIndex].split("=");
+ nIndex++;
+ if (separated.length > 1 && separated[0].equalsIgnoreCase(SERIALIZED_VERSION)) {
+ nVersion = Integer.parseInt(separated[1]);
+ break;
+ }
+ }
+
+ if (nVersion >= 0) {
+ //get count
+
+ while (nIndex < lineCount) {
+ String[] separated = lines[nIndex].split("=");
+ nIndex++;
+ if (separated.length > 1 && separated[0].equalsIgnoreCase(SERIALIZED_COUNT)) {
+ nCount = Integer.parseInt(separated[1]);
+ break;
+ }
+ }
+
+ if (nCount > 0 && nCount <= lineCount-2 && nCount < 20000) { //foolproof
+ //now add nCount to the vector.
+ double[] data = new double[nCount];
+ int dataIndex=0;
+
+ while (nIndex < lineCount) {
+ double value = Double.parseDouble(lines[nIndex]);
+ data[dataIndex++] = value;
+ nIndex++;
+ }
+ setData(data, true);
+ success = true;
+ }
+ }
+ }
+
+ return success;
+ }
+
+ private static void log(String msg) {
+ Log.v(LOGTAG, msg);
+ }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsService.java b/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsService.java
index a76bb7f..3037376 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsService.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsService.java
@@ -1295,8 +1295,8 @@
CaptureRequest.REPROCESS_EFFECTIVE_EXPOSURE_FACTOR));
inputReqest.set(CaptureRequest.NOISE_REDUCTION_MODE,
- CaptureRequest.NOISE_REDUCTION_MODE_OFF);
- inputReqest.set(CaptureRequest.EDGE_MODE, CaptureRequest.EDGE_MODE_OFF);
+ CaptureRequest.NOISE_REDUCTION_MODE_ZERO_SHUTTER_LAG);
+ inputReqest.set(CaptureRequest.EDGE_MODE, CaptureRequest.EDGE_MODE_ZERO_SHUTTER_LAG);
inputReqest.set(CaptureRequest.REPROCESS_EFFECTIVE_EXPOSURE_FACTOR, null);
inputReqest.addTarget(mInputImageReader.getSurface());
mSession.capture(inputReqest.build(), captureCallbackWaiter, mResultHandler);
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodFlowTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodFlowTestActivity.java
index a463937..bee1241 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodFlowTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodFlowTestActivity.java
@@ -32,6 +32,7 @@
import com.android.cts.verifier.DialogTestListActivity;
import com.android.cts.verifier.R;
import com.android.cts.verifier.TestListActivity;
+import com.android.cts.verifier.TestListAdapter.TestListItem;
import com.android.cts.verifier.TestResult;
/**
@@ -73,6 +74,7 @@
private DialogTestListItem mCrossProfileImageCaptureSupportTest;
private DialogTestListItem mCrossProfileVideoCaptureSupportTest;
private DialogTestListItem mCrossProfileAudioCaptureSupportTest;
+ private TestListItem mKeyguardDisabledFeaturesTest;
public ByodFlowTestActivity() {
super(R.layout.provisioning_byod,
@@ -256,6 +258,11 @@
R.string.provisioning_byod_cross_profile_instruction,
chooser);
+ mKeyguardDisabledFeaturesTest = TestListItem.newTest(this,
+ R.string.provisioning_byod_keyguard_disabled_features,
+ KeyguardDisabledFeaturesActivity.class.getName(),
+ new Intent(this, KeyguardDisabledFeaturesActivity.class), null);
+
// Test for checking if the required intent filters are set during managed provisioning.
mIntentFiltersTest = new DialogTestListItem(this,
R.string.provisioning_byod_cross_profile_intent_filters,
@@ -295,6 +302,7 @@
adapter.add(mEnableNonMarketTest);
adapter.add(mIntentFiltersTest);
adapter.add(mPermissionLockdownTest);
+ adapter.add(mKeyguardDisabledFeaturesTest);
if (canResolveIntent(ByodHelperActivity.getCaptureImageIntent())) {
// Capture image intent can be resolved in primary profile, so test.
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodHelperActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodHelperActivity.java
index 4d1a92a..09e6393 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodHelperActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodHelperActivity.java
@@ -67,8 +67,13 @@
public static final String ACTION_CAPTURE_AND_CHECK_VIDEO = "com.android.cts.verifier.managedprovisioning.BYOD_CAPTURE_AND_CHECK_VIDEO";
// Primage -> managed intent: request to capture and check an audio recording
public static final String ACTION_CAPTURE_AND_CHECK_AUDIO = "com.android.cts.verifier.managedprovisioning.BYOD_CAPTURE_AND_CHECK_AUDIO";
+ public static final String ACTION_KEYGUARD_DISABLED_FEATURES =
+ "com.android.cts.verifier.managedprovisioning.BYOD_KEYGUARD_DISABLED_FEATURES";
+ public static final String ACTION_LOCKNOW =
+ "com.android.cts.verifier.managedprovisioning.BYOD_LOCKNOW";
public static final String EXTRA_PROVISIONED = "extra_provisioned";
+ public static final String EXTRA_PARAMETER_1 = "extra_parameter_1";
// Primary -> managed intent: set unknown sources restriction and install package
public static final String ACTION_INSTALL_APK = "com.android.cts.verifier.managedprovisioning.BYOD_INSTALL_APK";
@@ -187,6 +192,14 @@
finish();
}
return;
+ } else if (ACTION_KEYGUARD_DISABLED_FEATURES.equals(action)) {
+ final int value = intent.getIntExtra(EXTRA_PARAMETER_1,
+ DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_NONE);
+ ComponentName admin = DeviceAdminTestReceiver.getReceiverComponentName();
+ mDevicePolicyManager.setKeyguardDisabledFeatures(admin, value);
+ } else if (ACTION_LOCKNOW.equals(action)) {
+ mDevicePolicyManager.lockNow();
+ setResult(RESULT_OK);
}
// This activity has no UI and is only used to respond to CtsVerifier in the primary side.
finish();
@@ -267,6 +280,10 @@
return new Intent(MediaStore.Audio.Media.RECORD_SOUND_ACTION);
}
+ public static Intent createLockIntent() {
+ return new Intent(ACTION_LOCKNOW);
+ }
+
private Uri getTempUri(String fileName) {
final File file = new File(getFilesDir() + File.separator + "images"
+ File.separator + fileName);
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceAdminTestReceiver.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceAdminTestReceiver.java
index 4987f86..b18e816 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceAdminTestReceiver.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceAdminTestReceiver.java
@@ -61,8 +61,11 @@
filter.addAction(ByodHelperActivity.ACTION_CAPTURE_AND_CHECK_IMAGE);
filter.addAction(ByodHelperActivity.ACTION_CAPTURE_AND_CHECK_VIDEO);
filter.addAction(ByodHelperActivity.ACTION_CAPTURE_AND_CHECK_AUDIO);
+ filter.addAction(ByodHelperActivity.ACTION_KEYGUARD_DISABLED_FEATURES);
+ filter.addAction(ByodHelperActivity.ACTION_LOCKNOW);
filter.addAction(CrossProfileTestActivity.ACTION_CROSS_PROFILE);
filter.addAction(WorkNotificationTestActivity.ACTION_WORK_NOTIFICATION);
+ filter.addAction(WorkNotificationTestActivity.ACTION_WORK_NOTIFICATION_ON_LOCKSCREEN);
filter.addAction(WorkNotificationTestActivity.ACTION_CLEAR_WORK_NOTIFICATION);
filter.addAction(WorkStatusTestActivity.ACTION_WORK_STATUS_TOAST);
filter.addAction(WorkStatusTestActivity.ACTION_WORK_STATUS_ICON);
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceOwnerPositiveTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceOwnerPositiveTestActivity.java
index e6bbdee..a6a5e5a 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceOwnerPositiveTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceOwnerPositiveTestActivity.java
@@ -25,6 +25,7 @@
import android.content.pm.PackageManager;
import android.database.DataSetObserver;
import android.os.Bundle;
+import android.os.UserManager;
import android.provider.Settings;
import android.util.Log;
import android.view.View;
@@ -66,11 +67,14 @@
static final String EXTRA_SETTING = "extra-setting";
private static final String CHECK_DEVICE_OWNER_TEST_ID = "CHECK_DEVICE_OWNER";
+ private static final String DEVICE_ADMIN_SETTINGS_ID = "DEVICE_ADMIN_SETTINGS";
private static final String WIFI_LOCKDOWN_TEST_ID = WifiLockdownTestActivity.class.getName();
private static final String DISABLE_STATUS_BAR_TEST_ID = "DISABLE_STATUS_BAR";
private static final String DISABLE_KEYGUARD_TEST_ID = "DISABLE_KEYGUARD";
private static final String CHECK_PERMISSION_LOCKDOWN_TEST_ID =
PermissionLockdownTestActivity.class.getName();
+ private static final String DISALLOW_CONFIG_BT_ID = "DISALLOW_CONFIG_BT";
+ private static final String DISALLOW_CONFIG_WIFI_ID = "DISALLOW_CONFIG_WIFI";
private static final String REMOVE_DEVICE_OWNER_TEST_ID = "REMOVE_DEVICE_OWNER";
@Override
@@ -132,11 +136,49 @@
new Intent(this, CommandReceiver.class)
.putExtra(EXTRA_COMMAND, COMMAND_CHECK_DEVICE_OWNER)
));
+
+ // device admin settings
+ adapter.add(createInteractiveTestItem(this, DEVICE_ADMIN_SETTINGS_ID,
+ R.string.device_owner_device_admin_visible,
+ R.string.device_owner_device_admin_visible_info,
+ new ButtonInfo(
+ R.string.device_owner_settings_go,
+ new Intent(Settings.ACTION_SECURITY_SETTINGS))));
+
PackageManager packageManager = getPackageManager();
if (packageManager.hasSystemFeature(PackageManager.FEATURE_WIFI)) {
+ // WiFi Lock down tests
adapter.add(createTestItem(this, WIFI_LOCKDOWN_TEST_ID,
R.string.device_owner_wifi_lockdown_test,
new Intent(this, WifiLockdownTestActivity.class)));
+
+ // DISALLOW_CONFIG_WIFI
+ adapter.add(createInteractiveTestItem(this, DISALLOW_CONFIG_WIFI_ID,
+ R.string.device_owner_disallow_config_wifi,
+ R.string.device_owner_disallow_config_wifi_info,
+ new ButtonInfo[] {
+ new ButtonInfo(
+ R.string.device_owner_user_restriction_set,
+ createSetUserRestrictionIntent(
+ UserManager.DISALLOW_CONFIG_WIFI)),
+ new ButtonInfo(
+ R.string.device_owner_settings_go,
+ new Intent(Settings.ACTION_WIFI_SETTINGS))}));
+ }
+
+ // DISALLOW_CONFIG_BLUETOOTH
+ if (packageManager.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH)) {
+ adapter.add(createInteractiveTestItem(this, DISALLOW_CONFIG_BT_ID,
+ R.string.device_owner_disallow_config_bt,
+ R.string.device_owner_disallow_config_bt_info,
+ new ButtonInfo[] {
+ new ButtonInfo(
+ R.string.device_owner_user_restriction_set,
+ createSetUserRestrictionIntent(
+ UserManager.DISALLOW_CONFIG_BLUETOOTH)),
+ new ButtonInfo(
+ R.string.device_owner_settings_go,
+ new Intent(Settings.ACTION_BLUETOOTH_SETTINGS))}));
}
// setStatusBarDisabled
@@ -215,6 +257,12 @@
.putExtra(EXTRA_PARAMETER_1, value);
}
+ private Intent createSetUserRestrictionIntent(String restriction) {
+ return new Intent(this, CommandReceiver.class)
+ .putExtra(EXTRA_COMMAND, COMMAND_ADD_USER_RESTRICTION)
+ .putExtra(EXTRA_RESTRICTION, restriction);
+ }
+
public static class CommandReceiver extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
@@ -276,6 +324,8 @@
dpm.setStatusBarDisabled(admin, false);
dpm.setKeyguardDisabled(admin, false);
+ dpm.clearUserRestriction(admin, UserManager.DISALLOW_CONFIG_BLUETOOTH);
+ dpm.clearUserRestriction(admin, UserManager.DISALLOW_CONFIG_WIFI);
dpm.clearDeviceOwnerApp(getPackageName());
}
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/KeyguardDisabledFeaturesActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/KeyguardDisabledFeaturesActivity.java
new file mode 100644
index 0000000..0fdc498
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/KeyguardDisabledFeaturesActivity.java
@@ -0,0 +1,123 @@
+/*
+ * 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.managedprovisioning;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.ActivityNotFoundException;
+import android.content.Context;
+import android.content.Intent;
+import android.hardware.fingerprint.FingerprintManager;
+import android.os.Bundle;
+import android.provider.Settings;
+import android.view.View;
+import android.view.View.OnClickListener;
+
+import com.android.cts.verifier.ArrayTestListAdapter;
+import com.android.cts.verifier.DialogTestListActivity;
+import com.android.cts.verifier.R;
+
+public class KeyguardDisabledFeaturesActivity extends DialogTestListActivity {
+
+ public KeyguardDisabledFeaturesActivity() {
+ super(R.layout.provisioning_byod,
+ R.string.provisioning_byod_keyguard_disabled_features,
+ R.string.provisioning_byod_keyguard_disabled_features_info,
+ R.string.provisioning_byod_keyguard_disabled_features_instruction);
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ mPrepareTestButton.setText(
+ R.string.provisioning_byod_keyguard_disabled_features_prepare_button);
+ mPrepareTestButton.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ resetPassword("testpassword");
+ setKeyguardDisabledFeatures(DevicePolicyManager.KEYGUARD_DISABLE_TRUST_AGENTS |
+ DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT |
+ DevicePolicyManager.KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS);
+ }
+ });
+ }
+
+ @Override
+ public void finish() {
+ // Pass and fail buttons are known to call finish() when clicked, and this is when we want to
+ // clear the password.
+ resetPassword(null);
+ super.finish();
+ }
+
+ private void setKeyguardDisabledFeatures(final int flags) {
+ Intent setKeyguardDisabledFeaturesIntent =
+ new Intent(ByodHelperActivity.ACTION_KEYGUARD_DISABLED_FEATURES)
+ .putExtra(ByodHelperActivity.EXTRA_PARAMETER_1, flags);
+ startActivity(setKeyguardDisabledFeaturesIntent);
+ }
+
+ /**
+ * Reset device password
+ * @param password password to reset to (may be null)
+ */
+ private void resetPassword(String password) {
+ DevicePolicyManager dpm = (DevicePolicyManager)
+ getSystemService(Context.DEVICE_POLICY_SERVICE);
+ dpm.resetPassword(password, 0);
+ }
+
+ @Override
+ protected void setupTests(ArrayTestListAdapter adapter) {
+ adapter.add(new DialogTestListItem(this, R.string.provisioning_byod_disable_trust_agents,
+ "BYOD_DisableTrustAgentsTest",
+ R.string.provisioning_byod_disable_trust_agents_instruction,
+ new Intent(Settings.ACTION_SECURITY_SETTINGS)));
+ adapter.add(new DialogTestListItemWithIcon(this,
+ R.string.provisioning_byod_disable_notifications,
+ "BYOD_DisableUnredactedNotifications",
+ R.string.provisioning_byod_disable_notifications_instruction,
+ new Intent(WorkNotificationTestActivity.ACTION_WORK_NOTIFICATION_ON_LOCKSCREEN),
+ R.drawable.ic_corp_icon));
+ FingerprintManager fpm = (FingerprintManager) getSystemService(Context.FINGERPRINT_SERVICE);
+ if (fpm.isHardwareDetected()) {
+ adapter.add(new DialogTestListItem(this,
+ R.string.provisioning_byod_fingerprint_disabled_in_settings,
+ "BYOD_FingerprintDisabledInSettings",
+ R.string.provisioning_byod_fingerprint_disabled_in_settings_instruction,
+ new Intent(Settings.ACTION_SECURITY_SETTINGS)));
+ adapter.add(new DialogTestListItem(this, R.string.provisioning_byod_disable_fingerprint,
+ "BYOD_DisableFingerprint",
+ R.string.provisioning_byod_disable_fingerprint_instruction,
+ ByodHelperActivity.createLockIntent()));
+ }
+ }
+
+ @Override
+ protected void clearRemainingState(final DialogTestListItem test) {
+ super.clearRemainingState(test);
+ if (WorkNotificationTestActivity.ACTION_WORK_NOTIFICATION_ON_LOCKSCREEN.equals(
+ test.getManualTestIntent().getAction())) {
+ try {
+ startActivity(new Intent(
+ WorkNotificationTestActivity.ACTION_CLEAR_WORK_NOTIFICATION));
+ } catch (ActivityNotFoundException e) {
+ // User shouldn't run this test before work profile is set up.
+ }
+ }
+ }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/WorkNotificationTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/WorkNotificationTestActivity.java
index c85ccf5..a912d2c 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/WorkNotificationTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/WorkNotificationTestActivity.java
@@ -19,7 +19,9 @@
import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
+import android.app.admin.DevicePolicyManager;
import android.content.Context;
+import android.content.Intent;
import android.os.Bundle;
import com.android.cts.verifier.R;
@@ -30,26 +32,37 @@
public class WorkNotificationTestActivity extends Activity {
public static final String ACTION_WORK_NOTIFICATION =
"com.android.cts.verifier.managedprovisioning.WORK_NOTIFICATION";
+ public static final String ACTION_WORK_NOTIFICATION_ON_LOCKSCREEN =
+ "com.android.cts.verifier.managedprovisioning.LOCKSCREEN_NOTIFICATION";
public static final String ACTION_CLEAR_WORK_NOTIFICATION =
"com.android.cts.verifier.managedprovisioning.CLEAR_WORK_NOTIFICATION";
private static final int NOTIFICATION_ID = 7;
+ private NotificationManager mNotificationManager;
+
+ private void showWorkNotification(int visibility) {
+ final Notification notification = new Notification.Builder(this)
+ .setSmallIcon(R.drawable.icon)
+ .setContentTitle(getString(R.string.provisioning_byod_work_notification_title))
+ .setVisibility(visibility)
+ .setAutoCancel(true)
+ .build();
+ mNotificationManager.notify(NOTIFICATION_ID, notification);
+ }
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final String action = getIntent().getAction();
- final NotificationManager notificationManager = (NotificationManager)
- getSystemService(Context.NOTIFICATION_SERVICE);
+ mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
if (ACTION_WORK_NOTIFICATION.equals(action)) {
- final Notification notification = new Notification.Builder(this)
- .setSmallIcon(R.drawable.icon)
- .setContentTitle(getString(R.string.provisioning_byod_work_notification_title))
- .setVisibility(Notification.VISIBILITY_PUBLIC)
- .setAutoCancel(true)
- .build();
- notificationManager.notify(NOTIFICATION_ID, notification);
+ showWorkNotification(Notification.VISIBILITY_PUBLIC);
+ } else if (ACTION_WORK_NOTIFICATION_ON_LOCKSCREEN.equals(action)) {
+ DevicePolicyManager dpm = (DevicePolicyManager) getSystemService(
+ Context.DEVICE_POLICY_SERVICE);
+ dpm.lockNow();
+ showWorkNotification(Notification.VISIBILITY_PRIVATE);
} else if (ACTION_CLEAR_WORK_NOTIFICATION.equals(action)) {
- notificationManager.cancel(NOTIFICATION_ID);
+ mNotificationManager.cancel(NOTIFICATION_ID);
}
finish();
}
diff --git a/hostsidetests/appsecurity/src/com/android/cts/appsecurity/ExternalStorageHostTest.java b/hostsidetests/appsecurity/src/com/android/cts/appsecurity/ExternalStorageHostTest.java
index d74ec52..cb67c63 100644
--- a/hostsidetests/appsecurity/src/com/android/cts/appsecurity/ExternalStorageHostTest.java
+++ b/hostsidetests/appsecurity/src/com/android/cts/appsecurity/ExternalStorageHostTest.java
@@ -215,6 +215,10 @@
// Verify they both have isolated view of storage
runDeviceTests(MULTIUSER_PKG, MULTIUSER_CLASS, "testReadIsolatedStorage", owner);
runDeviceTests(MULTIUSER_PKG, MULTIUSER_CLASS, "testReadIsolatedStorage", secondary);
+
+ // Verify they can't poke at each other
+ runDeviceTests(MULTIUSER_PKG, MULTIUSER_CLASS, "testUserIsolation", owner);
+ runDeviceTests(MULTIUSER_PKG, MULTIUSER_CLASS, "testUserIsolation", secondary);
} finally {
getDevice().uninstallPackage(MULTIUSER_PKG);
removeUsersForTest(users);
diff --git a/hostsidetests/appsecurity/test-apps/ExternalStorageApp/src/com/android/cts/externalstorageapp/CommonExternalStorageTest.java b/hostsidetests/appsecurity/test-apps/ExternalStorageApp/src/com/android/cts/externalstorageapp/CommonExternalStorageTest.java
index f01db4f..7fe0b80 100644
--- a/hostsidetests/appsecurity/test-apps/ExternalStorageApp/src/com/android/cts/externalstorageapp/CommonExternalStorageTest.java
+++ b/hostsidetests/appsecurity/test-apps/ExternalStorageApp/src/com/android/cts/externalstorageapp/CommonExternalStorageTest.java
@@ -26,12 +26,14 @@
import android.test.AndroidTestCase;
import android.util.Log;
+import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
+import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -166,6 +168,21 @@
return paths;
}
+ public static List<File> getMountPaths() throws IOException {
+ final List<File> paths = new ArrayList<>();
+ final BufferedReader br = new BufferedReader(new FileReader("/proc/self/mounts"));
+ try {
+ String line;
+ while ((line = br.readLine()) != null) {
+ final String[] fields = line.split(" ");
+ paths.add(new File(fields[1]));
+ }
+ } finally {
+ br.close();
+ }
+ return paths;
+ }
+
private static File[] dropFirst(File[] before) {
final File[] after = new File[before.length - 1];
System.arraycopy(before, 1, after, 0, after.length);
diff --git a/hostsidetests/appsecurity/test-apps/ExternalStorageApp/src/com/android/cts/externalstorageapp/ExternalStorageTest.java b/hostsidetests/appsecurity/test-apps/ExternalStorageApp/src/com/android/cts/externalstorageapp/ExternalStorageTest.java
index 7dc462a..6030f1c 100644
--- a/hostsidetests/appsecurity/test-apps/ExternalStorageApp/src/com/android/cts/externalstorageapp/ExternalStorageTest.java
+++ b/hostsidetests/appsecurity/test-apps/ExternalStorageApp/src/com/android/cts/externalstorageapp/ExternalStorageTest.java
@@ -17,8 +17,10 @@
package com.android.cts.externalstorageapp;
import static com.android.cts.externalstorageapp.CommonExternalStorageTest.assertDirNoAccess;
+import static com.android.cts.externalstorageapp.CommonExternalStorageTest.assertDirNoWriteAccess;
import static com.android.cts.externalstorageapp.CommonExternalStorageTest.assertDirReadWriteAccess;
import static com.android.cts.externalstorageapp.CommonExternalStorageTest.getAllPackageSpecificPaths;
+import static com.android.cts.externalstorageapp.CommonExternalStorageTest.getMountPaths;
import android.app.DownloadManager;
import android.app.DownloadManager.Query;
@@ -34,7 +36,9 @@
import android.test.AndroidTestCase;
import android.text.format.DateUtils;
+import java.io.BufferedReader;
import java.io.File;
+import java.io.FileReader;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
@@ -76,6 +80,25 @@
}
/**
+ * Verify that we don't have read access to any storage mountpoints.
+ */
+ public void testMountPointsNotReadable() throws Exception {
+ final String userId = Integer.toString(android.os.Process.myUid() / 100000);
+ final List<File> mountPaths = getMountPaths();
+ for (File path : mountPaths) {
+ if (path.getAbsolutePath().startsWith("/mnt/")
+ || path.getAbsolutePath().startsWith("/storage/")) {
+ // Mount points could be multi-user aware, so try probing both
+ // top level and user-specific directory.
+ final File userPath = new File(path, userId);
+
+ assertDirNoAccess(path);
+ assertDirNoAccess(userPath);
+ }
+ }
+ }
+
+ /**
* Verify that we can't download things outside package directory.
*/
public void testDownloadManager() throws Exception {
diff --git a/hostsidetests/appsecurity/test-apps/MultiUserStorageApp/src/com/android/cts/multiuserstorageapp/MultiUserStorageTest.java b/hostsidetests/appsecurity/test-apps/MultiUserStorageApp/src/com/android/cts/multiuserstorageapp/MultiUserStorageTest.java
index ed84a66..d9f00d2 100644
--- a/hostsidetests/appsecurity/test-apps/MultiUserStorageApp/src/com/android/cts/multiuserstorageapp/MultiUserStorageTest.java
+++ b/hostsidetests/appsecurity/test-apps/MultiUserStorageApp/src/com/android/cts/multiuserstorageapp/MultiUserStorageTest.java
@@ -16,6 +16,7 @@
package com.android.cts.multiuserstorageapp;
+import static com.android.cts.externalstorageapp.CommonExternalStorageTest.assertDirNoAccess;
import static com.android.cts.externalstorageapp.CommonExternalStorageTest.getAllPackageSpecificPathsExceptObb;
import static com.android.cts.externalstorageapp.CommonExternalStorageTest.readInt;
import static com.android.cts.externalstorageapp.CommonExternalStorageTest.writeInt;
@@ -119,6 +120,24 @@
readInt(buildRawObbPath(FILE_OBB_SINGLETON)));
}
+ /**
+ * Verify that we can't poke at storage of other users.
+ */
+ public void testUserIsolation() throws Exception {
+ final File myPath = Environment.getExternalStorageDirectory();
+ final int myId = android.os.Process.myUid() / 100000;
+ assertEquals(String.valueOf(myId), myPath.getName());
+
+ Log.d(TAG, "My path is " + myPath);
+ final File basePath = myPath.getParentFile();
+ for (int i = 0; i < 128; i++) {
+ if (i == myId) continue;
+
+ final File otherPath = new File(basePath, String.valueOf(i));
+ assertDirNoAccess(otherPath);
+ }
+ }
+
private File buildApiObbPath(String file) {
return new File(getContext().getObbDir(), file);
}
diff --git a/hostsidetests/appsecurity/test-apps/ReadExternalStorageApp/src/com/android/cts/readexternalstorageapp/ReadExternalStorageTest.java b/hostsidetests/appsecurity/test-apps/ReadExternalStorageApp/src/com/android/cts/readexternalstorageapp/ReadExternalStorageTest.java
index 71faab2..995da90 100644
--- a/hostsidetests/appsecurity/test-apps/ReadExternalStorageApp/src/com/android/cts/readexternalstorageapp/ReadExternalStorageTest.java
+++ b/hostsidetests/appsecurity/test-apps/ReadExternalStorageApp/src/com/android/cts/readexternalstorageapp/ReadExternalStorageTest.java
@@ -16,9 +16,11 @@
package com.android.cts.readexternalstorageapp;
+import static com.android.cts.externalstorageapp.CommonExternalStorageTest.assertDirNoWriteAccess;
import static com.android.cts.externalstorageapp.CommonExternalStorageTest.assertDirReadOnlyAccess;
import static com.android.cts.externalstorageapp.CommonExternalStorageTest.assertDirReadWriteAccess;
import static com.android.cts.externalstorageapp.CommonExternalStorageTest.getAllPackageSpecificPaths;
+import static com.android.cts.externalstorageapp.CommonExternalStorageTest.getMountPaths;
import android.os.Environment;
import android.test.AndroidTestCase;
@@ -64,4 +66,23 @@
}
}
}
+
+ /**
+ * Verify that we don't have write access to any mountpoints.
+ */
+ public void testMountPointsNotWritable() throws Exception {
+ final String userId = Integer.toString(android.os.Process.myUid() / 100000);
+ final List<File> mountPaths = getMountPaths();
+ for (File path : mountPaths) {
+ if (path.getAbsolutePath().startsWith("/mnt/")
+ || path.getAbsolutePath().startsWith("/storage/")) {
+ // Mount points could be multi-user aware, so try probing both
+ // top level and user-specific directory.
+ final File userPath = new File(path, userId);
+
+ assertDirNoWriteAccess(path);
+ assertDirNoWriteAccess(userPath);
+ }
+ }
+ }
}
diff --git a/hostsidetests/appsecurity/test-apps/WriteExternalStorageApp/src/com/android/cts/writeexternalstorageapp/WriteExternalStorageTest.java b/hostsidetests/appsecurity/test-apps/WriteExternalStorageApp/src/com/android/cts/writeexternalstorageapp/WriteExternalStorageTest.java
index badc852..5e6aa3e 100644
--- a/hostsidetests/appsecurity/test-apps/WriteExternalStorageApp/src/com/android/cts/writeexternalstorageapp/WriteExternalStorageTest.java
+++ b/hostsidetests/appsecurity/test-apps/WriteExternalStorageApp/src/com/android/cts/writeexternalstorageapp/WriteExternalStorageTest.java
@@ -24,6 +24,7 @@
import static com.android.cts.externalstorageapp.CommonExternalStorageTest.buildProbeFile;
import static com.android.cts.externalstorageapp.CommonExternalStorageTest.deleteContents;
import static com.android.cts.externalstorageapp.CommonExternalStorageTest.getAllPackageSpecificPaths;
+import static com.android.cts.externalstorageapp.CommonExternalStorageTest.getMountPaths;
import static com.android.cts.externalstorageapp.CommonExternalStorageTest.getPrimaryPackageSpecificPaths;
import static com.android.cts.externalstorageapp.CommonExternalStorageTest.getSecondaryPackageSpecificPaths;
import static com.android.cts.externalstorageapp.CommonExternalStorageTest.readInt;
@@ -35,9 +36,7 @@
import com.android.cts.externalstorageapp.CommonExternalStorageTest;
-import java.io.BufferedReader;
import java.io.File;
-import java.io.FileReader;
import java.util.List;
import java.util.Random;
@@ -273,28 +272,29 @@
* {@link CommonExternalStorageTest#testAllPackageDirsWritable()}.
*/
public void testSecondaryMountPointsNotWritable() throws Exception {
+ // Probe path could be /storage/emulated/0 or /storage/1234-5678
final File probe = buildProbeFile(Environment.getExternalStorageDirectory());
assertTrue(probe.createNewFile());
- final BufferedReader br = new BufferedReader(new FileReader("/proc/self/mounts"));
- try {
- String line;
- while ((line = br.readLine()) != null) {
- final String[] fields = line.split(" ");
- final File testMount = new File(fields[1]);
- final File testProbe = new File(testMount, probe.getName());
- if (testProbe.exists()) {
- Log.d(TAG, "Primary external mountpoint " + testMount);
- } else {
- // This mountpoint is not primary external storage; we must
- // not be able to write.
- Log.d(TAG, "Other mountpoint " + testMount);
- assertDirNoWriteAccess(testProbe.getParentFile());
- }
+ final String userId = Integer.toString(android.os.Process.myUid() / 100000);
+ final List<File> mountPaths = getMountPaths();
+ for (File path : mountPaths) {
+ // Mount points could be multi-user aware, so try probing both top
+ // level and user-specific directory.
+ final File userPath = new File(path, userId);
+
+ final File testProbe = new File(path, probe.getName());
+ final File testUserProbe = new File(userPath, probe.getName());
+
+ if (testProbe.exists() || testUserProbe.exists()) {
+ Log.d(TAG, "Primary external mountpoint " + path);
+ } else {
+ // This mountpoint is not primary external storage; we must
+ // not be able to write.
+ Log.d(TAG, "Other mountpoint " + path);
+ assertDirNoWriteAccess(path);
+ assertDirNoWriteAccess(userPath);
}
- } finally {
- br.close();
- probe.delete();
- }
+ }
}
}
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/AndroidManifest.xml b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/AndroidManifest.xml
index 07b6953..ed920e9 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/AndroidManifest.xml
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/AndroidManifest.xml
@@ -18,6 +18,9 @@
package="com.android.cts.deviceandprofileowner">
<uses-sdk android:minSdkVersion="23"/>
+ <uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" />
+ <uses-permission android:name="android.permission.GET_ACCOUNTS" />
+ <uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />
<application>
<uses-library android:name="android.test.runner" />
@@ -50,6 +53,15 @@
</intent-filter>
</activity>
+ <service android:name=".MockAccountService" android:exported="true">
+ <intent-filter>
+ <action android:name="android.accounts.AccountAuthenticator" />
+ </intent-filter>
+
+ <meta-data android:name="android.accounts.AccountAuthenticator"
+ android:resource="@xml/authenticator" />
+ </service>
+
</application>
<instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/res/values/strings.xml b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/res/values/strings.xml
new file mode 100644
index 0000000..4aca824
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/res/values/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Label for this package -->
+ <string name="authenticator_label">Android CTS - Device and Profile Owner</string>
+</resources>
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/res/xml/authenticator.xml b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/res/xml/authenticator.xml
new file mode 100644
index 0000000..0d8ecd8
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/res/xml/authenticator.xml
@@ -0,0 +1,22 @@
+<!-- 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.
+-->
+
+<!-- The attributes in this XML file provide configuration information -->
+<!-- for the Account Manager. -->
+
+<account-authenticator xmlns:android="http://schemas.android.com/apk/res/android"
+ android:accountType="com.android.cts.deviceandprofileowner.account.type"
+ android:label="@string/authenticator_label"
+/>
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/AccountManagementTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/AccountManagementTest.java
new file mode 100644
index 0000000..c40539b8
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/AccountManagementTest.java
@@ -0,0 +1,179 @@
+/*
+ * 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.deviceandprofileowner;
+
+import android.accounts.Account;
+import android.accounts.AccountManager;
+import android.accounts.AccountManagerFuture;
+import android.accounts.AuthenticatorException;
+import android.accounts.OperationCanceledException;
+import android.app.admin.DevicePolicyManager;
+import android.content.Context;
+import android.os.Bundle;
+
+import java.io.IOException;
+
+/**
+ * Functionality tests for {@link DevicePolicyManager#setAccountManagementDisabled}
+ *
+ * Fire up a remote unprivileged service and attempt to add/remove/list
+ * accounts from it to verify the enforcement is in place.
+ *
+ * This test depend on MockAccountService, which provides authenticator of type
+ * {@code com.android.cts.deviceandprofileowner.account.type}
+ */
+public class AccountManagementTest extends BaseDeviceAdminTest {
+
+ // Account type for MockAccountAuthenticator
+ private final static String ACCOUNT_TYPE_1 =
+ "com.android.cts.deviceandprofileowner.account.type";
+ private final static String ACCOUNT_TYPE_2 = "com.dummy.account";
+ private final static Account ACCOUNT_0 = new Account("user0", ACCOUNT_TYPE_1);
+ private final static Account ACCOUNT_1 = new Account("user1", ACCOUNT_TYPE_1);
+
+ private AccountManager mAccountManager;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mAccountManager = (AccountManager) mContext.getSystemService(Context.ACCOUNT_SERVICE);
+ clearAllAccountManagementDisabled();
+ removeAllAccounts();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ clearAllAccountManagementDisabled();
+ removeAllAccounts();
+ super.tearDown();
+ }
+
+ public void testAccountManagementDisabled_setterAndGetter() {
+ // Some local tests: adding and removing disabled accounts and make sure
+ // DevicePolicyManager keeps track of the disabled set correctly
+ assertEquals(0, mDevicePolicyManager.getAccountTypesWithManagementDisabled().length);
+
+ mDevicePolicyManager.setAccountManagementDisabled(ADMIN_RECEIVER_COMPONENT, ACCOUNT_TYPE_1,
+ true);
+ assertEquals(1, mDevicePolicyManager.getAccountTypesWithManagementDisabled().length);
+ assertEquals(ACCOUNT_TYPE_1,
+ mDevicePolicyManager.getAccountTypesWithManagementDisabled()[0]);
+
+ mDevicePolicyManager.setAccountManagementDisabled(ADMIN_RECEIVER_COMPONENT, ACCOUNT_TYPE_1,
+ false);
+ assertEquals(0, mDevicePolicyManager.getAccountTypesWithManagementDisabled().length);
+ }
+
+ public void testAccountManagementDisabled_addAccount() throws AuthenticatorException,
+ IOException, OperationCanceledException {
+ // Test for restriction on addAccount()
+ mDevicePolicyManager.setAccountManagementDisabled(ADMIN_RECEIVER_COMPONENT, ACCOUNT_TYPE_1,
+ true);
+ // Test if disabling ACCOUNT_TYPE_2 affects ACCOUNT_TYPE_1
+ mDevicePolicyManager.setAccountManagementDisabled(ADMIN_RECEIVER_COMPONENT, ACCOUNT_TYPE_2,
+ false);
+ assertEquals(1, mDevicePolicyManager.getAccountTypesWithManagementDisabled().length);
+
+ assertEquals(0, mAccountManager.getAccountsByType(ACCOUNT_TYPE_1).length);
+ // Management is disabled, adding account should fail.
+ try {
+ mAccountManager.addAccount(ACCOUNT_TYPE_1, null, null, null, null, null, null)
+ .getResult();
+ fail("Expected OperationCanceledException is not thrown.");
+ } catch (OperationCanceledException e) {
+ // Expected
+ }
+ assertEquals(0, mAccountManager.getAccountsByType(ACCOUNT_TYPE_1).length);
+
+ // Management is re-enabled, adding account should succeed.
+ mDevicePolicyManager.setAccountManagementDisabled(ADMIN_RECEIVER_COMPONENT, ACCOUNT_TYPE_1,
+ false);
+ assertEquals(0, mDevicePolicyManager.getAccountTypesWithManagementDisabled().length);
+ Bundle result = mAccountManager.addAccount(ACCOUNT_TYPE_1,
+ null, null, null, null, null, null).getResult();
+
+ // Normally the expected result of addAccount() is AccountManager returning
+ // an intent to start the authenticator activity for adding new accounts.
+ // But MockAccountAuthenticator returns a new account straightway.
+ assertEquals(ACCOUNT_TYPE_1, result.getString(AccountManager.KEY_ACCOUNT_TYPE));
+ }
+
+ public void testAccountManagementDisabled_removeAccount() throws AuthenticatorException,
+ IOException, OperationCanceledException {
+ // Test for restriction on removeAccount()
+ mDevicePolicyManager.setAccountManagementDisabled(ADMIN_RECEIVER_COMPONENT, ACCOUNT_TYPE_1,
+ true);
+ mDevicePolicyManager.setAccountManagementDisabled(ADMIN_RECEIVER_COMPONENT, ACCOUNT_TYPE_2,
+ false);
+ assertEquals(1, mDevicePolicyManager.getAccountTypesWithManagementDisabled().length);
+
+ assertEquals(0, mAccountManager.getAccountsByType(ACCOUNT_TYPE_1).length);
+ // First prepare some accounts by manually adding them,
+ // setAccountManagementDisabled(true) should not stop addAccountExplicitly().
+ assertTrue(mAccountManager.addAccountExplicitly(ACCOUNT_0, "password", null));
+ assertTrue(mAccountManager.addAccountExplicitly(ACCOUNT_1, "password", null));
+ assertEquals(2, mAccountManager.getAccountsByType(ACCOUNT_TYPE_1).length);
+
+ // Removing account should fail, as we just disabled it.
+ try {
+ mAccountManager.removeAccount(ACCOUNT_0, null, null).getResult();
+ fail("Expected OperationCanceledException is not thrown.");
+ } catch (OperationCanceledException e) {
+ // Expected
+ }
+ assertEquals(2, mAccountManager.getAccountsByType(ACCOUNT_TYPE_1).length);
+
+ // Re-enable management, so we can successfully remove account this time.
+ mDevicePolicyManager.setAccountManagementDisabled(ADMIN_RECEIVER_COMPONENT, ACCOUNT_TYPE_1,
+ false);
+ assertEquals(0, mDevicePolicyManager.getAccountTypesWithManagementDisabled().length);
+ assertTrue(mAccountManager.removeAccount(ACCOUNT_0, null, null).getResult());
+
+ // Make sure the removal actually succeeds.
+ Account[] accounts = mAccountManager.getAccountsByType(ACCOUNT_TYPE_1);
+ assertEquals(1, accounts.length);
+ assertEquals(ACCOUNT_1, accounts[0]);
+
+ // Disable account type 2, we should still be able to remove from type 1.
+ mDevicePolicyManager.setAccountManagementDisabled(ADMIN_RECEIVER_COMPONENT, ACCOUNT_TYPE_2,
+ true);
+ assertEquals(1, mDevicePolicyManager.getAccountTypesWithManagementDisabled().length);
+ assertTrue(mAccountManager.removeAccount(ACCOUNT_1, null, null).getResult());
+
+ // Make sure the removal actually succeeds.
+ assertEquals(0, mAccountManager.getAccountsByType(ACCOUNT_TYPE_1).length);
+ }
+
+ private void clearAllAccountManagementDisabled() {
+ for (String accountType : mDevicePolicyManager.getAccountTypesWithManagementDisabled()) {
+ mDevicePolicyManager.setAccountManagementDisabled(ADMIN_RECEIVER_COMPONENT, accountType,
+ false);
+ }
+ assertEquals(0, mDevicePolicyManager.getAccountTypesWithManagementDisabled().length);
+ }
+
+ private void removeAllAccounts() throws OperationCanceledException, AuthenticatorException,
+ IOException {
+ for (Account account : mAccountManager.getAccountsByType(ACCOUNT_TYPE_1)) {
+ AccountManagerFuture<Boolean> result = mAccountManager.removeAccount(account, null,
+ null);
+ assertTrue(result.getResult());
+ }
+ assertEquals(0, mAccountManager.getAccountsByType(ACCOUNT_TYPE_1).length);
+ }
+
+}
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/MockAccountAuthenticator.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/MockAccountAuthenticator.java
new file mode 100644
index 0000000..161410f
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/MockAccountAuthenticator.java
@@ -0,0 +1,100 @@
+/*
+ * 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.deviceandprofileowner;
+
+import android.accounts.AbstractAccountAuthenticator;
+import android.accounts.Account;
+import android.accounts.AccountAuthenticatorResponse;
+import android.accounts.AccountManager;
+import android.accounts.NetworkErrorException;
+import android.content.Context;
+import android.os.Bundle;
+
+/* package */ class MockAccountAuthenticator extends AbstractAccountAuthenticator {
+ private static MockAccountAuthenticator sMockAuthenticator = null;
+ private static final String ACCOUNT_NAME = "com.android.cts.deviceandprofileowner.account.name";
+ private static final String ACCOUNT_TYPE = "com.android.cts.deviceandprofileowner.account.type";
+ private static final String AUTH_TOKEN = "mockAuthToken";
+ private static final String AUTH_TOKEN_LABEL = "mockAuthTokenLabel";
+
+ private MockAccountAuthenticator(Context context) {
+ super(context);
+ }
+
+ private Bundle createResultBundle() {
+ Bundle result = new Bundle();
+ result.putString(AccountManager.KEY_ACCOUNT_NAME, ACCOUNT_NAME);
+ result.putString(AccountManager.KEY_ACCOUNT_TYPE, ACCOUNT_TYPE);
+ result.putString(AccountManager.KEY_AUTHTOKEN, AUTH_TOKEN);
+
+ return result;
+ }
+
+ @Override
+ public Bundle addAccount(AccountAuthenticatorResponse response, String accountType,
+ String authTokenType, String[] requiredFeatures, Bundle options)
+ throws NetworkErrorException {
+ return createResultBundle();
+ }
+
+ @Override
+ public Bundle editProperties(AccountAuthenticatorResponse response, String accountType) {
+ return createResultBundle();
+ }
+
+ @Override
+ public Bundle updateCredentials(AccountAuthenticatorResponse response, Account account,
+ String authTokenType, Bundle options) throws NetworkErrorException {
+ return createResultBundle();
+ }
+
+ @Override
+ public Bundle confirmCredentials(AccountAuthenticatorResponse response, Account account,
+ Bundle options) throws NetworkErrorException {
+
+ Bundle result = new Bundle();
+ result.putBoolean(AccountManager.KEY_BOOLEAN_RESULT, true);
+ return result;
+ }
+
+ @Override
+ public Bundle getAuthToken(AccountAuthenticatorResponse response, Account account,
+ String authTokenType, Bundle options) throws NetworkErrorException {
+ return createResultBundle();
+ }
+
+ @Override
+ public String getAuthTokenLabel(String authTokenType) {
+ return AUTH_TOKEN_LABEL;
+ }
+
+ @Override
+ public Bundle hasFeatures(AccountAuthenticatorResponse response, Account account,
+ String[] features) throws NetworkErrorException {
+
+ Bundle result = new Bundle();
+ result.putBoolean(AccountManager.KEY_BOOLEAN_RESULT, true);
+ return result;
+ }
+
+ public static synchronized MockAccountAuthenticator getMockAuthenticator(Context context) {
+ if (null == sMockAuthenticator) {
+ sMockAuthenticator = new MockAccountAuthenticator(context);
+ }
+ return sMockAuthenticator;
+ }
+}
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/MockAccountService.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/MockAccountService.java
new file mode 100644
index 0000000..dfedccb
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/MockAccountService.java
@@ -0,0 +1,32 @@
+/*
+ * 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.deviceandprofileowner;
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.IBinder;
+
+/**
+ * a basic Mock Service for wrapping the MockAccountAuthenticator
+ */
+public class MockAccountService extends Service {
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return MockAccountAuthenticator.getMockAuthenticator(this).getIBinder();
+ }
+}
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/NfcTest.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/NfcTest.java
new file mode 100644
index 0000000..c74211d
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/NfcTest.java
@@ -0,0 +1,59 @@
+/*
+ * 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.managedprofile;
+
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.test.AndroidTestCase;
+import android.util.Log;
+
+public class NfcTest extends AndroidTestCase {
+ private static final String SAMPLE_TEXT = "This is my text to send.";
+ private static final String TEXT_MIME_TYPE = "text/plain";
+ private static final String NFC_BEAM_ACTIVITY = "com.android.nfc.BeamShareActivity";
+
+ public void testNfcShareDisabled() throws Exception {
+ Intent intent = getTextShareIntent();
+ assertFalse("Nfc beam activity should not be resolved", isNfcBeamActivityResolved(intent));
+ }
+
+ public void testNfcShareEnabled() throws Exception {
+ Intent intent = getTextShareIntent();
+ assertTrue("Nfc beam activity should be resolved", isNfcBeamActivityResolved(intent));
+ }
+
+ private Intent getTextShareIntent() {
+ Intent intent = new Intent();
+ intent.setAction(Intent.ACTION_SEND);
+ intent.putExtra(Intent.EXTRA_TEXT, SAMPLE_TEXT);
+ intent.setType(TEXT_MIME_TYPE);
+ return intent;
+ }
+
+ private boolean isNfcBeamActivityResolved(Intent intent) {
+ PackageManager pm = mContext.getPackageManager();
+ for (ResolveInfo resolveInfo : pm.queryIntentActivities(intent, 0)) {
+ if (NFC_BEAM_ACTIVITY.equals(resolveInfo.activityInfo.name)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+}
+
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/CustomDeviceOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/CustomDeviceOwnerTest.java
index adf81a3..e6351c5 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/CustomDeviceOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/CustomDeviceOwnerTest.java
@@ -37,6 +37,24 @@
private static final String ADMIN_RECEIVER_TEST_CLASS =
DEVICE_OWNER_PKG + ".BaseDeviceOwnerTest$BasicAdminReceiver";
+ private static final String ADMIN_RECEIVER_COMPONENT =
+ DEVICE_OWNER_PKG + "/" + ADMIN_RECEIVER_TEST_CLASS;
+
+ public void setUp() throws Exception {
+ super.setUp();
+
+ if (mHasFeature) {
+ installApp(DEVICE_OWNER_APK);
+ }
+ }
+
+ public void tearDown() throws Exception {
+ if (mHasFeature) {
+ getDevice().uninstallPackage(DEVICE_OWNER_PKG);
+ }
+
+ super.tearDown();
+ }
public void testOwnerChangedBroadcast() throws Exception {
if (!mHasFeature) {
@@ -44,7 +62,6 @@
}
try {
installApp(INTENT_RECEIVER_APK);
- installApp(DEVICE_OWNER_APK);
String testClass = INTENT_RECEIVER_PKG + ".OwnerChangedBroadcastTest";
@@ -54,15 +71,27 @@
"testOwnerChangedBroadcastNotReceived", 0));
// Setting the device owner should send the owner changed broadcast.
- setDeviceOwner(DEVICE_OWNER_PKG + "/" + ADMIN_RECEIVER_TEST_CLASS);
+ assertTrue(setDeviceOwner(ADMIN_RECEIVER_COMPONENT));
assertTrue(runDeviceTests(INTENT_RECEIVER_PKG, testClass,
"testOwnerChangedBroadcastReceived", 0));
} finally {
+ getDevice().uninstallPackage(INTENT_RECEIVER_PKG);
assertTrue("Failed to remove device owner.",
runDeviceTests(DEVICE_OWNER_PKG, CLEAR_DEVICE_OWNER_TEST_CLASS));
- getDevice().uninstallPackage(DEVICE_OWNER_PKG);
- getDevice().uninstallPackage(INTENT_RECEIVER_PKG);
+ }
+ }
+
+ public void testCannotSetDeviceOwnerWhenSecondaryUserPresent() throws Exception {
+ if (!mHasFeature) {
+ return;
+ }
+ int userId = -1;
+ try {
+ userId = createUser();
+ assertFalse(setDeviceOwner(ADMIN_RECEIVER_COMPONENT));
+ } finally {
+ removeUser(userId);
}
}
}
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java
index 45f3618..36dab2c 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java
@@ -16,12 +16,6 @@
package com.android.cts.devicepolicy;
-import com.android.ddmlib.Log.LogLevel;
-import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.log.LogUtil.CLog;
-
-import junit.framework.AssertionFailedError;
-
/**
* Set of tests for usecases that apply to profile and device owner.
* This class is the base class of MixedProfileOwnerTest and MixedDeviceOwnerTest and is abstract
@@ -46,6 +40,7 @@
// is the user id of the created profile.
protected int mUserId;
+ @Override
protected void tearDown() throws Exception {
if (mHasFeature) {
getDevice().uninstallPackage(DEVICE_ADMIN_PKG);
@@ -164,6 +159,15 @@
executeDeviceTestClass(".ApplicationHiddenTest");
}
+ // TODO: Remove AccountManagementTest from XTS after GTS is released for MNC.
+ public void testAccountManagement() throws Exception {
+ if (!mHasFeature) {
+ return;
+ }
+
+ executeDeviceTestClass(".AccountManagementTest");
+ }
+
protected void executeDeviceTestClass(String className) throws Exception {
assertTrue(runDeviceTestsAsUser(DEVICE_ADMIN_PKG, className, mUserId));
}
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
index a1ae9b9..54b535a 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
@@ -62,6 +62,8 @@
private int mUserId;
private String mPackageVerifier;
+ private boolean mHasNfcFeature;
+
@Override
protected void setUp() throws Exception {
super.setUp();
@@ -69,6 +71,7 @@
// We need multi user to be supported in order to create a profile of the user owner.
mHasFeature = mHasFeature && hasDeviceFeature(
"android.software.managed_users");
+ mHasNfcFeature = hasDeviceFeature("android.hardware.nfc");
if (mHasFeature) {
removeTestUsers();
@@ -563,6 +566,30 @@
}
}
+ public void testNfcRestriction() throws Exception {
+ if (!mHasFeature || !mHasNfcFeature) {
+ return;
+ }
+
+ assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".NfcTest",
+ "testNfcShareEnabled", mUserId));
+ assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".NfcTest",
+ "testNfcShareEnabled", 0));
+
+ String restriction = "no_outgoing_beam"; // UserManager.DISALLOW_OUTGOING_BEAM
+ String command = "add-restriction";
+
+ String addRestrictionCommandOutput =
+ changeUserRestrictionForUser(restriction, command, mUserId);
+ assertTrue("Command was expected to succeed " + addRestrictionCommandOutput,
+ addRestrictionCommandOutput.contains("Status: ok"));
+
+ assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".NfcTest",
+ "testNfcShareDisabled", mUserId));
+ assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".NfcTest",
+ "testNfcShareEnabled", 0));
+ }
+
private void disableActivityForUser(String activityName, int userId)
throws DeviceNotAvailableException {
String command = "am start -W --user " + userId
diff --git a/libs/deviceutil/src/android/cts/util/MediaUtils.java b/libs/deviceutil/src/android/cts/util/MediaUtils.java
index c04a2cf..c595e10 100644
--- a/libs/deviceutil/src/android/cts/util/MediaUtils.java
+++ b/libs/deviceutil/src/android/cts/util/MediaUtils.java
@@ -459,12 +459,13 @@
return avgs;
}
- public static void logResults(ReportLog log, String prefix,
+ public static String logResults(ReportLog log, String prefix,
double min, double max, double avg, double stdev) {
String msg = prefix;
msg += " min=" + Math.round(min / 1000) + " max=" + Math.round(max / 1000) +
" avg=" + Math.round(avg / 1000) + " stdev=" + Math.round(stdev / 1000);
log.printValue(msg, 1000000000 / min, ResultType.HIGHER_BETTER, ResultUnit.FPS);
+ return msg;
}
public static VideoCapabilities getVideoCapabilities(String codecName, String mime) {
@@ -512,4 +513,17 @@
return (measured >= lowerBoundary1 && measured <= upperBoundary1 &&
measured >= lowerBoundary2 && measured <= upperBoundary2);
}
+
+ public static String getErrorMessage(
+ Range<Double> reportedRange, double[] measuredFps, String[] rawData) {
+ String msg = "";
+ if (reportedRange == null) {
+ msg += "Failed to get achievable frame rate.\n";
+ } else {
+ msg += "Expected achievable frame rate range: " + reportedRange + ".\n";
+ }
+ msg += "Measured frame rate: " + Arrays.toString(measuredFps) + ".\n";
+ msg += "Raw data: " + Arrays.toString(rawData) + ".\n";
+ return msg;
+ }
}
diff --git a/suite/cts/deviceTests/videoperf/src/com/android/cts/videoperf/VideoEncoderDecoderTest.java b/suite/cts/deviceTests/videoperf/src/com/android/cts/videoperf/VideoEncoderDecoderTest.java
index 8fc5a44..62f37c5 100644
--- a/suite/cts/deviceTests/videoperf/src/com/android/cts/videoperf/VideoEncoderDecoderTest.java
+++ b/suite/cts/deviceTests/videoperf/src/com/android/cts/videoperf/VideoEncoderDecoderTest.java
@@ -516,6 +516,8 @@
boolean encTestPassed = false;
boolean decTestPassed = false;
+ double[] measuredFps = new double[mTestConfig.mNumberOfRepeat];
+ String[] resultRawData = new String[mTestConfig.mNumberOfRepeat];
for (int i = 0; i < mTestConfig.mNumberOfRepeat; i++) {
// make sure that rms error is not too big.
if (decoderRmsErrorResults[i] >= mRmsErrorMargain) {
@@ -542,8 +544,11 @@
String prefix = "codec=" + encoderName + " round=" + i +
" EncInputFormat=" + mEncInputFormat +
" EncOutputFormat=" + mEncOutputFormat;
- MediaUtils.logResults(mReportLog, prefix, encMin, encMax, encAvg, encStdev);
+ String result =
+ MediaUtils.logResults(mReportLog, prefix, encMin, encMax, encAvg, encStdev);
double measuredEncFps = 1000000000 / encMin;
+ resultRawData[i] = result;
+ measuredFps[i] = measuredEncFps;
if (!encTestPassed) {
encTestPassed = MediaUtils.verifyResults(
encoderName, mimeType, w, h, measuredEncFps);
@@ -565,10 +570,14 @@
}
}
}
+
if (mTestConfig.mTestResult) {
if (!encTestPassed) {
- fail("Measured fps for " + encoderName +
- " doesn't match with reported achievable frame rates.");
+ Range<Double> reportedRange =
+ MediaUtils.getAchievableFrameRatesFor(encoderName, mimeType, w, h);
+ String failMessage =
+ MediaUtils.getErrorMessage(reportedRange, measuredFps, resultRawData);
+ fail(failMessage);
}
// Decoder result will be verified in VideoDecoderPerfTest
// if (!decTestPassed) {
@@ -576,6 +585,8 @@
// " doesn't match with reported achievable frame rates.");
// }
}
+ measuredFps = null;
+ resultRawData = null;
}
/**
diff --git a/tests/deviceadmin/res/xml/device_admin.xml b/tests/deviceadmin/res/xml/device_admin.xml
index 263fda6..f7d394e 100644
--- a/tests/deviceadmin/res/xml/device_admin.xml
+++ b/tests/deviceadmin/res/xml/device_admin.xml
@@ -22,6 +22,7 @@
<force-lock />
<wipe-data />
<expire-password />
+ <disable-keyguard-features />
</uses-policies>
</device-admin>
diff --git a/tests/tests/admin/src/android/admin/cts/DevicePolicyManagerTest.java b/tests/tests/admin/src/android/admin/cts/DevicePolicyManagerTest.java
index 04e2ba3..66e12c0 100644
--- a/tests/tests/admin/src/android/admin/cts/DevicePolicyManagerTest.java
+++ b/tests/tests/admin/src/android/admin/cts/DevicePolicyManagerTest.java
@@ -526,6 +526,23 @@
}
}
+ public void testKeyguardDisabledFeatures() {
+ if (!mDeviceAdmin) {
+ Log.w(TAG, "Skipping testKeyguardDisabledFeatures");
+ return;
+ }
+ int originalValue = mDevicePolicyManager.getKeyguardDisabledFeatures(mComponent);
+ try {
+ for (int which = DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_NONE;
+ which < 2 * DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT; ++which) {
+ mDevicePolicyManager.setKeyguardDisabledFeatures(mComponent, which);
+ assertEquals(which, mDevicePolicyManager.getKeyguardDisabledFeatures(mComponent));
+ }
+ } finally {
+ mDevicePolicyManager.setKeyguardDisabledFeatures(mComponent, originalValue);
+ }
+ }
+
public void testCreateUser_failIfNotDeviceOwner() {
if (!mDeviceAdmin) {
Log.w(TAG, "Skipping testCreateUser_failIfNotDeviceOwner");
diff --git a/tests/tests/assist/AndroidManifest.xml b/tests/tests/assist/AndroidManifest.xml
index c5772ad..b6cd684 100644
--- a/tests/tests/assist/AndroidManifest.xml
+++ b/tests/tests/assist/AndroidManifest.xml
@@ -28,6 +28,7 @@
<intent-filter>
<action android:name="android.intent.action.TEST_START_ACTIVITY_ASSIST_STRUCTURE" />
<action android:name="android.intent.action.TEST_START_ACTIVITY_DISABLE_CONTEXT" />
+ <action android:name="android.intent.action.TEST_START_ACTIVITY_FLAG_SECURE" />
<category android:name="android.intent.category.LAUNCHER" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
diff --git a/tests/tests/assist/common/src/android/voiceinteraction/common/Utils.java b/tests/tests/assist/common/src/android/assist/common/Utils.java
similarity index 61%
rename from tests/tests/assist/common/src/android/voiceinteraction/common/Utils.java
rename to tests/tests/assist/common/src/android/assist/common/Utils.java
index b9fb7cf..bf051c0 100644
--- a/tests/tests/assist/common/src/android/voiceinteraction/common/Utils.java
+++ b/tests/tests/assist/common/src/android/assist/common/Utils.java
@@ -15,23 +15,13 @@
*/
package android.assist.common;
-import android.app.VoiceInteractor;
-import android.app.VoiceInteractor.PickOptionRequest.Option;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
+import android.R;
+import android.content.ComponentName;
import android.os.Bundle;
-import android.util.Log;
import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.concurrent.CountDownLatch;
public class Utils {
- public enum TestCaseType {
- ASSIST_STRUCTURE,
- DISABLE_CONTEXT,
- }
public static final String TESTCASE_TYPE = "testcase_type";
public static final String TESTINFO = "testinfo";
public static final String BROADCAST_INTENT = "android.intent.action.ASSIST_TESTAPP";
@@ -40,17 +30,46 @@
public static final String ASSIST_STRUCTURE_KEY = "assist_structure";
public static final String ASSIST_CONTENT_KEY = "assist_content";
- public static final String ASSIST_BUNDLE = "assist_bundle";
+ public static final String ASSIST_BUNDLE_KEY = "assist_bundle";
+ public static final String ASSIST_SCREENSHOT_KEY = "assist_screenshot";
public static final int TIMEOUT_MS = 2 * 1000; // TODO(awlee): what is the timeout
+ /** Test name suffixes */
+ public static final String ASSIST_STRUCTURE = "ASSIST_STRUCTURE";
+ public static final String DISABLE_CONTEXT = "DISABLE_CONTEXT";
+ public static final String FLAG_SECURE = "FLAG_SECURE";
+
+ /**
+ * The shim activity that starts the service associated with each test.
+ */
public static final String getTestActivity(String testCaseType) {
- if (testCaseType.equals("ASSIST_STRUCTURE")) {
- return "service.AssistStructureActivity";
- } else if (testCaseType.equals("DISABLE_CONTEXT")) {
- return "service.DisableContextActivity";
+ switch (testCaseType) {
+ case ASSIST_STRUCTURE:
+ case FLAG_SECURE:
+ return "service.AssistStructureActivity";
+ case DISABLE_CONTEXT:
+ return "service.DisableContextActivity";
+ default:
+ return "";
}
- return "";
+ }
+
+ /**
+ * The test app associated with each test.
+ */
+ public static final ComponentName getTestAppComponent(String testCaseType) {
+ switch (testCaseType) {
+ case ASSIST_STRUCTURE:
+ case DISABLE_CONTEXT:
+ return new ComponentName(
+ "android.assist.testapp", "android.assist.testapp.TestApp");
+ case FLAG_SECURE:
+ return new ComponentName(
+ "android.assist.testapp", "android.assist.testapp.SecureActivity");
+ default:
+ return new ComponentName("","");
+ }
}
public static final String toBundleString(Bundle bundle) {
@@ -71,19 +90,6 @@
return buf.toString();
}
- public static final String toOptionsString(Option[] options) {
- StringBuilder sb = new StringBuilder();
- sb.append("{");
- for (int i = 0; i < options.length; i++) {
- if (i >= 1) {
- sb.append(", ");
- }
- sb.append(options[i].getLabel());
- }
- sb.append("}");
- return sb.toString();
- }
-
public static final void addErrorResult(final Bundle testinfo, final String msg) {
testinfo.getStringArrayList(testinfo.getString(Utils.TESTCASE_TYPE))
.add(TEST_ERROR + " " + msg);
diff --git a/tests/tests/assist/service/AndroidManifest.xml b/tests/tests/assist/service/AndroidManifest.xml
index 543568d..2c5206a 100644
--- a/tests/tests/assist/service/AndroidManifest.xml
+++ b/tests/tests/assist/service/AndroidManifest.xml
@@ -34,6 +34,7 @@
<activity android:name=".AssistStructureActivity" >
<intent-filter>
<action android:name="android.intent.action.START_TEST_ASSIST_STRUCTURE" />
+ <action android:name="android.intent.action.START_TEST_FLAG_SECURE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
diff --git a/tests/tests/assist/service/src/android/voiceinteraction/service/AssistStructureActivity.java b/tests/tests/assist/service/src/android/voiceinteraction/service/AssistStructureActivity.java
index 8b63b25..784d63b 100644
--- a/tests/tests/assist/service/src/android/voiceinteraction/service/AssistStructureActivity.java
+++ b/tests/tests/assist/service/src/android/voiceinteraction/service/AssistStructureActivity.java
@@ -35,8 +35,8 @@
super.onStart();
Intent intent = new Intent();
intent.setComponent(new ComponentName(this, MainInteractionService.class));
- ComponentName serviceName = startService(intent);
- Log.i(TAG, "Started service: " + serviceName);
- getLayoutInflater().inflate(R.layout.voice_interaction_main, null);
+ Log.i(TAG, "Starting service.");
+ finish();
+ startService(intent);
}
}
diff --git a/tests/tests/assist/service/src/android/voiceinteraction/service/DisableContextActivity.java b/tests/tests/assist/service/src/android/voiceinteraction/service/DisableContextActivity.java
index 0db7ec1..52ba7ac 100644
--- a/tests/tests/assist/service/src/android/voiceinteraction/service/DisableContextActivity.java
+++ b/tests/tests/assist/service/src/android/voiceinteraction/service/DisableContextActivity.java
@@ -38,6 +38,7 @@
super.onStart();
Intent intent = new Intent();
intent.setComponent(new ComponentName(this, MainInteractionService.class));
+ finish();
ComponentName serviceName = startService(intent);
Log.i(TAG, "Started service: " + serviceName);
}
diff --git a/tests/tests/assist/service/src/android/voiceinteraction/service/MainInteractionService.java b/tests/tests/assist/service/src/android/voiceinteraction/service/MainInteractionService.java
index 56017ce..85bd6ea 100644
--- a/tests/tests/assist/service/src/android/voiceinteraction/service/MainInteractionService.java
+++ b/tests/tests/assist/service/src/android/voiceinteraction/service/MainInteractionService.java
@@ -17,7 +17,6 @@
package android.assist.service;
import android.content.ComponentName;
-import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.service.voice.VoiceInteractionService;
@@ -48,14 +47,9 @@
Log.wtf(TAG, "Can't start session because either intent is null or onReady() "
+ "has not been called yet. mIntent = " + mIntent + ", mReady = " + mReady);
} else {
- Log.i(TAG, "Yay! about to start session with TestApp");
+ Log.i(TAG, "Yay! about to start session");
if (isActiveService(this, new ComponentName(this, getClass()))) {
- Bundle args = new Bundle();
- Intent intent = new Intent();
- intent.setComponent(new ComponentName("android.assist.testapp",
- "android.assist.testapp.TestApp"));
- args.putParcelable("intent", intent);
- showSession(args, VoiceInteractionSession.SHOW_WITH_ASSIST |
+ showSession(new Bundle(), VoiceInteractionSession.SHOW_WITH_ASSIST |
VoiceInteractionSession.SHOW_WITH_SCREENSHOT);
} else {
Log.wtf(TAG, "**** Not starting MainInteractionService because" +
diff --git a/tests/tests/assist/service/src/android/voiceinteraction/service/MainInteractionSession.java b/tests/tests/assist/service/src/android/voiceinteraction/service/MainInteractionSession.java
index d19c6f8..9a835c2 100644
--- a/tests/tests/assist/service/src/android/voiceinteraction/service/MainInteractionSession.java
+++ b/tests/tests/assist/service/src/android/voiceinteraction/service/MainInteractionSession.java
@@ -16,26 +16,19 @@
package android.assist.service;
-import android.app.VoiceInteractor;
-import android.app.VoiceInteractor.Prompt;
import android.app.assist.AssistContent;
import android.app.assist.AssistStructure;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
-import android.os.AsyncTask;
import android.os.Bundle;
import android.service.voice.VoiceInteractionSession;
-import android.service.voice.VoiceInteractionSession.ConfirmationRequest;
-import android.service.voice.VoiceInteractionSession.PickOptionRequest;
import android.util.Log;
-import java.util.ArrayList;
-import java.util.List;
+import java.io.ByteArrayOutputStream;
import android.assist.common.Utils;
-import android.webkit.URLUtil;
public class MainInteractionSession extends VoiceInteractionSession {
static final String TAG = "MainInteractionSession";
@@ -44,6 +37,9 @@
Context mContext;
Bundle mAssistData = new Bundle();
+ private boolean hasReceivedAssistData = false;
+ private boolean hasReceivedScreenshot = false;
+
MainInteractionSession(Context context) {
super(context);
mContext = context;
@@ -64,8 +60,6 @@
public void onShow(Bundle args, int showFlags) {
// set some content view.
// TODO: check that the view takes up the whole screen.
- mStartIntent = args.getParcelable("intent");
- startVoiceActivity(mStartIntent); // remove
// check that interactor mode is for assist
if ((showFlags & SHOW_WITH_ASSIST) == 0) {
return;
@@ -73,32 +67,52 @@
super.onShow(args, showFlags);
}
-
@Override
public void onHandleAssist(/*@Nullable */Bundle data, /*@Nullable*/ AssistStructure structure,
/*@Nullable*/ AssistContent content) {
Log.i(TAG, "onHandleAssist");
- Log.i(TAG, String.format("Bundle: %s, Structure: %s, Content: %s", data, structure, content));
+ Log.i(TAG,
+ String.format("Bundle: %s, Structure: %s, Content: %s", data, structure, content));
super.onHandleAssist(data, structure, content);
// send to test to verify that this is accurate.
mAssistData.putParcelable(Utils.ASSIST_STRUCTURE_KEY, structure);
mAssistData.putParcelable(Utils.ASSIST_CONTENT_KEY, content);
- mAssistData.putBundle(Utils.ASSIST_BUNDLE, data);
- broadcastResults();
+ mAssistData.putBundle(Utils.ASSIST_BUNDLE_KEY, data);
+ hasReceivedAssistData = true;
+ maybeBroadcastResults();
}
@Override
public void onHandleScreenshot(/*@Nullable*/ Bitmap screenshot) {
+ Log.i(TAG, String.format("onHandleScreenshot - Screenshot: %s", screenshot));
super.onHandleScreenshot(screenshot);
- // add this to mAssistData?
+ ByteArrayOutputStream bs = new ByteArrayOutputStream();
+ if (screenshot != null) {
+ screenshot.compress(Bitmap.CompressFormat.PNG, 50, bs);
+ mAssistData.putByteArray(Utils.ASSIST_SCREENSHOT_KEY, bs.toByteArray());
+ } else {
+ mAssistData.putByteArray(Utils.ASSIST_SCREENSHOT_KEY, null);
+ }
+ hasReceivedScreenshot = true;
+ maybeBroadcastResults();
}
- private void broadcastResults() {
- Intent intent = new Intent(Utils.BROADCAST_ASSIST_DATA_INTENT);
- intent.putExtras(mAssistData);
- Log.i(TAG, "broadcasting: " + intent.toString() + ", Bundle = " + mAssistData.toString());
- mContext.sendBroadcast(intent);
+ private void maybeBroadcastResults() {
+ if (!hasReceivedAssistData) {
+ Log.i(TAG, "waiting for assist data before broadcasting results");
+ } else if (!hasReceivedScreenshot) {
+ Log.i(TAG, "waiting for screenshot before broadcasting results");
+ } else {
+ Intent intent = new Intent(Utils.BROADCAST_ASSIST_DATA_INTENT);
+ intent.putExtras(mAssistData);
+ Log.i(TAG,
+ "broadcasting: " + intent.toString() + ", Bundle = " + mAssistData.toString());
+ mContext.sendBroadcast(intent);
+
+ hasReceivedAssistData = false;
+ hasReceivedScreenshot = false;
+ }
}
class DoneReceiver extends BroadcastReceiver {
diff --git a/tests/tests/assist/src/android/assist/TestStartActivity.java b/tests/tests/assist/src/android/assist/TestStartActivity.java
index 06bf5aa..df9b534 100644
--- a/tests/tests/assist/src/android/assist/TestStartActivity.java
+++ b/tests/tests/assist/src/android/assist/TestStartActivity.java
@@ -21,12 +21,9 @@
import android.app.Activity;
import android.content.Intent;
import android.content.ComponentName;
-import android.content.Context;
import android.os.Bundle;
import android.util.Log;
-import android.assist.common.Utils;
-
public class TestStartActivity extends Activity {
static final String TAG = "TestStartActivity";
@@ -42,13 +39,20 @@
Log.i(TAG, " in onResume");
}
- public void startTest(String testCaseType) {
- Log.i(TAG, "Starting test activity for TestCaseType = " + testCaseType);
+ public void startTest(String testCaseName) {
+ Log.i(TAG, "Starting test activity for TestCaseType = " + testCaseName);
Intent intent = new Intent();
- intent.putExtra(Utils.TESTCASE_TYPE, testCaseType);
- intent.setAction("android.intent.action.START_TEST_" + testCaseType);
+ intent.putExtra(Utils.TESTCASE_TYPE, testCaseName);
+ intent.setAction("android.intent.action.START_TEST_" + testCaseName);
intent.setComponent(new ComponentName("android.assist.service",
- "android.assist." + Utils.getTestActivity(testCaseType)));
+ "android.assist." + Utils.getTestActivity(testCaseName)));
+ startActivity(intent);
+ }
+
+ public void start3pApp(String testCaseName) {
+ Intent intent = new Intent();
+ intent.setAction("android.intent.action.TEST_APP_" + testCaseName);
+ intent.setComponent(Utils.getTestAppComponent(testCaseName));
startActivity(intent);
}
diff --git a/tests/tests/assist/src/android/assist/cts/AssistStructureTest.java b/tests/tests/assist/src/android/assist/cts/AssistStructureTest.java
index 3c93c8a..97ab290 100644
--- a/tests/tests/assist/src/android/assist/cts/AssistStructureTest.java
+++ b/tests/tests/assist/src/android/assist/cts/AssistStructureTest.java
@@ -16,24 +16,10 @@
package android.assist.cts;
-import android.assist.TestStartActivity;
import android.assist.common.Utils;
-import android.app.assist.AssistContent;
-import android.app.assist.AssistStructure;
-import android.content.BroadcastReceiver;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.os.Bundle;
-import android.test.ActivityInstrumentationTestCase2;
-import android.util.Log;
+import android.provider.Settings;
-import java.lang.Exception;
-import java.lang.Override;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
/**
* Test that the AssistStructure returned is properly formatted.
@@ -42,7 +28,7 @@
public class AssistStructureTest extends AssistTestBase {
static final String TAG = "AssistStructureTest";
- private static final String TEST_CASE_TYPE = "ASSIST_STRUCTURE";
+ private static final String TEST_CASE_TYPE = Utils.ASSIST_STRUCTURE;
public AssistStructureTest() {
super();
@@ -52,38 +38,15 @@
protected void setUp() throws Exception {
super.setUp();
startTestActivity(TEST_CASE_TYPE);
- waitForBroadcast(Utils.TestCaseType.ASSIST_STRUCTURE);
+ waitForBroadcast();
}
public void testAssistStructure() throws Exception {
- // verify assist data contains what we want.
- // go through all things in the bundle, verify not null, verify contains what we want.
+ assertEquals("1", Settings.Secure.getString(
+ mContext.getContentResolver(), "assist_structure_enabled"));
- // TODO(awlee): verify that the context is not off by default.
- if (mAssistContent == null || mAssistBundle == null) {
- fail("Received null assistBundle or assistContent.");
- return;
- }
-
- if (mAssistStructure == null) {
- fail("Received null assistStructure");
- return;
- } else {
- verifyAssistStructure(new ComponentName("android.assist.service",
- "android.assist." + Utils.getTestActivity(TEST_CASE_TYPE)), false /*FLAG_SECURE set*/);
- }
- }
-
- private void verifyAssistStructure(ComponentName backgroundApp,
- boolean isSecureWindow) {
- // Check component name matches
- assertEquals(backgroundApp.flattenToString(),
- mAssistStructure.getActivityComponent().flattenToString());
-
- int numWindows = mAssistStructure.getWindowNodeCount();
- assertEquals(1, numWindows);
- for (int i = 0; i < numWindows; i++) {
- AssistStructure.ViewNode node = mAssistStructure.getWindowNodeAt(i).getRootViewNode();
- }
+ verifyAssistDataNullness(false, false, false, false);
+ verifyAssistStructure(Utils.getTestAppComponent(TEST_CASE_TYPE),
+ false /*FLAG_SECURE set*/);
}
}
\ No newline at end of file
diff --git a/tests/tests/assist/src/android/assist/cts/AssistTestBase.java b/tests/tests/assist/src/android/assist/cts/AssistTestBase.java
index a4f4cbc..e6d08cf 100644
--- a/tests/tests/assist/src/android/assist/cts/AssistTestBase.java
+++ b/tests/tests/assist/src/android/assist/cts/AssistTestBase.java
@@ -19,7 +19,6 @@
import android.assist.TestStartActivity;
import android.assist.common.Utils;
-import android.app.Activity;
import android.app.assist.AssistContent;
import android.app.assist.AssistStructure;
import android.content.BroadcastReceiver;
@@ -27,11 +26,14 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.res.XmlResourceParser;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
import android.os.Bundle;
+import android.provider.Settings;
import android.test.ActivityInstrumentationTestCase2;
import android.util.Log;
-import java.lang.Override;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -41,11 +43,11 @@
protected TestStartActivity mTestActivity;
protected AssistContent mAssistContent;
protected AssistStructure mAssistStructure;
+ protected Bitmap mScreenshot;
protected BroadcastReceiver mReceiver;
protected Bundle mAssistBundle;
protected Context mContext;
protected CountDownLatch mLatch;
- protected Utils.TestCaseType mTestCaseType;
private String mTestName;
public AssistTestBase() {
@@ -56,6 +58,11 @@
protected void setUp() throws Exception {
super.setUp();
mContext = getInstrumentation().getTargetContext();
+ assertEquals("1", Settings.Secure.getString(
+ mContext.getContentResolver(), "assist_structure_enabled"));
+ assertEquals("1", Settings.Secure.getString(
+ mContext.getContentResolver(), "assist_screenshot_enabled"));
+ logContextAndScreenshotSetting();
}
@Override
@@ -70,7 +77,7 @@
mTestName = testName;
intent.setAction("android.intent.action.TEST_START_ACTIVITY_" + testName);
intent.setComponent(new ComponentName(getInstrumentation().getContext(),
- TestStartActivity.class));
+ TestStartActivity.class));
setActivityIntent(intent);
mTestActivity = getActivity();
}
@@ -78,16 +85,16 @@
/**
* Called after startTestActivity
*/
- protected boolean waitForBroadcast(Utils.TestCaseType testCaseType) throws Exception {
- mTestCaseType = testCaseType;
+ protected boolean waitForBroadcast() throws Exception {
mLatch = new CountDownLatch(1);
if (mReceiver != null) {
mContext.unregisterReceiver(mReceiver);
}
mReceiver = new TestResultsReceiver();
mContext.registerReceiver(mReceiver,
- new IntentFilter(Utils.BROADCAST_ASSIST_DATA_INTENT));
+ new IntentFilter(Utils.BROADCAST_ASSIST_DATA_INTENT));
+ mTestActivity.start3pApp(mTestName);
mTestActivity.startTest(mTestName);
if (!mLatch.await(Utils.TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
fail("Failed to receive broadcast in " + Utils.TIMEOUT_MS + "msec");
@@ -96,18 +103,84 @@
return true;
}
+ /**
+ * Checks that the nullness of values are what we expect.
+ * @param isBundleNull True if assistBundle should be null.
+ * @param isStructureNull True if assistStructure should be null.
+ * @param isContentNull True if assistContent should be null.
+ * @param isScreenshotNull True if screenshot should be null.
+ */
+ protected void verifyAssistDataNullness(boolean isBundleNull, boolean isStructureNull,
+ boolean isContentNull, boolean isScreenshotNull) {
+
+ if ((mAssistContent == null) != isContentNull) {
+ fail(String.format("Should %s have been null - AssistContent: %s",
+ isContentNull? "":"not", mAssistContent));
+ }
+
+ if ((mAssistStructure == null) != isStructureNull) {
+ fail(String.format("Should %s have been null - AssistStructure: %s",
+ isStructureNull ? "" : "not", mAssistStructure));
+ }
+
+ if ((mAssistBundle == null) != isBundleNull) {
+ fail(String.format("Should %s have been null - AssistBundle: %s",
+ isBundleNull? "":"not", mAssistBundle));
+ }
+
+ if ((mScreenshot == null) != isScreenshotNull) {
+ fail(String.format("Should %s have been null - Screenshot: %s",
+ isScreenshotNull? "":"not", mScreenshot));
+ }
+ }
+
+ /**
+ * Traverses and compares the view heirarchy of the backgroundApp and the view we expect.
+ *
+ * @param backgroundApp ComponentName of app the assistant is invoked upon
+ * @param isSecureWindow Denotes whether the activity has FLAG_SECURE set
+ */
+ protected void verifyAssistStructure(ComponentName backgroundApp, boolean isSecureWindow) {
+ // Check component name matches
+ assertEquals(backgroundApp.flattenToString(),
+ mAssistStructure.getActivityComponent().flattenToString());
+
+ int numWindows = mAssistStructure.getWindowNodeCount();
+ assertEquals(1, numWindows);
+ for (int i = 0; i < numWindows; i++) {
+ AssistStructure.ViewNode node = mAssistStructure.getWindowNodeAt(i).getRootViewNode();
+ // TODO: Actually traverse the view heirarchy and verify it matches what we expect
+ // If isSecureWindow, will not have any children.
+ }
+ }
+
+ protected void logContextAndScreenshotSetting() {
+ Log.i(TAG, "Context is: " + Settings.Secure.getString(
+ mContext.getContentResolver(), "assist_structure_enabled"));
+ Log.i(TAG, "Screenshot is: " + Settings.Secure.getString(
+ mContext.getContentResolver(), "assist_screenshot_enabled"));
+ }
+
class TestResultsReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equalsIgnoreCase(Utils.BROADCAST_ASSIST_DATA_INTENT)) { // not necessary?
- Log.i(TAG, "received broadcast with results ");
+ Log.i(TAG, "Received broadcast with assist data.");
Bundle assistData = intent.getExtras();
+ AssistTestBase.this.mAssistBundle = assistData.getBundle(Utils.ASSIST_BUNDLE_KEY);
AssistTestBase.this.mAssistStructure = assistData.getParcelable(
Utils.ASSIST_STRUCTURE_KEY);
- AssistTestBase.this.mAssistBundle = assistData.getBundle(Utils.ASSIST_BUNDLE);
AssistTestBase.this.mAssistContent = assistData.getParcelable(
Utils.ASSIST_CONTENT_KEY);
+ byte[] bitmapArray = assistData.getByteArray(Utils.ASSIST_SCREENSHOT_KEY);
+ if (bitmapArray != null) {
+ AssistTestBase.this.mScreenshot = BitmapFactory.decodeByteArray(
+ bitmapArray, 0, bitmapArray.length);
+ } else {
+ AssistTestBase.this.mScreenshot = null;
+ }
+
if (mLatch != null) {
mLatch.countDown();
}
diff --git a/tests/tests/assist/src/android/assist/cts/DisableContextTest.java b/tests/tests/assist/src/android/assist/cts/DisableContextTest.java
index f3da32b..9407ec5 100644
--- a/tests/tests/assist/src/android/assist/cts/DisableContextTest.java
+++ b/tests/tests/assist/src/android/assist/cts/DisableContextTest.java
@@ -27,7 +27,9 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.cts.util.SystemUtil;
import android.os.Bundle;
+import android.provider.Settings;
import android.test.ActivityInstrumentationTestCase2;
import android.util.Log;
@@ -39,7 +41,7 @@
public class DisableContextTest extends AssistTestBase {
static final String TAG = "DisableContextTest";
- private static final String TEST_CASE_TYPE = "DISABLE_CONTEXT";
+ private static final String TEST_CASE_TYPE = Utils.DISABLE_CONTEXT;
public DisableContextTest() {
super();
@@ -48,43 +50,49 @@
@Override
public void setUp() throws Exception {
super.setUp();
- // need to set action/component/activityintent for the test activity?
+ SystemUtil.runShellCommand(getInstrumentation(),
+ "settings put secure assist_structure_enabled 0");
+ SystemUtil.runShellCommand(getInstrumentation(),
+ "settings put secure assist_screenshot_enabled 0");
+ logContextAndScreenshotSetting();
startTestActivity(TEST_CASE_TYPE);
- waitForBroadcast(Utils.TestCaseType.DISABLE_CONTEXT);
+ waitForBroadcast();
}
- public void testContextOnAndOff() throws Exception {
- // filler
-
-
- // verify assist data contains what we want.
- // go through all things in the bundle, verify not null, verify contains what we want.
-
- // TODO(awlee): verify that the context is not off by default.
- if (mAssistContent == null || mAssistBundle == null) {
- fail("Received null assistBundle or assistContent.");
- return;
- }
-
- if (mAssistStructure == null) {
- fail("Received null assistStructure");
- return;
- } else {
- verifyAssistStructure(new ComponentName("android.assist.service",
- "android.assist." + Utils.getTestActivity(TEST_CASE_TYPE)), false /*FLAG_SECURE set*/);
- }
+ @Override
+ public void tearDown() throws Exception {
+ SystemUtil.runShellCommand(getInstrumentation(),
+ "settings put secure assist_structure_enabled 1");
+ SystemUtil.runShellCommand(getInstrumentation(),
+ "settings put secure assist_screenshot_enabled 1");
+ logContextAndScreenshotSetting();
+ super.tearDown();
}
- private void verifyAssistStructure(ComponentName backgroundApp,
- boolean isSecureWindow) {
- // Check component name matches
- assertEquals(backgroundApp.flattenToString(),
- mAssistStructure.getActivityComponent().flattenToString());
+ public void testContextAndScreenshotOff() throws Exception {
+ // Both settings off
+ verifyAssistDataNullness(true, true, true, true);
- int numWindows = mAssistStructure.getWindowNodeCount();
- assertEquals(1, numWindows);
- for (int i = 0; i < numWindows; i++) {
- AssistStructure.ViewNode node = mAssistStructure.getWindowNodeAt(i).getRootViewNode();
- }
+ // Screenshot off, context on
+ SystemUtil.runShellCommand(getInstrumentation(),
+ "settings put secure assist_structure_enabled 1");
+ SystemUtil.runShellCommand(getInstrumentation(),
+ "settings put secure assist_screenshot_enabled 0");
+ waitForBroadcast();
+
+ logContextAndScreenshotSetting();
+
+ verifyAssistDataNullness(false, false, false, true);
+
+ // Context off, screenshot on
+ SystemUtil.runShellCommand(getInstrumentation(),
+ "settings put secure assist_structure_enabled 0");
+ SystemUtil.runShellCommand(getInstrumentation(),
+ "settings put secure assist_screenshot_enabled 1");
+ waitForBroadcast();
+
+ logContextAndScreenshotSetting();
+
+ verifyAssistDataNullness(true, true, true, false);
}
}
\ No newline at end of file
diff --git a/tests/tests/assist/src/android/assist/cts/FlagSecureTest.java b/tests/tests/assist/src/android/assist/cts/FlagSecureTest.java
new file mode 100644
index 0000000..0e79d9d
--- /dev/null
+++ b/tests/tests/assist/src/android/assist/cts/FlagSecureTest.java
@@ -0,0 +1,55 @@
+/*
+ * 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 android.assist.cts;
+
+import android.assist.common.Utils;
+
+import java.util.concurrent.CountDownLatch;
+
+/**
+ * Test we receive proper assist data (root assistStructure with no children) when the assistant is
+ * invoked on an app with FLAG_SECURE set.
+ */
+public class FlagSecureTest extends AssistTestBase {
+
+ static final String TAG = "DisableContextTest";
+
+ private static final String TEST_CASE_TYPE = Utils.FLAG_SECURE;
+
+ public FlagSecureTest() {
+ super();
+ }
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ startTestActivity(TEST_CASE_TYPE);
+ waitForBroadcast();
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ public void testSecureActivity() throws Exception {
+ verifyAssistDataNullness(false, false, false, true);
+
+ // verify that we have only the root window and not its children.
+ verifyAssistStructure(Utils.getTestAppComponent(TEST_CASE_TYPE), true);
+ }
+}
\ No newline at end of file
diff --git a/tests/tests/assist/testapp/AndroidManifest.xml b/tests/tests/assist/testapp/AndroidManifest.xml
index 5b16ed7..371ae7b 100644
--- a/tests/tests/assist/testapp/AndroidManifest.xml
+++ b/tests/tests/assist/testapp/AndroidManifest.xml
@@ -19,16 +19,25 @@
package="android.assist.testapp">
<application>
- <uses-library android:name="android.test.runner" />
+ <uses-library android:name="android.test.runner" />
- <activity android:name="TestApp"
+ <activity android:name="TestApp"
android:label="Assist Test App"
android:theme="@android:style/Theme.Material.Light">
<intent-filter>
- <action android:name="android.intent.action.TEST_APP" />
+ <action android:name="android.intent.action.TEST_APP_ASSIST_STRUCTURE" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.VOICE" />
</intent-filter>
- </activity>
+ </activity>
+ <activity android:name="SecureActivity"
+ android:label="Secure Test App"
+ android:theme="@android:style/Theme.Material.Light">
+ <intent-filter>
+ <action android:name="android.intent.action.TEST_APP_FLAG_SECURE" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.VOICE" />
+ </intent-filter>
+ </activity>
</application>
</manifest>
diff --git a/tests/tests/assist/service/res/layout/voice_interaction_main.xml b/tests/tests/assist/testapp/res/layout/secure_app.xml
similarity index 100%
rename from tests/tests/assist/service/res/layout/voice_interaction_main.xml
rename to tests/tests/assist/testapp/res/layout/secure_app.xml
diff --git a/tests/tests/assist/service/res/layout/voice_interaction_main.xml b/tests/tests/assist/testapp/res/layout/test_app.xml
similarity index 100%
copy from tests/tests/assist/service/res/layout/voice_interaction_main.xml
copy to tests/tests/assist/testapp/res/layout/test_app.xml
diff --git a/tests/tests/assist/service/res/values/strings.xml b/tests/tests/assist/testapp/res/values/strings.xml
similarity index 100%
rename from tests/tests/assist/service/res/values/strings.xml
rename to tests/tests/assist/testapp/res/values/strings.xml
diff --git a/tests/tests/assist/testapp/src/android/voiceinteraction/testapp/SecureActivity.java b/tests/tests/assist/testapp/src/android/voiceinteraction/testapp/SecureActivity.java
new file mode 100644
index 0000000..83f7549
--- /dev/null
+++ b/tests/tests/assist/testapp/src/android/voiceinteraction/testapp/SecureActivity.java
@@ -0,0 +1,36 @@
+/*
+ * 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 android.assist.testapp;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.util.Log;
+
+import android.view.WindowManager;
+
+public class SecureActivity extends Activity {
+ static final String TAG = "SecureActivity";
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ Log.i(TAG, "SecureActivity created");
+ setContentView(R.layout.secure_app);
+ getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE,
+ WindowManager.LayoutParams.FLAG_SECURE);
+ }
+}
\ No newline at end of file
diff --git a/tests/tests/assist/testapp/src/android/voiceinteraction/testapp/TestApp.java b/tests/tests/assist/testapp/src/android/voiceinteraction/testapp/TestApp.java
index 9083cda..85a9342 100644
--- a/tests/tests/assist/testapp/src/android/voiceinteraction/testapp/TestApp.java
+++ b/tests/tests/assist/testapp/src/android/voiceinteraction/testapp/TestApp.java
@@ -17,26 +17,24 @@
package android.assist.testapp;
import android.app.Activity;
-import android.app.VoiceInteractor;
-import android.app.VoiceInteractor.AbortVoiceRequest;
-import android.app.VoiceInteractor.CommandRequest;
-import android.app.VoiceInteractor.CompleteVoiceRequest;
-import android.app.VoiceInteractor.ConfirmationRequest;
-import android.app.VoiceInteractor.PickOptionRequest;
-import android.app.VoiceInteractor.PickOptionRequest.Option;
-import android.app.VoiceInteractor.Prompt;
-import android.content.BroadcastReceiver;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
import android.os.Bundle;
-import android.service.voice.VoiceInteractionService;
import android.util.Log;
-import java.util.ArrayList;
-
-import android.assist.common.Utils;
-
public class TestApp extends Activity {
+ static final String TAG = "TestApp";
-}
+ Bundle mTestinfo = new Bundle();
+ Bundle mTotalInfo = new Bundle();
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ Log.i(TAG, "TestApp created");
+ getLayoutInflater().inflate(R.layout.test_app, null);
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ }
+}
\ No newline at end of file
diff --git a/tests/tests/hardware/Android.mk b/tests/tests/hardware/Android.mk
index 9523d87..9c26d8a 100644
--- a/tests/tests/hardware/Android.mk
+++ b/tests/tests/hardware/Android.mk
@@ -34,7 +34,7 @@
src/android/hardware/cts/SensorIntegrationTests.java \
src/android/hardware/cts/SensorBatchingTests.java \
src/android/hardware/cts/SensorTest.java \
- src/android/hardware/cts/SensorManagerStaticTest.java \
+ src/android/hardware/cts/SensorManagerStaticTest.java
LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil
@@ -57,4 +57,4 @@
LOCAL_JAVA_LIBRARIES := android.test.runner
-include $(BUILD_CTS_PACKAGE)
\ No newline at end of file
+include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/hardware/src/android/hardware/cts/SensorParameterRangeTest.java b/tests/tests/hardware/src/android/hardware/cts/SensorParameterRangeTest.java
new file mode 100644
index 0000000..4750b09
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/SensorParameterRangeTest.java
@@ -0,0 +1,115 @@
+/*
+ * 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 android.hardware.cts;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.hardware.Sensor;
+import android.hardware.SensorManager;
+import android.hardware.cts.helpers.SensorCtsHelper;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Test min-max frequency, max range parameters for sensors.
+ *
+ * <p>To execute these test cases, the following command can be used:</p>
+ * <pre>
+ * adb shell am instrument -e class android.hardware.cts.SensorParameterRangeTest \
+ * -w com.android.cts.hardware/android.test.AndroidJUnitRunner
+ * </pre>
+ */
+public class SensorParameterRangeTest extends SensorTestCase {
+
+ private static final double ACCELEROMETER_MAX_RANGE = 8 * 9.81; // 8G
+ private static final int ACCELEROMETER_MIN_FREQUENCY = 5;
+ private static final int ACCELEROMETER_MAX_FREQUENCY = 200;
+
+ private static final double GYRO_MAX_RANGE = 1000/57.295; // 1000 degrees per sec.
+ private static final int GYRO_MIN_FREQUENCY = 5;
+ private static final int GYRO_MAX_FREQUENCY = 200;
+
+ private static final int MAGNETOMETER_MAX_RANGE = 900; // micro telsa
+ private static final int MAGNETOMETER_MIN_FREQUENCY = 5;
+ private static final int MAGNETOMETER_MAX_FREQUENCY = 50;
+
+ private static final int PRESSURE_MAX_RANGE = 1100; // hecto-pascal
+ private static final int PRESSURE_MIN_FREQUENCY = 1;
+ private static final int PRESSURE_MAX_FREQUENCY = 10;
+
+ private boolean mHasHifiSensors;
+ private SensorManager mSensorManager;
+
+ @Override
+ public void setUp() {
+ mSensorManager = (SensorManager) getContext().getSystemService(Context.SENSOR_SERVICE);
+ mHasHifiSensors = getContext().getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_HIFI_SENSORS);
+ }
+
+ public void testAccelerometerRange() {
+ checkSensorRangeAndFrequency(
+ mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
+ ACCELEROMETER_MAX_RANGE,
+ ACCELEROMETER_MIN_FREQUENCY,
+ ACCELEROMETER_MAX_FREQUENCY);
+ }
+
+ public void testGyroscopeRange() {
+ checkSensorRangeAndFrequency(
+ mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE),
+ GYRO_MAX_RANGE,
+ GYRO_MIN_FREQUENCY,
+ GYRO_MAX_FREQUENCY);
+ }
+
+ public void testMagnetometerRange() {
+ checkSensorRangeAndFrequency(
+ mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD),
+ MAGNETOMETER_MAX_RANGE,
+ MAGNETOMETER_MIN_FREQUENCY,
+ MAGNETOMETER_MAX_FREQUENCY);
+ }
+
+ public void testPressureRange() {
+ checkSensorRangeAndFrequency(
+ mSensorManager.getDefaultSensor(Sensor.TYPE_PRESSURE),
+ PRESSURE_MAX_RANGE,
+ PRESSURE_MIN_FREQUENCY,
+ PRESSURE_MAX_FREQUENCY);
+ }
+
+ private void checkSensorRangeAndFrequency(
+ Sensor sensor, double maxRange, int minFrequency, int maxFrequency) {
+ if (!mHasHifiSensors) return;
+ assertTrue(String.format("%s Range actual=%.2f expected=%.2f %s",
+ sensor.getName(), sensor.getMaximumRange(), maxRange,
+ SensorCtsHelper.getUnitsForSensor(sensor)),
+ sensor.getMaximumRange() >= maxRange);
+ double actualMinFrequency = SensorCtsHelper.getFrequency(sensor.getMaxDelay(),
+ TimeUnit.MICROSECONDS);
+ assertTrue(String.format("%s Min Frequency actual=%.2f expected=%dHz",
+ sensor.getName(), actualMinFrequency, minFrequency), actualMinFrequency <=
+ minFrequency);
+
+ double actualMaxFrequency = SensorCtsHelper.getFrequency(sensor.getMinDelay(),
+ TimeUnit.MICROSECONDS);
+ assertTrue(String.format("%s Max Frequency actual=%.2f expected=%dHz",
+ sensor.getName(), actualMaxFrequency, maxFrequency), actualMaxFrequency >=
+ maxFrequency);
+ }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/SensorSupportTest.java b/tests/tests/hardware/src/android/hardware/cts/SensorSupportTest.java
new file mode 100644
index 0000000..2f25c8d
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/SensorSupportTest.java
@@ -0,0 +1,101 @@
+/*
+ * 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 android.hardware.cts;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.hardware.Sensor;
+import android.hardware.SensorManager;
+import android.test.AndroidTestCase;
+
+/**
+ * Checks if Hifi sensors are supported. When supported, checks individual support for
+ * Accelerometer, Gyroscope, Gyroscope_uncal, GeoMagneticField, MagneticField_uncal
+ * Pressure, RotationVector, SignificantMotion, StepDetector, StepCounter, TiltDetector.
+ *
+ * <p>To execute these test cases, the following command can be used:</p>
+ * <pre>
+ * adb shell am instrument -e class android.hardware.cts.SensorSupportTest \
+ * -w com.android.cts.hardware/android.test.AndroidJUnitRunner
+ * </pre>
+ */
+public class SensorSupportTest extends AndroidTestCase {
+ private SensorManager mSensorManager;
+ private boolean mAreHifiSensorsSupported;
+
+ @Override
+ public void setUp() {
+ // Tests will only run if HIFI_SENSORS are supported.
+ mAreHifiSensorsSupported = getContext().getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_HIFI_SENSORS);
+ if (mAreHifiSensorsSupported) {
+ mSensorManager =
+ (SensorManager) getContext().getSystemService(Context.SENSOR_SERVICE);
+ }
+ }
+
+ public void testSupportsAccelerometer() {
+ checkSupportsSensor(Sensor.TYPE_ACCELEROMETER);
+ }
+
+ public void testSupportsGyroscope() {
+ checkSupportsSensor(Sensor.TYPE_GYROSCOPE);
+ }
+
+ public void testSupportsGyroscopeUncalibrated() {
+ checkSupportsSensor(Sensor.TYPE_GYROSCOPE_UNCALIBRATED);
+ }
+
+ public void testSupportsGeoMagneticField() {
+ checkSupportsSensor(Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR);
+ }
+
+ public void testSupportsMagneticFieldUncalibrated() {
+ checkSupportsSensor(Sensor.TYPE_MAGNETIC_FIELD_UNCALIBRATED);
+ }
+
+ public void testSupportsPressure() {
+ checkSupportsSensor(Sensor.TYPE_PRESSURE);
+ }
+
+ public void testSupportsRotationVector() {
+ checkSupportsSensor(Sensor.TYPE_ROTATION_VECTOR);
+ }
+
+ public void testSupportsSignificantMotion() {
+ checkSupportsSensor(Sensor.TYPE_SIGNIFICANT_MOTION);
+ }
+
+ public void testSupportsStepDetector() {
+ checkSupportsSensor(Sensor.TYPE_STEP_DETECTOR);
+ }
+
+ public void testSupportsStepCounter() {
+ checkSupportsSensor(Sensor.TYPE_STEP_COUNTER);
+ }
+
+ public void testSupportsTiltDetector() {
+ final int TYPE_TILT_DETECTOR = 22;
+ checkSupportsSensor(TYPE_TILT_DETECTOR);
+ }
+
+ private void checkSupportsSensor(int sensorType) {
+ if (mAreHifiSensorsSupported) {
+ assertTrue(mSensorManager.getDefaultSensor(sensorType) != null);
+ }
+ }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/SensorCtsHelper.java b/tests/tests/hardware/src/android/hardware/cts/helpers/SensorCtsHelper.java
index 490e965..55465ac 100644
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/SensorCtsHelper.java
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/SensorCtsHelper.java
@@ -15,6 +15,7 @@
*/
package android.hardware.cts.helpers;
+import android.hardware.Sensor;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
@@ -259,4 +260,20 @@
throw new IllegalStateException("Collection cannot be null or empty");
}
}
+
+ public static String getUnitsForSensor(Sensor sensor) {
+ switch(sensor.getType()) {
+ case Sensor.TYPE_ACCELEROMETER:
+ return "m/s^2";
+ case Sensor.TYPE_MAGNETIC_FIELD:
+ case Sensor.TYPE_MAGNETIC_FIELD_UNCALIBRATED:
+ return "uT";
+ case Sensor.TYPE_GYROSCOPE:
+ case Sensor.TYPE_GYROSCOPE_UNCALIBRATED:
+ return "radians/sec";
+ case Sensor.TYPE_PRESSURE:
+ return "hPa";
+ };
+ return "";
+ }
}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/EventGapVerificationTest.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/EventGapVerificationTest.java
index 6f17e7b..687e63b 100644
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/EventGapVerificationTest.java
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/EventGapVerificationTest.java
@@ -62,7 +62,7 @@
public void testVerify_missing_events() {
// Timestamps in ns, expected in us
long[] timestamps = {1000000, 2000000, 3000000, 5000000, 6000000};
- runVerification(1000, timestamps, false, new int[]{3});
+ runVerification(1000, timestamps, true, new int[]{3});
}
private void runVerification(int expected, long[] timestamps, boolean pass,
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/JitterVerification.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/JitterVerification.java
index 6633903..e5a5053 100644
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/JitterVerification.java
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/JitterVerification.java
@@ -18,6 +18,10 @@
import junit.framework.Assert;
+import android.content.Context;
+import android.content.pm.PackageManager;
+
+import android.util.Log;
import android.hardware.Sensor;
import android.hardware.cts.helpers.SensorCtsHelper;
import android.hardware.cts.helpers.SensorStats;
@@ -39,6 +43,8 @@
// sensorType: threshold (% of expected period)
private static final SparseIntArray DEFAULTS = new SparseIntArray(12);
+ // Max allowed jitter (in percentage).
+ private static final int THRESHOLD_PERCENT_FOR_HIFI_SENSORS = 1;
static {
// Use a method so that the @deprecation warning can be set for that method only
setDefaults();
@@ -68,6 +74,11 @@
if (threshold == -1) {
return null;
}
+ boolean hasHifiSensors = environment.getContext().getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_HIFI_SENSORS);
+ if (hasHifiSensors) {
+ threshold = THRESHOLD_PERCENT_FOR_HIFI_SENSORS;
+ }
return new JitterVerification(threshold);
}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/StandardDeviationVerification.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/StandardDeviationVerification.java
index f7c2c53..20dd2d2 100644
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/StandardDeviationVerification.java
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/StandardDeviationVerification.java
@@ -18,10 +18,13 @@
import junit.framework.Assert;
+import android.content.Context;
+import android.content.pm.PackageManager;
import android.hardware.Sensor;
import android.hardware.cts.helpers.SensorStats;
import android.hardware.cts.helpers.TestSensorEnvironment;
import android.hardware.cts.helpers.TestSensorEvent;
+import android.util.Log;
import java.util.HashMap;
import java.util.Map;
@@ -66,7 +69,21 @@
if (!DEFAULTS.containsKey(sensorType)) {
return null;
}
+ boolean hasHifiSensors = environment.getContext().getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_HIFI_SENSORS);
+ if (hasHifiSensors) {
+ // Max accelerometer deviation: 400uG/√Hz
+ DEFAULTS.put(Sensor.TYPE_ACCELEROMETER, new float[]{0.004f, 0.004f, 0.004f});
+ // Max gyro deviation: 0.014°/s/√Hz
+ float deviationInRadians = (float) (0.014f * (Math.PI / 180));
+ DEFAULTS.put(Sensor.TYPE_GYROSCOPE,
+ new float[]{deviationInRadians,deviationInRadians, deviationInRadians});
+ // Max magnetometer deviation: 0.1uT/√Hz
+ DEFAULTS.put(Sensor.TYPE_MAGNETIC_FIELD, new float[]{0.1f, 0.1f, 0.1f});
+ // Max pressure deviation: 2Pa/√Hz
+ DEFAULTS.put(Sensor.TYPE_PRESSURE, new float[]{2.0f, 2.0f, 2.0f});
+ }
return new StandardDeviationVerification(DEFAULTS.get(sensorType));
}
@@ -107,9 +124,9 @@
if (stdDevs[i] > mThreshold[i]) {
failed = true;
}
- stddevSb.append(String.format("%.2f", stdDevs[i]));
+ stddevSb.append(String.format("%.3f", stdDevs[i]));
if (i != stdDevs.length - 1) stddevSb.append(", ");
- expectedSb.append(String.format("<%.2f", mThreshold[i]));
+ expectedSb.append(String.format("<%.3f", mThreshold[i]));
if (i != stdDevs.length - 1) expectedSb.append(", ");
}
if (stdDevs.length > 1) {
diff --git a/tests/tests/media/src/android/media/cts/AudioManagerTest.java b/tests/tests/media/src/android/media/cts/AudioManagerTest.java
index ded0539..a0163e5 100644
--- a/tests/tests/media/src/android/media/cts/AudioManagerTest.java
+++ b/tests/tests/media/src/android/media/cts/AudioManagerTest.java
@@ -45,23 +45,27 @@
import android.os.Vibrator;
import android.provider.Settings;
import android.provider.Settings.System;
-import android.test.AndroidTestCase;
+import android.test.InstrumentationTestCase;
import android.view.SoundEffectConstants;
import java.util.TreeMap;
-public class AudioManagerTest extends AndroidTestCase {
+public class AudioManagerTest extends InstrumentationTestCase {
private final static int MP3_TO_PLAY = R.raw.testmp3;
private final static long TIME_TO_PLAY = 2000;
+ private final static String APPOPS_OP_STR = "android:write_settings";
private AudioManager mAudioManager;
private boolean mHasVibrator;
private boolean mUseFixedVolume;
private boolean mIsTelevision;
+ private Context mContext;
@Override
protected void setUp() throws Exception {
super.setUp();
+ mContext = getInstrumentation().getContext();
+ Utils.enableAppOps(mContext.getPackageName(), APPOPS_OP_STR, getInstrumentation());
mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
Vibrator vibrator = (Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE);
mHasVibrator = (vibrator != null) && vibrator.hasVibrator();
diff --git a/tests/tests/media/src/android/media/cts/EnumDevicesTest.java b/tests/tests/media/src/android/media/cts/EnumDevicesTest.java
index f513709..94af087 100644
--- a/tests/tests/media/src/android/media/cts/EnumDevicesTest.java
+++ b/tests/tests/media/src/android/media/cts/EnumDevicesTest.java
@@ -115,29 +115,31 @@
// Sample Rates
int[] sampleRates = deviceInfo.getSampleRates();
assertNotNull(sampleRates);
- // "analog" devices won't list any sample rates
+ // Note: an empty array indicates that the device supports arbitrary sample rates.
// Channel Masks
int[] channelMasks = deviceInfo.getChannelMasks();
assertNotNull(channelMasks);
- // "analog" devices won't list any channel masks
+ // Note: an empty array indicates that the device supports arbitrary channel masks.
// Channel Index Masks
int[] indexMasks = deviceInfo.getChannelIndexMasks();
- assertNotNull(channelMasks);
+ assertNotNull(indexMasks);
+ // Note: an empty array indicates that the device supports arbitrary channel index
+ // masks.
// Channel Counts
int[] channelCounts = deviceInfo.getChannelCounts();
assertNotNull(channelCounts);
- // "analog" devices won't list any channel Counts
+ // Note: an empty array indicates that the device supports arbitrary channel counts.
// Encodings
int[] encodings = deviceInfo.getEncodings();
assertNotNull(encodings);
- // "analog" devices won't list any encodings
+ // Note: an empty array indicates that the device supports arbitrary encodings.
int type = deviceInfo.getType();
- assert(type > AudioDeviceInfo.TYPE_UNKNOWN);
+ assertTrue(type != AudioDeviceInfo.TYPE_UNKNOWN);
}
}
@@ -167,7 +169,7 @@
}
return myLooper;
}
-
+
public void test_deviceCallback() {
// null callback?
mAudioManager.registerAudioDeviceCallback(null,null);
@@ -187,7 +189,7 @@
mAudioManager.unregisterAudioDeviceCallback(callback);
Looper myLooper = prepareIfNeededLooper();
-
+
mAudioManager.registerAudioDeviceCallback(callback, new Handler());
// unregister null callback
mAudioManager.unregisterAudioDeviceCallback(null);
diff --git a/tests/tests/media/src/android/media/cts/MediaCodecCapabilitiesTest.java b/tests/tests/media/src/android/media/cts/MediaCodecCapabilitiesTest.java
index b3fcce1..813af0f2 100644
--- a/tests/tests/media/src/android/media/cts/MediaCodecCapabilitiesTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaCodecCapabilitiesTest.java
@@ -19,6 +19,7 @@
import android.cts.util.MediaUtils;
import android.media.MediaCodec;
import android.media.MediaCodecInfo;
+import android.media.MediaCodecInfo.AudioCapabilities;
import android.media.MediaCodecInfo.CodecCapabilities;
import android.media.MediaCodecInfo.CodecProfileLevel;
import android.media.MediaCodecInfo.VideoCapabilities;
@@ -530,24 +531,35 @@
}
}
- private static MediaFormat createMinFormat(String mime, VideoCapabilities vcaps, int color) {
- int minWidth = vcaps.getSupportedWidths().getLower();
- int minHeight = vcaps.getSupportedHeightsFor(minWidth).getLower();
- int minBitrate = vcaps.getBitrateRange().getLower();
+ private static MediaFormat createMinFormat(String mime, CodecCapabilities caps) {
+ MediaFormat format;
+ if (caps.getVideoCapabilities() != null) {
+ VideoCapabilities vcaps = caps.getVideoCapabilities();
+ int minWidth = vcaps.getSupportedWidths().getLower();
+ int minHeight = vcaps.getSupportedHeightsFor(minWidth).getLower();
+ int minBitrate = vcaps.getBitrateRange().getLower();
+ format = MediaFormat.createVideoFormat(mime, minWidth, minHeight);
+ format.setInteger(MediaFormat.KEY_COLOR_FORMAT, caps.colorFormats[0]);
+ format.setInteger(MediaFormat.KEY_BIT_RATE, minBitrate);
+ format.setInteger(MediaFormat.KEY_FRAME_RATE, 10);
+ format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 10);
+ } else {
+ AudioCapabilities acaps = caps.getAudioCapabilities();
+ int minSampleRate = acaps.getSupportedSampleRateRanges()[0].getLower();
+ int minChannelCount = 1;
+ int minBitrate = acaps.getBitrateRange().getLower();
+ format = MediaFormat.createAudioFormat(mime, minSampleRate, minChannelCount);
+ format.setInteger(MediaFormat.KEY_BIT_RATE, minBitrate);
+ }
- MediaFormat format = MediaFormat.createVideoFormat(mime, minWidth, minHeight);
- format.setInteger(MediaFormat.KEY_COLOR_FORMAT, color);
- format.setInteger(MediaFormat.KEY_BIT_RATE, minBitrate);
- format.setInteger(MediaFormat.KEY_FRAME_RATE, 10);
- format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 10);
return format;
}
private static int getActualMax(
boolean isEncoder, String name, String mime, CodecCapabilities caps, int max) {
int flag = isEncoder ? MediaCodec.CONFIGURE_FLAG_ENCODE : 0;
- MediaFormat format =
- createMinFormat(mime, caps.getVideoCapabilities(), caps.colorFormats[0]);
+ MediaFormat format = createMinFormat(mime, caps);
+ Log.d(TAG, "Test format " + format);
Vector<MediaCodec> codecs = new Vector<MediaCodec>();
MediaCodec codec = null;
for (int i = 0; i < max; ++i) {
@@ -588,14 +600,6 @@
return actualMax;
}
- private static boolean shouldTestActual(CodecCapabilities caps) {
- if (caps.getVideoCapabilities() == null) {
- // TODO: test audio codecs.
- return false;
- }
- return true;
- }
-
public void testGetMaxSupportedInstances() {
final int MAX_INSTANCES = 32;
StringBuilder xmlOverrides = new StringBuilder();
@@ -612,21 +616,19 @@
Log.d(TAG, "getMaxSupportedInstances returns " + max);
assertTrue(max > 0);
- if (shouldTestActual(caps)) {
- int actualMax = getActualMax(
- info.isEncoder(), info.getName(), types[j], caps, MAX_INSTANCES);
- Log.d(TAG, "actualMax " + actualMax + " vs reported max " + max);
- if (actualMax < (int)(max * 0.9) || actualMax > (int) Math.ceil(max * 1.1)) {
- String codec = "<MediaCodec name=\"" + info.getName() +
- "\" type=\"" + types[j] + "\" >";
- String limit = " <Limit name=\"concurrent-instances\" max=\"" +
- actualMax + "\" />";
- xmlOverrides.append(codec);
- xmlOverrides.append("\n");
- xmlOverrides.append(limit);
- xmlOverrides.append("\n");
- xmlOverrides.append("</MediaCodec>\n");
- }
+ int actualMax = getActualMax(
+ info.isEncoder(), info.getName(), types[j], caps, MAX_INSTANCES);
+ Log.d(TAG, "actualMax " + actualMax + " vs reported max " + max);
+ if (actualMax < (int)(max * 0.9) || actualMax > (int) Math.ceil(max * 1.1)) {
+ String codec = "<MediaCodec name=\"" + info.getName() +
+ "\" type=\"" + types[j] + "\" >";
+ String limit = " <Limit name=\"concurrent-instances\" max=\"" +
+ actualMax + "\" />";
+ xmlOverrides.append(codec);
+ xmlOverrides.append("\n");
+ xmlOverrides.append(limit);
+ xmlOverrides.append("\n");
+ xmlOverrides.append("</MediaCodec>\n");
}
}
}
diff --git a/tests/tests/media/src/android/media/cts/MidiSoloTest.java b/tests/tests/media/src/android/media/cts/MidiSoloTest.java
index 4c1a5e8..d198ee8 100644
--- a/tests/tests/media/src/android/media/cts/MidiSoloTest.java
+++ b/tests/tests/media/src/android/media/cts/MidiSoloTest.java
@@ -97,9 +97,7 @@
MidiManager.DeviceCallback callback = new MidiManager.DeviceCallback();
// These should not crash.
- midiManager.unregisterDeviceCallback(null);
midiManager.unregisterDeviceCallback(callback);
- midiManager.registerDeviceCallback(null, null);
midiManager.registerDeviceCallback(callback, null);
midiManager.unregisterDeviceCallback(callback);
midiManager.registerDeviceCallback(callback, new Handler(Looper.getMainLooper()));
@@ -107,9 +105,6 @@
midiManager.unregisterDeviceCallback(callback);
midiManager.unregisterDeviceCallback(callback);
midiManager.unregisterDeviceCallback(callback);
- midiManager.registerDeviceCallback(null, new Handler(Looper.getMainLooper()));
- midiManager.unregisterDeviceCallback(callback);
- midiManager.unregisterDeviceCallback(null);
}
public void testMidiReceiver() throws Exception {
diff --git a/tests/tests/media/src/android/media/cts/RingtoneManagerTest.java b/tests/tests/media/src/android/media/cts/RingtoneManagerTest.java
index bf47a27..4693036 100644
--- a/tests/tests/media/src/android/media/cts/RingtoneManagerTest.java
+++ b/tests/tests/media/src/android/media/cts/RingtoneManagerTest.java
@@ -55,6 +55,7 @@
mActivity = getActivity();
mInstrumentation = getInstrumentation();
mContext = mInstrumentation.getContext();
+ Utils.enableAppOps(mContext.getPackageName(), "android:write_settings", mInstrumentation);
mRingtoneManager = new RingtoneManager(mActivity);
mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
// backup ringer settings
@@ -74,6 +75,7 @@
}
RingtoneManager.setActualDefaultRingtoneUri(mContext, RingtoneManager.TYPE_RINGTONE,
mDefaultUri);
+ Utils.disableAppOps(mContext.getPackageName(), "android:write_settings", mInstrumentation);
super.tearDown();
}
diff --git a/tests/tests/media/src/android/media/cts/Utils.java b/tests/tests/media/src/android/media/cts/Utils.java
new file mode 100644
index 0000000..bb9cf78
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/Utils.java
@@ -0,0 +1,70 @@
+/*
+ * 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 android.media.cts;
+
+import android.app.Instrumentation;
+import android.app.UiAutomation;
+import android.os.ParcelFileDescriptor;
+
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.util.Scanner;
+
+public class Utils {
+ public static void enableAppOps(String packageName, String operation,
+ Instrumentation instrumentation) {
+ setAppOps(packageName, operation, instrumentation, true);
+ }
+
+ public static void disableAppOps(String packageName, String operation,
+ Instrumentation instrumentation) {
+ setAppOps(packageName, operation, instrumentation, false);
+ }
+
+ public static String convertStreamToString(InputStream is) {
+ try (Scanner scanner = new Scanner(is).useDelimiter("\\A")) {
+ return scanner.hasNext() ? scanner.next() : "";
+ }
+ }
+
+ private static void setAppOps(String packageName, String operation,
+ Instrumentation instrumentation, boolean enable) {
+ StringBuilder cmd = new StringBuilder();
+ cmd.append("appops set ");
+ cmd.append(packageName);
+ cmd.append(" ");
+ cmd.append(operation);
+ cmd.append(enable ? " allow" : " deny");
+ instrumentation.getUiAutomation().executeShellCommand(cmd.toString());
+
+ StringBuilder query = new StringBuilder();
+ query.append("appops get ");
+ query.append(packageName);
+ query.append(" ");
+ query.append(operation);
+ String queryStr = query.toString();
+
+ String expectedResult = enable ? "allow" : "deny";
+ String result = "";
+ while(!result.contains(expectedResult)) {
+ ParcelFileDescriptor pfd = instrumentation.getUiAutomation().executeShellCommand(
+ queryStr);
+ InputStream inputStream = new FileInputStream(pfd.getFileDescriptor());
+ result = convertStreamToString(inputStream);
+ }
+ }
+}
diff --git a/tests/tests/media/src/android/media/cts/VideoDecoderPerfTest.java b/tests/tests/media/src/android/media/cts/VideoDecoderPerfTest.java
index ede5040..f5680f6 100644
--- a/tests/tests/media/src/android/media/cts/VideoDecoderPerfTest.java
+++ b/tests/tests/media/src/android/media/cts/VideoDecoderPerfTest.java
@@ -31,6 +31,7 @@
import android.media.MediaExtractor;
import android.media.MediaFormat;
import android.util.Log;
+import android.util.Range;
import android.view.Surface;
import com.android.cts.util.ResultType;
@@ -58,6 +59,8 @@
LinkedList<ByteBuffer> mSamplesInMemory = new LinkedList<ByteBuffer>();
private static final int MOVING_AVERAGE_NUM = 10;
private MediaFormat mDecOutputFormat;
+ private double[] mMeasuredFps;
+ private String[] mResultRawData;
private Resources mResources;
private DeviceReportLog mReportLog;
@@ -104,6 +107,8 @@
}
boolean pass = false;
+ mMeasuredFps = new double[NUMBER_OF_REPEAT];
+ mResultRawData = new String[NUMBER_OF_REPEAT];
Log.d(TAG, "testing " + name);
for (int i = 0; i < NUMBER_OF_REPEAT; ++i) {
// Decode to Surface.
@@ -118,7 +123,16 @@
Log.d(TAG, "round #" + i + " decode to buffer");
doDecode(name, video, width, height, null, i);
}
- assertTrue("Measured fps doesn't match with reported achievable frame rates.", pass);
+
+ if (!pass) {
+ Range<Double> reportedRange =
+ MediaUtils.getAchievableFrameRatesFor(name, mime, width, height);
+ String failMessage =
+ MediaUtils.getErrorMessage(reportedRange, mMeasuredFps, mResultRawData);
+ fail(failMessage);
+ }
+ mMeasuredFps = null;
+ mResultRawData = null;
}
// use 0 for summary line, detail for each test config is in the report.
mReportLog.printSummary("average fps", 0, ResultType.HIGHER_BETTER, ResultUnit.FPS);
@@ -276,9 +290,15 @@
double decMax = Stat.getMax(avgs);
double decAvg = Stat.getAverage(avgs);
double decStdev = MediaUtils.getStdev(avgs);
- MediaUtils.logResults(mReportLog, testConfig, decMin, decMax, decAvg, decStdev);
+ String result =
+ MediaUtils.logResults(mReportLog, testConfig, decMin, decMax, decAvg, decStdev);
+ fps = 1000000000 / decMin;
+ if (surface != null) {
+ mMeasuredFps[round] = fps;
+ mResultRawData[round] = result;
+ }
- return MediaUtils.verifyResults(name, mime, w, h, 1000000000 / decMin);
+ return MediaUtils.verifyResults(name, mime, w, h, fps);
}
public void testH2640320x0240Other() throws Exception {
diff --git a/tests/tests/net/src/android/net/cts/ConnectivityManagerTest.java b/tests/tests/net/src/android/net/cts/ConnectivityManagerTest.java
index e4d77b1..88dbd7c 100644
--- a/tests/tests/net/src/android/net/cts/ConnectivityManagerTest.java
+++ b/tests/tests/net/src/android/net/cts/ConnectivityManagerTest.java
@@ -67,7 +67,6 @@
private PackageManager mPackageManager;
private final HashMap<Integer, NetworkConfig> mNetworks =
new HashMap<Integer, NetworkConfig>();
- private final List<Integer>mProtectedNetworks = new ArrayList<Integer>();
@Override
protected void setUp() throws Exception {
@@ -90,13 +89,6 @@
mNetworks.put(n.type, n);
} catch (Exception e) {}
}
-
- // Get com.android.internal.R.array.config_protectedNetworks
- resId = getContext().getResources().getIdentifier("config_protectedNetworks", "array", "android");
- int[] protectedNetworks = getContext().getResources().getIntArray(resId);
- for (int p : protectedNetworks) {
- mProtectedNetworks.add(p);
- }
}
public void testIsNetworkTypeValid() {
@@ -190,6 +182,27 @@
}
}
+ private void assertStartUsingNetworkFeatureUnsupported(int networkType, String feature) {
+ try {
+ mCm.startUsingNetworkFeature(networkType, feature);
+ fail("startUsingNetworkFeature is no longer supported in the current API version");
+ } catch (UnsupportedOperationException expected) {}
+ }
+
+ private void assertStopUsingNetworkFeatureUnsupported(int networkType, String feature) {
+ try {
+ mCm.startUsingNetworkFeature(networkType, feature);
+ fail("stopUsingNetworkFeature is no longer supported in the current API version");
+ } catch (UnsupportedOperationException expected) {}
+ }
+
+ private void assertRequestRouteToHostUnsupported(int networkType, int hostAddress) {
+ try {
+ mCm.requestRouteToHost(networkType, hostAddress);
+ fail("requestRouteToHost is no longer supported in the current API version");
+ } catch (UnsupportedOperationException expected) {}
+ }
+
public void testStartUsingNetworkFeature() {
final String invalidateFeature = "invalidateFeature";
@@ -198,27 +211,9 @@
final int wifiOnlyStartFailureCode = PhoneConstants.APN_REQUEST_FAILED;
final int wifiOnlyStopFailureCode = -1;
- NetworkInfo ni = mCm.getNetworkInfo(TYPE_MOBILE);
- if (ni != null) {
- assertEquals(PhoneConstants.APN_REQUEST_FAILED,
- mCm.startUsingNetworkFeature(TYPE_MOBILE, invalidateFeature));
- assertEquals(failureCode, mCm.stopUsingNetworkFeature(TYPE_MOBILE,
- invalidateFeature));
- } else {
- assertEquals(wifiOnlyStartFailureCode, mCm.startUsingNetworkFeature(TYPE_MOBILE,
- invalidateFeature));
- assertEquals(wifiOnlyStopFailureCode, mCm.stopUsingNetworkFeature(TYPE_MOBILE,
- invalidateFeature));
- }
-
- ni = mCm.getNetworkInfo(TYPE_WIFI);
- if (ni != null) {
- // Should return failure because MMS is not supported on WIFI.
- assertEquals(PhoneConstants.APN_REQUEST_FAILED, mCm.startUsingNetworkFeature(TYPE_WIFI,
- mmsFeature));
- assertEquals(failureCode, mCm.stopUsingNetworkFeature(TYPE_WIFI,
- mmsFeature));
- }
+ assertStartUsingNetworkFeatureUnsupported(TYPE_MOBILE, invalidateFeature);
+ assertStopUsingNetworkFeatureUnsupported(TYPE_MOBILE, invalidateFeature);
+ assertStartUsingNetworkFeatureUnsupported(TYPE_WIFI, mmsFeature);
}
private boolean isSupported(int networkType) {
@@ -229,11 +224,6 @@
(networkType == ConnectivityManager.TYPE_VPN);
}
- // true if only the system can turn it on
- private boolean isNetworkProtected(int networkType) {
- return mProtectedNetworks.contains(networkType);
- }
-
public void testIsNetworkSupported() {
for (int type = -1; type <= ConnectivityManager.MAX_NETWORK_TYPE; type++) {
boolean supported = mCm.isNetworkSupported(type);
@@ -247,82 +237,14 @@
public void testRequestRouteToHost() {
for (int type = -1 ; type <= ConnectivityManager.MAX_NETWORK_TYPE; type++) {
- NetworkInfo ni = mCm.getNetworkInfo(type);
- boolean expectToWork = isSupported(type) && !isNetworkProtected(type) &&
- ni != null && ni.isConnected();
-
- try {
- assertTrue("Network type " + type,
- mCm.requestRouteToHost(type, HOST_ADDRESS) == expectToWork);
- } catch (Exception e) {
- Log.d(TAG, "got exception in requestRouteToHost for type " + type);
- assertFalse("Exception received for type " + type, expectToWork);
- }
-
- //TODO verify route table
+ assertRequestRouteToHostUnsupported(type, HOST_ADDRESS);
}
-
- assertFalse(mCm.requestRouteToHost(-1, HOST_ADDRESS));
}
public void testTest() {
mCm.getBackgroundDataSetting();
}
- /** Test that hipri can be brought up when Wifi is enabled. */
- public void testStartUsingNetworkFeature_enableHipri() throws Exception {
- if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)
- || !mPackageManager.hasSystemFeature(PackageManager.FEATURE_WIFI)) {
- // This test requires a mobile data connection and WiFi.
- return;
- }
-
- boolean isWifiEnabled = mWifiManager.isWifiEnabled();
- boolean isWifiConnected = false;
-
- NetworkInfo nwInfo = mCm.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
- if (nwInfo != null) {
- isWifiConnected = nwInfo.isConnected();
- }
- try {
- // Make sure WiFi is connected to an access point.
- if (!isWifiConnected) {
- connectToWifi();
- }
-
- // Register a receiver that will capture the connectivity change for hipri.
- ConnectivityActionReceiver receiver = new ConnectivityActionReceiver(
- ConnectivityManager.TYPE_MOBILE_HIPRI, NetworkInfo.State.CONNECTED);
- IntentFilter filter = new IntentFilter();
- filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
- mContext.registerReceiver(receiver, filter);
-
- // Try to start using the hipri feature...
- int result = mCm.startUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE,
- FEATURE_ENABLE_HIPRI);
- assertTrue("Couldn't start using the HIPRI feature.", result != -1);
-
- // Check that the ConnectivityManager reported that it connected using hipri...
- assertTrue("Couldn't connect using hipri...", receiver.waitForState());
-
- assertTrue("Couldn't requestRouteToHost using HIPRI.",
- mCm.requestRouteToHost(ConnectivityManager.TYPE_MOBILE_HIPRI, HOST_ADDRESS));
- // TODO check dns selection
- // TODO check routes
- } catch (InterruptedException e) {
- fail("Broadcast receiver waiting for ConnectivityManager interrupted.");
- } finally {
- mCm.stopUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE,
- FEATURE_ENABLE_HIPRI);
- // TODO wait for HIPRI to go
- // TODO check dns selection
- // TODO check routes
- if (!isWifiEnabled) {
- disconnectFromWifi();
- }
- }
- }
-
/**
* Exercises both registerNetworkCallback and unregisterNetworkCallback. This checks to
* see if we get a callback for the TRANSPORT_WIFI transport type being available.
diff --git a/tests/tests/netlegacy22/Android.mk b/tests/tests/netlegacy22/Android.mk
new file mode 100644
index 0000000..68fd6f8
--- /dev/null
+++ b/tests/tests/netlegacy22/Android.mk
@@ -0,0 +1,32 @@
+# 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 := tests
+# and when built explicitly put it in the data partition
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := CtsNetTestCasesLegacyApi22
+
+LOCAL_SDK_VERSION := 22
+
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+
+include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/netlegacy22/AndroidManifest.xml b/tests/tests/netlegacy22/AndroidManifest.xml
new file mode 100644
index 0000000..d243e45
--- /dev/null
+++ b/tests/tests/netlegacy22/AndroidManifest.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.cts.net.legacy22">
+
+ <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+ <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
+ <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
+ <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
+ <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
+ <uses-permission android:name="android.permission.INTERNET" />
+
+ <application>
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+ android:targetPackage="com.android.cts.net.legacy22"
+ android:label="CTS tests of legacy android.net APIs as of API 22">
+ <meta-data android:name="listener"
+ android:value="com.android.cts.runner.CtsTestRunListener" />
+ </instrumentation>
+
+</manifest>
+
diff --git a/tests/tests/netlegacy22/src/android/net/cts/legacy/api22/ConnectivityManagerLegacyTest.java b/tests/tests/netlegacy22/src/android/net/cts/legacy/api22/ConnectivityManagerLegacyTest.java
new file mode 100644
index 0000000..8a9002b
--- /dev/null
+++ b/tests/tests/netlegacy22/src/android/net/cts/legacy/api22/ConnectivityManagerLegacyTest.java
@@ -0,0 +1,259 @@
+/*
+ * 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 android.net.cts.legacy.api22;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.net.ConnectivityManager;
+import android.net.LinkAddress;
+import android.net.LinkProperties;
+import android.net.Network;
+import android.net.NetworkInfo;
+import android.net.wifi.WifiManager;
+import android.os.ConditionVariable;
+import android.test.AndroidTestCase;
+import android.util.Log;
+
+import java.net.DatagramSocket;
+import java.net.Inet4Address;
+import java.net.InetAddress;
+import java.util.ArrayList;
+import java.util.List;
+
+import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
+import static android.net.ConnectivityManager.TYPE_MOBILE;
+import static android.net.ConnectivityManager.TYPE_MOBILE_HIPRI;
+import static android.net.ConnectivityManager.TYPE_VPN;
+import static android.net.ConnectivityManager.TYPE_WIFI;
+
+public class ConnectivityManagerLegacyTest extends AndroidTestCase {
+ private static final String TAG = ConnectivityManagerLegacyTest.class.getSimpleName();
+ private static final String FEATURE_ENABLE_HIPRI = "enableHIPRI";
+ private static final String HOST_ADDRESS1 = "192.0.2.1";
+ private static final String HOST_ADDRESS2 = "192.0.2.2";
+ private static final String HOST_ADDRESS3 = "192.0.2.3";
+
+ // These are correct as of API level 22, which is what we target here.
+ private static final int APN_REQUEST_FAILED = 3;
+ private static final int MAX_NETWORK_TYPE = TYPE_VPN;
+
+ private ConnectivityManager mCm;
+ private WifiManager mWifiManager;
+ private PackageManager mPackageManager;
+
+ private final List<Integer>mProtectedNetworks = new ArrayList<Integer>();
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ mCm = (ConnectivityManager) getContext().getSystemService(Context.CONNECTIVITY_SERVICE);
+ mWifiManager = (WifiManager) getContext().getSystemService(Context.WIFI_SERVICE);
+ mPackageManager = getContext().getPackageManager();
+
+ // Get com.android.internal.R.array.config_protectedNetworks
+ int resId = getContext().getResources().getIdentifier("config_protectedNetworks", "array", "android");
+ int[] protectedNetworks = getContext().getResources().getIntArray(resId);
+ for (int p : protectedNetworks) {
+ mProtectedNetworks.add(p);
+ }
+ }
+
+ // true if only the system can turn it on
+ private boolean isNetworkProtected(int networkType) {
+ return mProtectedNetworks.contains(networkType);
+ }
+
+ private int ipv4AddrToInt(String addrString) throws Exception {
+ byte[] addr = ((Inet4Address) InetAddress.getByName(addrString)).getAddress();
+ return ((addr[3] & 0xff) << 24) | ((addr[2] & 0xff) << 16) |
+ ((addr[1] & 0xff) << 8) | (addr[0] & 0xff);
+ }
+
+ private void checkSourceAddress(String addrString, int type) throws Exception {
+ DatagramSocket d = new DatagramSocket();
+ d.connect(InetAddress.getByName(addrString), 7);
+ InetAddress localAddress = d.getLocalAddress();
+
+ Network[] networks = mCm.getAllNetworks();
+ for (int i = 0; i < networks.length; i++) {
+ NetworkInfo ni = mCm.getNetworkInfo(networks[i]);
+ if (ni != null && ni.getType() == type) {
+ LinkProperties lp = mCm.getLinkProperties(networks[i]);
+ for (LinkAddress address : lp.getLinkAddresses()) {
+ if (address.getAddress().equals(localAddress)) {
+ return;
+ }
+ }
+ }
+ }
+ fail("Local address " + localAddress + " not assigned to any network of type " + type);
+ }
+
+ /** Test that hipri can be brought up when Wifi is enabled. */
+ public void testStartUsingNetworkFeature_enableHipri() throws Exception {
+ if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)
+ || !mPackageManager.hasSystemFeature(PackageManager.FEATURE_WIFI)) {
+ // This test requires a mobile data connection and WiFi.
+ return;
+ }
+
+ // Make sure WiFi is connected to an access point.
+ connectToWifi();
+
+ expectNetworkBroadcast(TYPE_MOBILE_HIPRI, NetworkInfo.State.CONNECTED,
+ new Runnable() {
+ public void run() {
+ int ret = mCm.startUsingNetworkFeature(TYPE_MOBILE, FEATURE_ENABLE_HIPRI);
+ assertTrue("Couldn't start using the HIPRI feature.", ret != -1);
+ }
+ });
+
+ assertTrue("Couldn't requestRouteToHost using HIPRI.",
+ mCm.requestRouteToHost(TYPE_MOBILE_HIPRI, ipv4AddrToInt(HOST_ADDRESS1)));
+
+ try { Thread.sleep(1000); } catch(Exception e) {}
+ checkSourceAddress(HOST_ADDRESS1, TYPE_MOBILE);
+ checkSourceAddress(HOST_ADDRESS2, TYPE_WIFI);
+
+ // TODO check dns selection
+
+ expectNetworkBroadcast(TYPE_MOBILE_HIPRI, NetworkInfo.State.DISCONNECTED,
+ new Runnable() {
+ public void run() {
+ int ret = mCm.stopUsingNetworkFeature(TYPE_MOBILE, FEATURE_ENABLE_HIPRI);
+ assertTrue("Couldn't stop using the HIPRI feature.", ret != -1);
+ }
+ });
+
+
+ // TODO check dns selection
+ disconnectFromWifi();
+ }
+
+ public void testStartUsingNetworkFeature() {
+
+ final String invalidFeature = "invalidFeature";
+ final String mmsFeature = "enableMMS";
+ final int failureCode = -1;
+ final int wifiOnlyStartFailureCode = APN_REQUEST_FAILED;
+ final int wifiOnlyStopFailureCode = -1;
+
+ NetworkInfo ni = mCm.getNetworkInfo(TYPE_MOBILE);
+ if (ni != null) {
+ assertEquals(APN_REQUEST_FAILED,
+ mCm.startUsingNetworkFeature(TYPE_MOBILE, invalidFeature));
+ assertEquals(failureCode, mCm.stopUsingNetworkFeature(TYPE_MOBILE, invalidFeature));
+ } else {
+ assertEquals(wifiOnlyStartFailureCode, mCm.startUsingNetworkFeature(TYPE_MOBILE,
+ invalidFeature));
+ assertEquals(wifiOnlyStopFailureCode, mCm.stopUsingNetworkFeature(TYPE_MOBILE,
+ invalidFeature));
+ }
+
+ ni = mCm.getNetworkInfo(TYPE_WIFI);
+ if (ni != null) {
+ // Should return failure because MMS is not supported on WIFI.
+ assertEquals(APN_REQUEST_FAILED, mCm.startUsingNetworkFeature(TYPE_WIFI,
+ mmsFeature));
+ assertEquals(failureCode, mCm.stopUsingNetworkFeature(TYPE_WIFI,
+ mmsFeature));
+ }
+ }
+
+ private void expectNetworkBroadcast(final int type, final NetworkInfo.State state,
+ Runnable afterWhat) {
+ final int TIMEOUT_MS = 30 * 1000;
+ final ConditionVariable var = new ConditionVariable();
+
+ Log.d(TAG, "Waiting for " + state + " broadcast for type " + type);
+ BroadcastReceiver receiver = new BroadcastReceiver() {
+ public void onReceive(Context context, Intent intent) {
+ NetworkInfo ni = intent.getExtras()
+ .getParcelable(ConnectivityManager.EXTRA_NETWORK_INFO);
+ assertNotNull("CONNECTIVITY_ACTION with null EXTRA_NETWORK_INFO", ni);
+ if (ni.getType() == type && ni.getState().equals(state)) {
+ Log.d(TAG, "Received expected " + state + " broadcast for type " + type);
+ var.open();
+ }
+ }
+ };
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(CONNECTIVITY_ACTION);
+ mContext.registerReceiver(receiver, filter);
+
+ try {
+ afterWhat.run();
+ final String msg = "Did not receive expected " + state + " broadcast for type " + type +
+ " after " + TIMEOUT_MS + " ms";
+ assertTrue(msg, var.block(TIMEOUT_MS));
+ } finally {
+ mContext.unregisterReceiver(receiver);
+ }
+ }
+
+ private boolean isWifiConnected() {
+ NetworkInfo ni = mCm.getNetworkInfo(TYPE_WIFI);
+ return ni != null && ni.isConnected();
+ }
+
+ private void setWifiState(final boolean enabled) {
+ if (enabled != isWifiConnected()) {
+ final NetworkInfo.State desiredState = enabled ?
+ NetworkInfo.State.CONNECTED :
+ NetworkInfo.State.DISCONNECTED;
+ expectNetworkBroadcast(TYPE_WIFI, desiredState, new Runnable() {
+ public void run() {
+ mWifiManager.setWifiEnabled(enabled);
+ }
+ });
+ }
+ }
+
+ private void connectToWifi() {
+ setWifiState(true);
+ }
+
+ private void disconnectFromWifi() {
+ setWifiState(false);
+ }
+
+ private boolean isNetworkSupported(int networkType) {
+ return mCm.getNetworkInfo(networkType) != null;
+ }
+
+ public void testRequestRouteToHost() throws Exception {
+ for (int type = -1 ; type <= MAX_NETWORK_TYPE; type++) {
+ NetworkInfo ni = mCm.getNetworkInfo(type);
+ boolean expectToWork = isNetworkSupported(type) && !isNetworkProtected(type) &&
+ ni != null && ni.isConnected();
+
+ try {
+ assertTrue("Network type " + type,
+ mCm.requestRouteToHost(type, ipv4AddrToInt(HOST_ADDRESS3)) == expectToWork);
+ } catch (Exception e) {
+ Log.d(TAG, "got exception in requestRouteToHost for type " + type);
+ assertFalse("Exception received for type " + type, expectToWork);
+ }
+
+ //TODO verify route table
+ }
+
+ assertFalse(mCm.requestRouteToHost(-1, ipv4AddrToInt(HOST_ADDRESS1)));
+ }
+}
diff --git a/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java b/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java
new file mode 100644
index 0000000..a4d68cb
--- /dev/null
+++ b/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java
@@ -0,0 +1,64 @@
+/*
+* 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 android.permission2.cts;
+
+import android.Manifest;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PermissionInfo;
+import android.test.AndroidTestCase;
+import android.text.TextUtils;
+import android.util.ArraySet;
+
+import java.util.Set;
+
+/**
+ * Tests for permission policy on the platform.
+ */
+public class PermissionPolicyTest extends AndroidTestCase {
+ private static final String PLATFORM_PACKAGE_NAME = "android";
+
+ private static final Set<String> PERMISSION_GROUPS = new ArraySet<>();
+ static {
+ PERMISSION_GROUPS.add(Manifest.permission_group.CALENDAR);
+ PERMISSION_GROUPS.add(Manifest.permission_group.CAMERA);
+ PERMISSION_GROUPS.add(Manifest.permission_group.CONTACTS);
+ PERMISSION_GROUPS.add(Manifest.permission_group.LOCATION);
+ PERMISSION_GROUPS.add(Manifest.permission_group.MICROPHONE);
+ PERMISSION_GROUPS.add(Manifest.permission_group.PHONE);
+ PERMISSION_GROUPS.add(Manifest.permission_group.SENSORS);
+ PERMISSION_GROUPS.add(Manifest.permission_group.SMS);
+ PERMISSION_GROUPS.add(Manifest.permission_group.STORAGE);
+ }
+
+ public void testPlatformDefinedRuntimePermissionValid() throws Exception {
+ PackageManager packageManager = getContext().getPackageManager();
+ PackageInfo packageInfo = packageManager.getPackageInfo(PLATFORM_PACKAGE_NAME,
+ PackageManager.GET_PERMISSIONS);
+ for (PermissionInfo permission : packageInfo.permissions) {
+ if ((permission.protectionLevel & PermissionInfo.PROTECTION_DANGEROUS) == 0) {
+ continue;
+ }
+ assertTrue(permission.name + " must be in one of these groups: " + PERMISSION_GROUPS,
+ PERMISSION_GROUPS.contains(permission.group));
+ assertFalse(permission.name + " must have non-empty label",
+ TextUtils.isEmpty(permission.loadLabel(packageManager)));
+ assertFalse(permission.name + " must have non-empty description",
+ TextUtils.isEmpty(permission.loadDescription(packageManager)));
+ }
+ }
+}
diff --git a/tests/tests/telecom/src/android/telecom/cts/BaseTelecomTestWithMockServices.java b/tests/tests/telecom/src/android/telecom/cts/BaseTelecomTestWithMockServices.java
index 323190c..31ca09b 100644
--- a/tests/tests/telecom/src/android/telecom/cts/BaseTelecomTestWithMockServices.java
+++ b/tests/tests/telecom/src/android/telecom/cts/BaseTelecomTestWithMockServices.java
@@ -86,13 +86,16 @@
String mPreviousDefaultDialer = null;
MockConnectionService connectionService = null;
+ boolean mShouldTestTelecom = true;
+
@Override
protected void setUp() throws Exception {
super.setUp();
mContext = getInstrumentation().getContext();
mTelecomManager = (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
- if (shouldTestTelecom(mContext)) {
+ mShouldTestTelecom = shouldTestTelecom(mContext);
+ if (mShouldTestTelecom) {
mPreviousDefaultDialer = TestUtils.getDefaultDialer(getInstrumentation());
TestUtils.setDefaultDialer(getInstrumentation(), PACKAGE);
setupCallbacks();
@@ -101,7 +104,7 @@
@Override
protected void tearDown() throws Exception {
- if (shouldTestTelecom(mContext)) {
+ if (mShouldTestTelecom) {
cleanupCalls();
if (!TextUtils.isEmpty(mPreviousDefaultDialer)) {
TestUtils.setDefaultDialer(getInstrumentation(), mPreviousDefaultDialer);
@@ -319,8 +322,6 @@
assertThat("Telecom should create outgoing connection for outgoing call",
connectionService.outgoingConnections.size(), not(equalTo(0)));
- assertEquals("Telecom should not create incoming connections for outgoing calls",
- 0, connectionService.incomingConnections.size());
MockConnection connection = connectionService.outgoingConnections.get(connectionIndex);
return connection;
}
@@ -342,8 +343,6 @@
assertThat("Telecom should create incoming connections for incoming calls",
connectionService.incomingConnections.size(), not(equalTo(0)));
- assertEquals("Telecom should not create outgoing connections for incoming calls",
- 0, connectionService.outgoingConnections.size());
MockConnection connection = connectionService.incomingConnections.get(connectionIndex);
setAndVerifyConnectionForIncomingCall(connection);
return connection;
diff --git a/tests/tests/telecom/src/android/telecom/cts/CallDetailsTest.java b/tests/tests/telecom/src/android/telecom/cts/CallDetailsTest.java
index dd93573..879c995 100644
--- a/tests/tests/telecom/src/android/telecom/cts/CallDetailsTest.java
+++ b/tests/tests/telecom/src/android/telecom/cts/CallDetailsTest.java
@@ -65,7 +65,7 @@
@Override
protected void setUp() throws Exception {
super.setUp();
- if (TestUtils.shouldTestTelecom(mContext)) {
+ if (mShouldTestTelecom) {
PhoneAccount account = setupConnectionService(
new MockConnectionService() {
@Override
@@ -93,23 +93,27 @@
}
}, FLAG_REGISTER | FLAG_ENABLE);
+ /** Place a call as a part of the setup before we test the various
+ * Call details.
+ */
+ placeAndVerifyCall();
+ verifyConnectionForOutgoingCall();
+
+ mInCallService = mInCallCallbacks.getService();
+ mCall = mInCallService.getLastCall();
+
+ assertCallState(mCall, Call.STATE_DIALING);
}
- /** Place a call as a part of the setup before we test the various
- * Call details.
- */
- placeAndVerifyCall();
- verifyConnectionForOutgoingCall();
-
- mInCallService = mInCallCallbacks.getService();
- mCall = mInCallService.getLastCall();
-
- assertCallState(mCall, Call.STATE_DIALING);
}
/**
* Tests whether the getAccountHandle() getter returns the correct object.
*/
public void testAccountHandle() {
+ if (!mShouldTestTelecom) {
+ return;
+ }
+
assertThat(mCall.getDetails().getAccountHandle(), is(PhoneAccountHandle.class));
assertEquals(TEST_PHONE_ACCOUNT_HANDLE, mCall.getDetails().getAccountHandle());
}
@@ -118,6 +122,10 @@
* Tests whether the getCallCapabilities() getter returns the correct object.
*/
public void testCallCapabilities() {
+ if (!mShouldTestTelecom) {
+ return;
+ }
+
assertThat(mCall.getDetails().getCallCapabilities(), is(Integer.class));
assertEquals(CALL_CAPABILITIES, mCall.getDetails().getCallCapabilities());
assertTrue(mCall.getDetails().can(Call.Details.CAPABILITY_HOLD));
@@ -130,6 +138,10 @@
* Tests whether the getCallerDisplayName() getter returns the correct object.
*/
public void testCallerDisplayName() {
+ if (!mShouldTestTelecom) {
+ return;
+ }
+
assertThat(mCall.getDetails().getCallerDisplayName(), is(String.class));
assertEquals(CALLER_DISPLAY_NAME, mCall.getDetails().getCallerDisplayName());
}
@@ -138,6 +150,10 @@
* Tests whether the getCallerDisplayNamePresentation() getter returns the correct object.
*/
public void testCallerDisplayNamePresentation() {
+ if (!mShouldTestTelecom) {
+ return;
+ }
+
assertThat(mCall.getDetails().getCallerDisplayNamePresentation(), is(Integer.class));
assertEquals(CALLER_DISPLAY_NAME_PRESENTATION, mCall.getDetails().getCallerDisplayNamePresentation());
}
@@ -146,6 +162,10 @@
* Tests whether the getCallProperties() getter returns the correct object.
*/
public void testCallProperties() {
+ if (!mShouldTestTelecom) {
+ return;
+ }
+
assertThat(mCall.getDetails().getCallProperties(), is(Integer.class));
assertEquals(CALL_PROPERTIES, mCall.getDetails().getCallProperties());
}
@@ -154,6 +174,10 @@
* Tests whether the getConnectTimeMillis() getter returns the correct object.
*/
public void testConnectTimeMillis() {
+ if (!mShouldTestTelecom) {
+ return;
+ }
+
assertThat(mCall.getDetails().getConnectTimeMillis(), is(Long.class));
}
@@ -161,6 +185,10 @@
* Tests whether the getDisconnectCause() getter returns the correct object.
*/
public void testDisconnectCause() {
+ if (!mShouldTestTelecom) {
+ return;
+ }
+
assertThat(mCall.getDetails().getDisconnectCause(), is(DisconnectCause.class));
}
@@ -168,6 +196,10 @@
* Tests whether the getExtras() getter returns the correct object.
*/
public void testExtras() {
+ if (!mShouldTestTelecom) {
+ return;
+ }
+
if (mCall.getDetails().getExtras() != null) {
assertThat(mCall.getDetails().getExtras(), is(Bundle.class));
}
@@ -177,6 +209,10 @@
* Tests whether the getIntentExtras() getter returns the correct object.
*/
public void testIntentExtras() {
+ if (!mShouldTestTelecom) {
+ return;
+ }
+
assertThat(mCall.getDetails().getIntentExtras(), is(Bundle.class));
}
@@ -184,6 +220,10 @@
* Tests whether the getGatewayInfo() getter returns the correct object.
*/
public void testGatewayInfo() {
+ if (!mShouldTestTelecom) {
+ return;
+ }
+
if (mCall.getDetails().getGatewayInfo() != null) {
assertThat(mCall.getDetails().getGatewayInfo(), is(GatewayInfo.class));
}
@@ -193,6 +233,10 @@
* Tests whether the getHandle() getter returns the correct object.
*/
public void testHandle() {
+ if (!mShouldTestTelecom) {
+ return;
+ }
+
assertThat(mCall.getDetails().getHandle(), is(Uri.class));
assertEquals(getTestNumber(), mCall.getDetails().getHandle());
}
@@ -201,6 +245,10 @@
* Tests whether the getHandlePresentation() getter returns the correct object.
*/
public void testHandlePresentation() {
+ if (!mShouldTestTelecom) {
+ return;
+ }
+
assertThat(mCall.getDetails().getHandlePresentation(), is(Integer.class));
assertEquals(MockConnectionService.CONNECTION_PRESENTATION, mCall.getDetails().getHandlePresentation());
}
@@ -209,6 +257,10 @@
* Tests whether the getStatusHints() getter returns the correct object.
*/
public void testStatusHints() {
+ if (!mShouldTestTelecom) {
+ return;
+ }
+
assertThat(mCall.getDetails().getStatusHints(), is(StatusHints.class));
assertEquals(mStatusHints.getLabel(), mCall.getDetails().getStatusHints().getLabel());
assertEquals(
@@ -221,6 +273,10 @@
* Tests whether the getVideoState() getter returns the correct object.
*/
public void testVideoState() {
+ if (!mShouldTestTelecom) {
+ return;
+ }
+
assertThat(mCall.getDetails().getVideoState(), is(Integer.class));
}
}
diff --git a/tests/tests/telecom/src/android/telecom/cts/ConferenceTest.java b/tests/tests/telecom/src/android/telecom/cts/ConferenceTest.java
index 989045c..121d559 100644
--- a/tests/tests/telecom/src/android/telecom/cts/ConferenceTest.java
+++ b/tests/tests/telecom/src/android/telecom/cts/ConferenceTest.java
@@ -51,17 +51,17 @@
protected void setUp() throws Exception {
super.setUp();
mContext = getInstrumentation().getContext();
- if (shouldTestTelecom(mContext)) {
+ if (mShouldTestTelecom) {
addOutgoingCalls();
addConferenceCall(mCall1, mCall2);
// Use vanilla conference object so that the CTS coverage tool detects the useage.
- mConferenceObject = (Conference)verifyConferenceForOutgoingCall();
+ mConferenceObject = verifyConferenceForOutgoingCall();
verifyConferenceObject(mConferenceObject, mConnection1, mConnection2);
}
}
public void testConferenceCreate() {
- if (!shouldTestTelecom(mContext)) {
+ if (!mShouldTestTelecom) {
return;
}
final Call conf = mInCallService.getLastConferenceCall();
@@ -81,7 +81,7 @@
}
public void testConferenceSplit() {
- if (!shouldTestTelecom(mContext)) {
+ if (!mShouldTestTelecom) {
return;
}
final Call conf = mInCallService.getLastConferenceCall();
@@ -101,7 +101,7 @@
}
public void testConferenceHoldAndUnhold() {
- if (!shouldTestTelecom(mContext)) {
+ if (!mShouldTestTelecom) {
return;
}
final Call conf = mInCallService.getLastConferenceCall();
@@ -119,7 +119,7 @@
}
public void testConferenceMergeAndSwap() {
- if (!shouldTestTelecom(mContext)) {
+ if (!mShouldTestTelecom) {
return;
}
final Call conf = mInCallService.getLastConferenceCall();
@@ -144,7 +144,7 @@
}
public void testConferenceSetters() {
- if (!shouldTestTelecom(mContext)) {
+ if (!mShouldTestTelecom) {
return;
}
final Call conf = mInCallService.getLastConferenceCall();
@@ -215,7 +215,7 @@
}
public void testConferenceAddAndRemoveConnection() {
- if (!shouldTestTelecom(mContext)) {
+ if (!mShouldTestTelecom) {
return;
}
final Call conf = mInCallService.getLastConferenceCall();
@@ -240,7 +240,7 @@
}
public void testConferenceDTMFTone() {
- if (!shouldTestTelecom(mContext)) {
+ if (!mShouldTestTelecom) {
return;
}
final Call conf = mInCallService.getLastConferenceCall();
diff --git a/tests/tests/telecom/src/android/telecom/cts/ConnectionServiceTest.java b/tests/tests/telecom/src/android/telecom/cts/ConnectionServiceTest.java
new file mode 100644
index 0000000..afaa3eb
--- /dev/null
+++ b/tests/tests/telecom/src/android/telecom/cts/ConnectionServiceTest.java
@@ -0,0 +1,96 @@
+/*
+ * 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 android.telecom.cts;
+
+import static android.telecom.cts.TestUtils.*;
+
+import android.telecom.Call;
+import android.telecom.Connection;
+import android.telecom.ConnectionService;
+import android.util.Log;
+
+import java.util.Collection;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Test some additional {@link ConnectionService} APIs not already covered by other tests.
+ */
+public class ConnectionServiceTest extends BaseTelecomTestWithMockServices {
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mContext = getInstrumentation().getContext();
+ if (mShouldTestTelecom) {
+ setupConnectionService(null, FLAG_REGISTER | FLAG_ENABLE);
+ }
+ }
+
+ public void testAddExistingConnection() {
+ if (!mShouldTestTelecom) {
+ return;
+ }
+
+ placeAndVerifyCall();
+ verifyConnectionForOutgoingCall();
+
+ final MockConnection connection = new MockConnection();
+ connection.setOnHold();
+ CtsConnectionService.addExistingConnectionToTelecom(TEST_PHONE_ACCOUNT_HANDLE, connection);
+
+ try {
+ if (!mInCallCallbacks.lock.tryAcquire(3, TimeUnit.SECONDS)) {
+ fail("No call added to InCallService.");
+ }
+ } catch (InterruptedException e) {
+ Log.i(TAG, "Test interrupted!");
+ }
+
+ final MockInCallService inCallService = mInCallCallbacks.getService();
+ final Call call = inCallService.getLastCall();
+ assertCallState(call, Call.STATE_HOLDING);
+ }
+
+ public void testGetAllConnections() {
+ if (!mShouldTestTelecom) {
+ return;
+ }
+
+ // Add first connection (outgoing call)
+ placeAndVerifyCall();
+ final Connection connection1 = verifyConnectionForOutgoingCall();
+
+ Collection<Connection> connections = CtsConnectionService.getAllConnectionsFromTelecom();
+ assertEquals(1, connections.size());
+ assertTrue(connections.contains(connection1));
+
+ // Add second connection (add existing connection)
+ final Connection connection2 = new MockConnection();
+ CtsConnectionService.addExistingConnectionToTelecom(TEST_PHONE_ACCOUNT_HANDLE, connection2);
+
+ connections = CtsConnectionService.getAllConnectionsFromTelecom();
+ assertEquals(2, connections.size());
+ assertTrue(connections.contains(connection2));
+
+ // Add third connection (incoming call)
+ addAndVerifyNewIncomingCall(getTestNumber(), null);
+ final Connection connection3 = verifyConnectionForIncomingCall();
+ connections = CtsConnectionService.getAllConnectionsFromTelecom();
+ assertEquals(3, connections.size());
+ assertTrue(connections.contains(connection3));
+ }
+}
diff --git a/tests/tests/telecom/src/android/telecom/cts/CtsConnectionService.java b/tests/tests/telecom/src/android/telecom/cts/CtsConnectionService.java
index f7e08ed6f..3c30e6b 100644
--- a/tests/tests/telecom/src/android/telecom/cts/CtsConnectionService.java
+++ b/tests/tests/telecom/src/android/telecom/cts/CtsConnectionService.java
@@ -24,6 +24,8 @@
import android.telecom.RemoteConference;
import android.telecom.RemoteConnection;
+import java.util.Collection;
+
/**
* This is the official ConnectionService for Telecom's CTS App. Since telecom requires that a
* CS be registered in the AndroidManifest.xml file, we have to have a single implementation
@@ -135,6 +137,19 @@
}
}
+ public static void addExistingConnectionToTelecom(
+ PhoneAccountHandle phoneAccountHandle, Connection connection) {
+ synchronized(sLock) {
+ sTelecomConnectionService.addExistingConnection(phoneAccountHandle, connection);
+ }
+ }
+
+ public static Collection<Connection> getAllConnectionsFromTelecom() {
+ synchronized(sLock) {
+ return sTelecomConnectionService.getAllConnections();
+ }
+ }
+
public static RemoteConnection createRemoteOutgoingConnectionToTelecom(
PhoneAccountHandle connectionManagerPhoneAccount,
ConnectionRequest request) {
diff --git a/tests/tests/telecom/src/android/telecom/cts/ExtendedInCallServiceTest.java b/tests/tests/telecom/src/android/telecom/cts/ExtendedInCallServiceTest.java
index 74fc143..216ba97 100644
--- a/tests/tests/telecom/src/android/telecom/cts/ExtendedInCallServiceTest.java
+++ b/tests/tests/telecom/src/android/telecom/cts/ExtendedInCallServiceTest.java
@@ -36,13 +36,13 @@
@Override
protected void setUp() throws Exception {
super.setUp();
- if (TestUtils.shouldTestTelecom(mContext)) {
+ if (mShouldTestTelecom) {
setupConnectionService(null, FLAG_REGISTER | FLAG_ENABLE);
}
}
public void testAddNewOutgoingCallAndThenDisconnect() {
- if (!shouldTestTelecom(mContext)) {
+ if (!mShouldTestTelecom) {
return;
}
@@ -56,7 +56,7 @@
}
public void testMuteAndUnmutePhone() {
- if (!shouldTestTelecom(mContext)) {
+ if (!mShouldTestTelecom) {
return;
}
@@ -83,7 +83,7 @@
}
public void testSwitchAudioRoutes() {
- if (!shouldTestTelecom(mContext)) {
+ if (!mShouldTestTelecom) {
return;
}
@@ -122,7 +122,7 @@
* @see {@link Call#stopDtmfTone()}
*/
public void testPlayAndStopDtmfTones() {
- if (!shouldTestTelecom(mContext)) {
+ if (!mShouldTestTelecom) {
return;
}
@@ -155,7 +155,7 @@
}
public void testHoldAndUnholdCall() {
- if (!shouldTestTelecom(mContext)) {
+ if (!mShouldTestTelecom) {
return;
}
@@ -182,6 +182,10 @@
}
public void testAnswerIncomingCallAudioOnly() {
+ if (!mShouldTestTelecom) {
+ return;
+ }
+
addAndVerifyNewIncomingCall(getTestNumber(), null);
final MockConnection connection = verifyConnectionForIncomingCall();
@@ -199,6 +203,10 @@
}
public void testAnswerIncomingCallAsVideo_SendsCorrectVideoState() {
+ if (!mShouldTestTelecom) {
+ return;
+ }
+
addAndVerifyNewIncomingCall(getTestNumber(), null);
final MockConnection connection = verifyConnectionForIncomingCall();
@@ -218,6 +226,10 @@
}
public void testRejectIncomingCall() {
+ if (!mShouldTestTelecom) {
+ return;
+ }
+
addAndVerifyNewIncomingCall(getTestNumber(), null);
final MockConnection connection = verifyConnectionForIncomingCall();
@@ -235,7 +247,7 @@
}
public void testCanAddCall_CannotAddForExistingDialingCall() {
- if (!shouldTestTelecom(mContext)) {
+ if (!mShouldTestTelecom) {
return;
}
@@ -252,7 +264,7 @@
}
public void testCanAddCall_CanAddForExistingActiveCall() {
- if (!shouldTestTelecom(mContext)) {
+ if (!mShouldTestTelecom) {
return;
}
@@ -273,7 +285,7 @@
}
public void testCanAddCall_CannotAddIfTooManyCalls() {
- if (!shouldTestTelecom(mContext)) {
+ if (!mShouldTestTelecom) {
return;
}
@@ -308,7 +320,7 @@
}
public void testOnBringToForeground() {
- if (!shouldTestTelecom(mContext)) {
+ if (!mShouldTestTelecom) {
return;
}
@@ -340,7 +352,7 @@
}
public void testOnPostDialWaitAndContinue() {
- if (!shouldTestTelecom(mContext)) {
+ if (!mShouldTestTelecom) {
return;
}
@@ -354,7 +366,7 @@
assertCallState(call, Call.STATE_ACTIVE);
final String postDialString = "12345";
- connection.setPostDialWait(postDialString);
+ ((Connection) connection).setPostDialWait(postDialString);
mOnPostDialWaitCounter.waitForCount(1, WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
assertEquals(postDialString, mOnPostDialWaitCounter.getArgs(0)[1]);
@@ -372,7 +384,7 @@
}
public void testOnCannedTextResponsesLoaded() {
- if (!shouldTestTelecom(mContext)) {
+ if (!mShouldTestTelecom) {
return;
}
diff --git a/tests/tests/telecom/src/android/telecom/cts/NumberDialingTest.java b/tests/tests/telecom/src/android/telecom/cts/NumberDialingTest.java
index 8d6d114..8ffcf48 100644
--- a/tests/tests/telecom/src/android/telecom/cts/NumberDialingTest.java
+++ b/tests/tests/telecom/src/android/telecom/cts/NumberDialingTest.java
@@ -35,7 +35,7 @@
private static final int CS_WAIT_MILLIS = 2000;
public void testEndInPound() throws Exception {
- if (!shouldTestTelecom(mContext)) {
+ if (!mShouldTestTelecom) {
return;
}
diff --git a/tests/tests/telecom/src/android/telecom/cts/OutgoingCallTest.java b/tests/tests/telecom/src/android/telecom/cts/OutgoingCallTest.java
index b1c77fd..f2422c9 100644
--- a/tests/tests/telecom/src/android/telecom/cts/OutgoingCallTest.java
+++ b/tests/tests/telecom/src/android/telecom/cts/OutgoingCallTest.java
@@ -30,7 +30,7 @@
@Override
protected void setUp() throws Exception {
super.setUp();
- if (TestUtils.shouldTestTelecom(mContext)) {
+ if (mShouldTestTelecom) {
setupConnectionService(null, FLAG_REGISTER | FLAG_ENABLE);
}
}
@@ -52,6 +52,10 @@
* @see {@link TelecomManager#EXTRA_START_CALL_WITH_SPEAKERPHONE}
*/
public void testStartCallWithSpeakerphoneTrue_SpeakerphoneOnInCall() {
+ if (!mShouldTestTelecom) {
+ return;
+ }
+
final Bundle extras = new Bundle();
extras.putBoolean(TelecomManager.EXTRA_START_CALL_WITH_SPEAKERPHONE, true);
placeAndVerifyCall(extras);
@@ -60,6 +64,10 @@
}
public void testStartCallWithSpeakerphoneFalse_SpeakerphoneOffInCall() {
+ if (!mShouldTestTelecom) {
+ return;
+ }
+
final Bundle extras = new Bundle();
extras.putBoolean(TelecomManager.EXTRA_START_CALL_WITH_SPEAKERPHONE, false);
placeAndVerifyCall(extras);
@@ -68,6 +76,10 @@
}
public void testStartCallWithSpeakerphoneNotProvided_SpeakerphoneOffByDefault() {
+ if (!mShouldTestTelecom) {
+ return;
+ }
+
placeAndVerifyCall();
verifyConnectionForOutgoingCall();
assertAudioRoute(mInCallCallbacks.getService(), CallAudioState.ROUTE_EARPIECE);
diff --git a/tests/tests/telecom/src/android/telecom/cts/PhoneAccountOperationsTest.java b/tests/tests/telecom/src/android/telecom/cts/PhoneAccountOperationsTest.java
index 27c8cf4..cfa8e9f 100644
--- a/tests/tests/telecom/src/android/telecom/cts/PhoneAccountOperationsTest.java
+++ b/tests/tests/telecom/src/android/telecom/cts/PhoneAccountOperationsTest.java
@@ -74,6 +74,9 @@
@Override
protected void tearDown() throws Exception {
+ if (!TestUtils.shouldTestTelecom(mContext)) {
+ return;
+ }
mTelecomManager.unregisterPhoneAccount(TEST_PHONE_ACCOUNT_HANDLE);
PhoneAccount retrievedPhoneAccount = mTelecomManager.getPhoneAccount(
TEST_PHONE_ACCOUNT_HANDLE);
diff --git a/tests/tests/telecom/src/android/telecom/cts/RemoteConferenceTest.java b/tests/tests/telecom/src/android/telecom/cts/RemoteConferenceTest.java
index d14372e..3fc65ea 100644
--- a/tests/tests/telecom/src/android/telecom/cts/RemoteConferenceTest.java
+++ b/tests/tests/telecom/src/android/telecom/cts/RemoteConferenceTest.java
@@ -62,14 +62,14 @@
protected void setUp() throws Exception {
super.setUp();
mContext = getInstrumentation().getContext();
- if (shouldTestTelecom(mContext)) {
+ if (mShouldTestTelecom) {
addRemoteConferenceCall();
verifyRemoteConferenceObject(mRemoteConferenceObject, mRemoteConference, mConference);
}
}
public void testRemoteConferenceCreate() {
- if (!shouldTestTelecom(mContext)) {
+ if (!mShouldTestTelecom) {
return;
}
final Call confCall = mInCallCallbacks.getService().getLastConferenceCall();
@@ -92,7 +92,7 @@
}
public void testRemoteConferenceSplit() {
- if (!shouldTestTelecom(mContext)) {
+ if (!mShouldTestTelecom) {
return;
}
final Call confCall = mInCallCallbacks.getService().getLastConferenceCall();
@@ -114,7 +114,7 @@
}
public void testRemoteConferenceHoldAndUnhold() {
- if (!shouldTestTelecom(mContext)) {
+ if (!mShouldTestTelecom) {
return;
}
final Call confCall = mInCallCallbacks.getService().getLastConferenceCall();
@@ -146,7 +146,7 @@
}
public void testRemoteConferenceMergeAndSwap() {
- if (!shouldTestTelecom(mContext)) {
+ if (!mShouldTestTelecom) {
return;
}
final Call confCall = mInCallCallbacks.getService().getLastConferenceCall();
@@ -178,7 +178,7 @@
}
public void testRemoteConferenceDTMFTone() {
- if (!shouldTestTelecom(mContext)) {
+ if (!mShouldTestTelecom) {
return;
}
final Call confCall = mInCallCallbacks.getService().getLastConferenceCall();
@@ -201,7 +201,7 @@
}
public void testRemoteConferenceCallbacks_StateChange() {
- if (!shouldTestTelecom(mContext)) {
+ if (!mShouldTestTelecom) {
return;
}
Handler handler = setupRemoteConferenceCallbacksTest();
@@ -227,7 +227,7 @@
}
public void testRemoteConferenceCallbacks_Disconnect() {
- if (!shouldTestTelecom(mContext)) {
+ if (!mShouldTestTelecom) {
return;
}
Handler handler = setupRemoteConferenceCallbacksTest();
@@ -254,7 +254,7 @@
}
public void testRemoteConferenceCallbacks_ConnectionAdd() {
- if (!shouldTestTelecom(mContext)) {
+ if (!mShouldTestTelecom) {
return;
}
Handler handler = setupRemoteConferenceCallbacksTest();
@@ -285,7 +285,7 @@
}
public void testRemoteConferenceCallbacks_ConnectionRemove() {
- if (!shouldTestTelecom(mContext)) {
+ if (!mShouldTestTelecom) {
return;
}
Handler handler = setupRemoteConferenceCallbacksTest();
@@ -317,7 +317,7 @@
}
public void testRemoteConferenceCallbacks_ConnectionCapabilities() {
- if (!shouldTestTelecom(mContext)) {
+ if (!mShouldTestTelecom) {
return;
}
Handler handler = setupRemoteConferenceCallbacksTest();
@@ -345,7 +345,7 @@
}
public void testRemoteConferenceCallbacks_ConferenceableConnections() {
- if (!shouldTestTelecom(mContext)) {
+ if (!mShouldTestTelecom) {
return;
}
Handler handler = setupRemoteConferenceCallbacksTest();
@@ -380,7 +380,7 @@
}
public void testRemoteConferenceCallbacks_Destroy() {
- if (!shouldTestTelecom(mContext)) {
+ if (!mShouldTestTelecom) {
return;
}
Handler handler = setupRemoteConferenceCallbacksTest();
@@ -404,7 +404,7 @@
}
public void testRemoteConferenceCallbacks_Extras() {
- if (!shouldTestTelecom(mContext)) {
+ if (!mShouldTestTelecom) {
return;
}
Handler handler = setupRemoteConferenceCallbacksTest();
diff --git a/tests/tests/telecom/src/android/telecom/cts/RemoteConnectionTest.java b/tests/tests/telecom/src/android/telecom/cts/RemoteConnectionTest.java
index 9863c11..79fb592 100644
--- a/tests/tests/telecom/src/android/telecom/cts/RemoteConnectionTest.java
+++ b/tests/tests/telecom/src/android/telecom/cts/RemoteConnectionTest.java
@@ -55,7 +55,7 @@
RemoteConnection mRemoteConnectionObject;
public void testRemoteConnectionOutgoingCall() {
- if (!shouldTestTelecom(mContext)) {
+ if (!mShouldTestTelecom) {
return;
}
addRemoteConnectionOutgoingCall();
@@ -92,7 +92,7 @@
}
public void testRemoteConnectionIncomingCallAccept() {
- if (!shouldTestTelecom(mContext)) {
+ if (!mShouldTestTelecom) {
return;
}
addRemoteConnectionIncomingCall();
@@ -113,7 +113,7 @@
}
public void testRemoteConnectionIncomingCallReject() {
- if (!shouldTestTelecom(mContext)) {
+ if (!mShouldTestTelecom) {
return;
}
addRemoteConnectionIncomingCall();
@@ -134,7 +134,7 @@
}
public void testRemoteConnectionDTMFTone() {
- if (!shouldTestTelecom(mContext)) {
+ if (!mShouldTestTelecom) {
return;
}
addRemoteConnectionIncomingCall();
@@ -160,7 +160,7 @@
}
public void testRemoteConnectionCallbacks_StateChange() {
- if (!shouldTestTelecom(mContext)) {
+ if (!mShouldTestTelecom) {
return;
}
@@ -186,7 +186,7 @@
}
public void testRemoteConnectionCallbacks_RingbackRequest() {
- if (!shouldTestTelecom(mContext)) {
+ if (!mShouldTestTelecom) {
return;
}
@@ -212,7 +212,7 @@
}
public void testRemoteConnectionCallbacks_ConnectionCapabilities() {
- if (!shouldTestTelecom(mContext)) {
+ if (!mShouldTestTelecom) {
return;
}
@@ -242,7 +242,7 @@
}
public void testRemoteConnectionCallbacks_PostDialWait() {
- if (!shouldTestTelecom(mContext)) {
+ if (!mShouldTestTelecom) {
return;
}
@@ -270,7 +270,7 @@
}
public void testRemoteConnectionCallbacks_PostDialChar() {
- if (!shouldTestTelecom(mContext)) {
+ if (!mShouldTestTelecom) {
return;
}
@@ -289,7 +289,7 @@
};
mRemoteConnectionObject.registerCallback(callback, handler);
char postDialChar = '3';
- mRemoteConnection.setNextPostDialChar(postDialChar);
+ ((Connection) mRemoteConnection).setNextPostDialChar(postDialChar);
callbackInvoker.waitForCount(1, WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
assertEquals(mRemoteConnectionObject, callbackInvoker.getArgs(0)[0]);
assertEquals(postDialChar, callbackInvoker.getArgs(0)[1]);
@@ -297,7 +297,7 @@
}
public void testRemoteConnectionCallbacks_VoipAudio() {
- if (!shouldTestTelecom(mContext)) {
+ if (!mShouldTestTelecom) {
return;
}
@@ -323,7 +323,7 @@
}
public void testRemoteConnectionCallbacks_StatusHints() {
- if (!shouldTestTelecom(mContext)) {
+ if (!mShouldTestTelecom) {
return;
}
@@ -350,7 +350,7 @@
}
public void testRemoteConnectionCallbacks_AddressChange() {
- if (!shouldTestTelecom(mContext)) {
+ if (!mShouldTestTelecom) {
return;
}
@@ -379,7 +379,7 @@
}
public void testRemoteConnectionCallbacks_CallerDisplayName() {
- if (!shouldTestTelecom(mContext)) {
+ if (!mShouldTestTelecom) {
return;
}
@@ -408,7 +408,7 @@
}
public void testRemoteConnectionCallbacks_VideoState() {
- if (!shouldTestTelecom(mContext)) {
+ if (!mShouldTestTelecom) {
return;
}
@@ -434,7 +434,7 @@
}
public void testRemoteConnectionCallbacks_ConferenceableConnections() {
- if (!shouldTestTelecom(mContext)) {
+ if (!mShouldTestTelecom) {
return;
}
@@ -474,7 +474,7 @@
}
public void testRemoteConnectionCallbacks_VideoProvider() {
- if (!shouldTestTelecom(mContext)) {
+ if (!mShouldTestTelecom) {
return;
}
@@ -502,7 +502,7 @@
}
public void testRemoteConnectionCallbacks_Extras() {
- if (!shouldTestTelecom(mContext)) {
+ if (!mShouldTestTelecom) {
return;
}
@@ -531,7 +531,7 @@
}
public void testRemoteConnectionCallbacks_Disconnect() {
- if (!shouldTestTelecom(mContext)) {
+ if (!mShouldTestTelecom) {
return;
}
@@ -560,7 +560,7 @@
}
public void testRemoteConnectionCallbacks_Destroy() {
- if (!shouldTestTelecom(mContext)) {
+ if (!mShouldTestTelecom) {
return;
}
@@ -585,7 +585,7 @@
}
public void testRemoteConnectionVideoCallbacks_SessionModify() {
- if (!shouldTestTelecom(mContext)) {
+ if (!mShouldTestTelecom) {
return;
}
@@ -627,7 +627,7 @@
}
public void testRemoteConnectionVideoCallbacks_SessionEvent() {
- if (!shouldTestTelecom(mContext)) {
+ if (!mShouldTestTelecom) {
return;
}
@@ -655,7 +655,7 @@
}
public void testRemoteConnectionVideoCallbacks_PeerDimensions() {
- if (!shouldTestTelecom(mContext)) {
+ if (!mShouldTestTelecom) {
return;
}
@@ -686,7 +686,7 @@
}
public void testRemoteConnectionVideoCallbacks_CallDataUsage() {
- if (!shouldTestTelecom(mContext)) {
+ if (!mShouldTestTelecom) {
return;
}
@@ -715,7 +715,7 @@
}
public void testRemoteConnectionVideoCallbacks_CameraCapabilities() {
- if (!shouldTestTelecom(mContext)) {
+ if (!mShouldTestTelecom) {
return;
}
@@ -746,7 +746,7 @@
}
public void testRemoteConnectionVideoCallbacks_VideoQuality() {
- if (!shouldTestTelecom(mContext)) {
+ if (!mShouldTestTelecom) {
return;
}
@@ -775,7 +775,7 @@
}
public void testRemoteConnectionVideo_RequestCallDataUsage() {
- if (!shouldTestTelecom(mContext)) {
+ if (!mShouldTestTelecom) {
return;
}
@@ -810,7 +810,7 @@
}
public void testRemoteConnectionVideo_RequestCameraCapabilities() {
- if (!shouldTestTelecom(mContext)) {
+ if (!mShouldTestTelecom) {
return;
}
@@ -848,7 +848,7 @@
}
public void testRemoteConnectionVideo_SendSessionModifyRequest() {
- if (!shouldTestTelecom(mContext)) {
+ if (!mShouldTestTelecom) {
return;
}
@@ -889,7 +889,7 @@
}
public void testRemoteConnectionVideo_SendSessionModifyResponse() {
- if (!shouldTestTelecom(mContext)) {
+ if (!mShouldTestTelecom) {
return;
}
@@ -935,7 +935,7 @@
}
public void testRemoteConnectionVideo_SetCamera() {
- if (!shouldTestTelecom(mContext)) {
+ if (!mShouldTestTelecom) {
return;
}
@@ -975,7 +975,7 @@
}
public void testRemoteConnectionVideo_SetDeviceOrientation() {
- if (!shouldTestTelecom(mContext)) {
+ if (!mShouldTestTelecom) {
return;
}
@@ -998,7 +998,7 @@
}
public void testRemoteConnectionVideo_SetDisplaySurface() {
- if (!shouldTestTelecom(mContext)) {
+ if (!mShouldTestTelecom) {
return;
}
@@ -1021,7 +1021,7 @@
}
public void testRemoteConnectionVideo_SetPauseImage() {
- if (!shouldTestTelecom(mContext)) {
+ if (!mShouldTestTelecom) {
return;
}
@@ -1044,7 +1044,7 @@
}
public void testRemoteConnectionVideo_SetPreviewSurface() {
- if (!shouldTestTelecom(mContext)) {
+ if (!mShouldTestTelecom) {
return;
}
@@ -1067,7 +1067,7 @@
}
public void testRemoteConnectionVideo_SetZoom() {
- if (!shouldTestTelecom(mContext)) {
+ if (!mShouldTestTelecom) {
return;
}
diff --git a/tests/tests/telecom/src/android/telecom/cts/VideoCallTest.java b/tests/tests/telecom/src/android/telecom/cts/VideoCallTest.java
index e3ba6ef..fbfa998 100644
--- a/tests/tests/telecom/src/android/telecom/cts/VideoCallTest.java
+++ b/tests/tests/telecom/src/android/telecom/cts/VideoCallTest.java
@@ -47,7 +47,7 @@
@Override
protected void setUp() throws Exception {
super.setUp();
- if (TestUtils.shouldTestTelecom(mContext)) {
+ if (mShouldTestTelecom) {
setupConnectionService(null, FLAG_REGISTER | FLAG_ENABLE);
}
}
@@ -56,6 +56,9 @@
* Tests ability to start a 2-way video call and retrieve its video state.
*/
public void testMakeTwoWayVideoCall() {
+ if (!mShouldTestTelecom) {
+ return;
+ }
placeAndVerifyCall(VideoProfile.STATE_BIDIRECTIONAL);
final MockConnection connection = verifyConnectionForOutgoingCall();
@@ -75,6 +78,10 @@
* Tests ability to start a 1-way video call and retrieve its video state.
*/
public void testMakeOneWayVideoCall() {
+ if (!mShouldTestTelecom) {
+ return;
+ }
+
placeAndVerifyCall(VideoProfile.STATE_TX_ENABLED);
verifyConnectionForOutgoingCall();
@@ -89,6 +96,10 @@
* Tests ability to upgrade an audio-only call to a video call.
*/
public void testUpgradeToVideo() {
+ if (!mShouldTestTelecom) {
+ return;
+ }
+
placeAndVerifyCall(VideoProfile.STATE_AUDIO_ONLY);
verifyConnectionForOutgoingCall();
@@ -109,6 +120,10 @@
* Tests ability to receive a session modification request.
*/
public void testReceiveSessionModifyRequest() {
+ if (!mShouldTestTelecom) {
+ return;
+ }
+
placeAndVerifyCall(VideoProfile.STATE_AUDIO_ONLY);
final MockConnection connection = verifyConnectionForOutgoingCall();
@@ -134,6 +149,10 @@
* Tests ability to send a session modification response.
*/
public void testSendSessionModifyResponse() {
+ if (!mShouldTestTelecom) {
+ return;
+ }
+
placeAndVerifyCall(VideoProfile.STATE_AUDIO_ONLY);
final MockConnection connection = verifyConnectionForOutgoingCall();
@@ -156,6 +175,10 @@
* the call.
*/
public void testVideoCallDelayProvider() {
+ if (!mShouldTestTelecom) {
+ return;
+ }
+
// Don't create video provider when call is created initially; we will do this later.
try {
connectionService.setCreateVideoProvider(false);
@@ -187,6 +210,10 @@
* back in response.
*/
public void testChangeCamera() {
+ if (!mShouldTestTelecom) {
+ return;
+ }
+
placeAndVerifyCall(VideoProfile.STATE_BIDIRECTIONAL);
verifyConnectionForOutgoingCall();
@@ -208,6 +235,10 @@
* Tests ability to request the camera capabilities from the video provider.
*/
public void testRequestCameraCapabilities() {
+ if (!mShouldTestTelecom) {
+ return;
+ }
+
placeAndVerifyCall(VideoProfile.STATE_BIDIRECTIONAL);
verifyConnectionForOutgoingCall();
@@ -232,6 +263,10 @@
* Tests ability to request data usage from the video provider.
*/
public void testRequestDataUsage() {
+ if (!mShouldTestTelecom) {
+ return;
+ }
+
placeAndVerifyCall(VideoProfile.STATE_BIDIRECTIONAL);
verifyConnectionForOutgoingCall();
@@ -249,6 +284,10 @@
* Tests ability to receive changes to the video quality from the video provider.
*/
public void testReceiveVideoQuality() {
+ if (!mShouldTestTelecom) {
+ return;
+ }
+
placeAndVerifyCall(VideoProfile.STATE_BIDIRECTIONAL);
final MockConnection connection = verifyConnectionForOutgoingCall();
@@ -281,6 +320,10 @@
* Tests ability to receive call session events from the video provider.
*/
public void testReceiveCallSessionEvent() {
+ if (!mShouldTestTelecom) {
+ return;
+ }
+
placeAndVerifyCall(VideoProfile.STATE_BIDIRECTIONAL);
final MockConnection connection = verifyConnectionForOutgoingCall();
@@ -303,6 +346,10 @@
* Tests ability to receive changes to the peer dimensions from the video provider.
*/
public void testReceivePeerDimensionChange() {
+ if (!mShouldTestTelecom) {
+ return;
+ }
+
placeAndVerifyCall(VideoProfile.STATE_BIDIRECTIONAL);
final MockConnection connection = verifyConnectionForOutgoingCall();
@@ -324,6 +371,10 @@
* Tests ability to set the device orientation via the provider.
*/
public void testSetDeviceOrientation() {
+ if (!mShouldTestTelecom) {
+ return;
+ }
+
placeAndVerifyCall(VideoProfile.STATE_BIDIRECTIONAL);
final MockConnection connection = verifyConnectionForOutgoingCall();
@@ -342,6 +393,10 @@
* Tests ability to set the preview surface via the provider.
*/
public void testSetPreviewSurface() {
+ if (!mShouldTestTelecom) {
+ return;
+ }
+
placeAndVerifyCall(VideoProfile.STATE_BIDIRECTIONAL);
final MockConnection connection = verifyConnectionForOutgoingCall();
@@ -365,6 +420,10 @@
* Tests ability to set the display surface via the provider.
*/
public void testSetDisplaySurface() {
+ if (!mShouldTestTelecom) {
+ return;
+ }
+
placeAndVerifyCall(VideoProfile.STATE_BIDIRECTIONAL);
final MockConnection connection = verifyConnectionForOutgoingCall();
@@ -388,6 +447,10 @@
* Tests ability to set the camera zoom via the provider.
*/
public void testSetZoom() {
+ if (!mShouldTestTelecom) {
+ return;
+ }
+
placeAndVerifyCall(VideoProfile.STATE_BIDIRECTIONAL);
final MockConnection connection = verifyConnectionForOutgoingCall();
diff --git a/tests/tests/telecom/src/android/telecom/cts/WiredHeadsetTest.java b/tests/tests/telecom/src/android/telecom/cts/WiredHeadsetTest.java
index 697b191..466a90b 100644
--- a/tests/tests/telecom/src/android/telecom/cts/WiredHeadsetTest.java
+++ b/tests/tests/telecom/src/android/telecom/cts/WiredHeadsetTest.java
@@ -30,7 +30,7 @@
@Override
protected void setUp() throws Exception {
super.setUp();
- if (TestUtils.shouldTestTelecom(mContext)) {
+ if (mShouldTestTelecom) {
setupConnectionService(null, FLAG_REGISTER | FLAG_ENABLE);
}
}
@@ -45,6 +45,10 @@
}
public void testIncomingCallShortPress_acceptsCall() throws Exception {
+ if (!mShouldTestTelecom) {
+ return;
+ }
+
addAndVerifyNewIncomingCall(getTestNumber(), null);
final MockConnection connection = verifyConnectionForIncomingCall();
@@ -58,6 +62,10 @@
}
public void testIncomingCallLongPress_rejectsCall() throws Exception {
+ if (!mShouldTestTelecom) {
+ return;
+ }
+
addAndVerifyNewIncomingCall(getTestNumber(), null);
final MockConnection connection = verifyConnectionForIncomingCall();
@@ -71,6 +79,10 @@
}
public void testInCallShortPress_togglesMute() throws Exception {
+ if (!mShouldTestTelecom) {
+ return;
+ }
+
placeAndVerifyCall();
final MockConnection connection = verifyConnectionForOutgoingCall();
final MockInCallService incallService = mInCallCallbacks.getService();
@@ -89,6 +101,10 @@
}
public void testInCallLongPress_hangupCall() throws Exception {
+ if (!mShouldTestTelecom) {
+ return;
+ }
+
placeAndVerifyCall();
final MockConnection connection = verifyConnectionForOutgoingCall();
@@ -104,6 +120,10 @@
}
public void testStartCallWithSpeakerphoneNotProvided_SpeakerphoneOffByDefault() {
+ if (!mShouldTestTelecom) {
+ return;
+ }
+
placeAndVerifyCall();
verifyConnectionForOutgoingCall();
assertAudioRoute(mInCallCallbacks.getService(), CallAudioState.ROUTE_EARPIECE);
diff --git a/tests/tests/telephony/src/android/telephony/cts/TelephonyManagerTest.java b/tests/tests/telephony/src/android/telephony/cts/TelephonyManagerTest.java
index ce3fe78..41fe996 100644
--- a/tests/tests/telephony/src/android/telephony/cts/TelephonyManagerTest.java
+++ b/tests/tests/telephony/src/android/telephony/cts/TelephonyManagerTest.java
@@ -177,7 +177,7 @@
assertTrue("Phone count should be > 0", phoneCount > 0);
break;
case TelephonyManager.PHONE_TYPE_NONE:
- assertTrue("Phone count should be 0", phoneCount == 0);
+ assertTrue("Phone count should be 0", phoneCount == 0 || phoneCount == 1);
break;
default:
throw new IllegalArgumentException("Did you add a new phone type? " + phoneType);
diff --git a/tests/tests/webkit/src/android/webkit/cts/WebSettingsTest.java b/tests/tests/webkit/src/android/webkit/cts/WebSettingsTest.java
index e6b656f..592e308 100644
--- a/tests/tests/webkit/src/android/webkit/cts/WebSettingsTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/WebSettingsTest.java
@@ -95,7 +95,7 @@
* brackets are optional):
* <p/>
* Mozilla/5.0 (Linux;[ U;] Android <version>;[ <language>-<country>;]
- * [<devicemodel>;] Build/<buildID>[; wv]) AppleWebKit/<major>.<minor> (KHTML, like Gecko)
+ * [<devicemodel>;] Build/<buildID>; wv) AppleWebKit/<major>.<minor> (KHTML, like Gecko)
* Version/<major>.<minor> Chrome/<major>.<minor>.<branch>.<build>[ Mobile]
* Safari/<major>.<minor>
*/
@@ -107,7 +107,7 @@
Log.i(LOG_TAG, String.format("Checking user agent string %s", actualUserAgentString));
final String patternString =
"Mozilla/5\\.0 \\(Linux;( U;)? Android ([^;]+);( (\\w+)-(\\w+);)?" +
- "\\s?(.*)\\sBuild/(.+?)(; wv)?\\) AppleWebKit/(\\d+)\\.(\\d+) " +
+ "\\s?(.*)\\sBuild/(.+); wv\\) AppleWebKit/(\\d+)\\.(\\d+) " +
"\\(KHTML, like Gecko\\) " +
"Version/\\d+\\.\\d+ Chrome/\\d+\\.\\d+\\.\\d+\\.\\d+( Mobile)? " +
"Safari/(\\d+)\\.(\\d+)";
@@ -119,12 +119,11 @@
// 5 - language
// 6 - device model (optional)
// 7 - build ID
- // 8 - WebView identifier "; wv" (optional)
- // 9 - AppleWebKit major version number
- // 10 - AppleWebKit minor version number
- // 11 - " Mobile" string (optional)
- // 12 - Safari major version number
- // 13 - Safari minor version number
+ // 8 - AppleWebKit major version number
+ // 9 - AppleWebKit minor version number
+ // 10 - " Mobile" string (optional)
+ // 11 - Safari major version number
+ // 12 - Safari minor version number
Log.i(LOG_TAG, String.format("Trying to match pattern %s", patternString));
final Pattern userAgentExpr = Pattern.compile(patternString);
Matcher patternMatcher = userAgentExpr.matcher(actualUserAgentString);
diff --git a/tests/tests/widget/src/android/widget/cts/ListViewTest.java b/tests/tests/widget/src/android/widget/cts/ListViewTest.java
index f6f490f..6c62be4 100644
--- a/tests/tests/widget/src/android/widget/cts/ListViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ListViewTest.java
@@ -431,6 +431,7 @@
mInstrumentation.runOnMainSync(new Runnable() {
public void run() {
mListView.setDivider(d);
+ mListView.requestLayout();
}
});
mInstrumentation.waitForIdleSync();
@@ -440,6 +441,7 @@
mInstrumentation.runOnMainSync(new Runnable() {
public void run() {
mListView.setDividerHeight(10);
+ mListView.requestLayout();
}
});
mInstrumentation.waitForIdleSync();
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/CtsTest.java b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/CtsTest.java
index 01f148ae..d74cce5 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/CtsTest.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/CtsTest.java
@@ -289,9 +289,8 @@
@Override
public void testFailed(TestIdentifier test, String trace) {
super.testFailed(test, trace);
- // sleep a small amount of time to ensure test failure stack trace makes it into logcat
- // capture
- RunUtil.getDefault().sleep(10);
+ // sleep 2s to ensure test failure stack trace makes it into logcat capture
+ RunUtil.getDefault().sleep(2 * 1000);
InputStreamSource logSource = mDevice.getLogcat(mNumLogcatBytes);
super.testLog(String.format("logcat-%s_%s", test.getClassName(), test.getTestName()),
LogDataType.TEXT, logSource);
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/DeqpTestRunner.java b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/DeqpTestRunner.java
index 12adb9f..43aaf98 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/DeqpTestRunner.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/DeqpTestRunner.java
@@ -64,7 +64,6 @@
new BatchRunConfiguration("rgba8888d24s8", "unspecified", "window");
private static final int UNRESPOSIVE_CMD_TIMEOUT_MS = 60000; // one minute
- private static final int FILE_REMOVE_RETRY_INTERVAL = 2000; // 2 seconds
private final String mPackageName;
private final String mName;
@@ -79,7 +78,6 @@
private Set<String> mDeviceFeatures;
private Map<String, Boolean> mConfigQuerySupportCache = new HashMap<>();
private IRunUtil mRunUtil = RunUtil.getDefault();
- private ISleepProvider mSleepProvider = new SleepProvider();
private IRecovery mDeviceRecovery = new Recovery();
{
@@ -154,15 +152,6 @@
}
/**
- * Sets the sleep provider DeqpTestRunner works on.
- *
- * Exposed for unit testing.
- */
- public void setSleepProvider(ISleepProvider sleepProvider) {
- mSleepProvider = sleepProvider;
- }
-
- /**
* Set IRunUtil.
*
* Exposed for unit testing.
@@ -777,12 +766,12 @@
public void recoverConnectionRefused() throws DeviceNotAvailableException;
/**
- * Tries to recover device after abnormal termination of a command or a test run execution
- * or link failure.
+ * Tries to recover device after abnormal execution termination or link failure.
*
+ * @param progressedSinceLastCall true if test execution has progressed since last call
* @throws DeviceNotAvailableException if recovery did not succeed
*/
- public void recoverCommandNotCompleted() throws DeviceNotAvailableException;
+ public void recoverComLinkKilled() throws DeviceNotAvailableException;
};
/**
@@ -875,7 +864,7 @@
* {@inheritDoc}
*/
@Override
- public void recoverCommandNotCompleted() throws DeviceNotAvailableException {
+ public void recoverComLinkKilled() throws DeviceNotAvailableException {
switch (mState) {
case WAIT:
// First failure, just try to wait and try again
@@ -890,10 +879,10 @@
killDeqpProcess();
} catch (DeviceNotAvailableException ex) {
// chain forward
- recoverCommandNotCompleted();
+ recoverComLinkKilled();
} catch (ProcessKillFailureException ex) {
// chain forward
- recoverCommandNotCompleted();
+ recoverComLinkKilled();
}
break;
@@ -907,10 +896,10 @@
killDeqpProcess();
} catch (DeviceNotAvailableException ex) {
// chain forward
- recoverCommandNotCompleted();
+ recoverComLinkKilled();
} catch (ProcessKillFailureException ex) {
// chain forward
- recoverCommandNotCompleted();
+ recoverComLinkKilled();
}
break;
@@ -923,7 +912,7 @@
rebootDevice();
} catch (DeviceNotAvailableException ex) {
// chain forward
- recoverCommandNotCompleted();
+ recoverComLinkKilled();
}
break;
@@ -1408,51 +1397,6 @@
}
}
- private static final class FileRecreateFailedException extends Exception {
- };
-
- /**
- * Creates a log file suitable for writing.
- *
- * Creates an empty file that is suitable for writing. If target file already exists, it will
- * first be removed and then recreated. This delete-recreate cycle should guarantee that the
- * target file is always writable and is not affected by file-access flags of the pre-existing
- * file.
- *
- * Precreating a file in the runner makes detecting file-access issues faster and more
- * reliable. It also avoids issues caused by sdcard FUSE spuriously preventing file creation.
- */
- private void precreateLogFile() throws DeviceNotAvailableException,
- FileRecreateFailedException {
- final int NUM_ATTEMPTS = 4;
- int attemptNum = 0;
- for (;;) {
- mDevice.executeShellCommand("rm " + LOG_FILE_NAME);
- ++attemptNum;
-
- if (!mDevice.doesFileExist(LOG_FILE_NAME)) {
- // yay, remove works like it should
- break;
- } else if (attemptNum < NUM_ATTEMPTS) {
- // wait if we failed
- CLog.w("Remote file removal failed, retrying...");
- mSleepProvider.sleep(FILE_REMOVE_RETRY_INTERVAL);
- } else {
- // Bail
- CLog.e("Could not delete a remote file.");
- throw new FileRecreateFailedException();
- }
- }
-
- // create & truncate and make world read-writable
- mDevice.pushString("", LOG_FILE_NAME);
-
- if (!mDevice.doesFileExist(LOG_FILE_NAME)) {
- CLog.e("Could not precreate log file.");
- throw new FileRecreateFailedException();
- }
- }
-
/**
* Runs one execution pass over the given batch.
*
@@ -1468,8 +1412,8 @@
final String testCases = generateTestCaseTrie(batch.tests);
- // Caselist file cannot linger.
mDevice.executeShellCommand("rm " + CASE_LIST_FILE_NAME);
+ mDevice.executeShellCommand("rm " + LOG_FILE_NAME);
mDevice.pushString(testCases + "\n", CASE_LIST_FILE_NAME);
final String instrumentationName =
@@ -1499,9 +1443,6 @@
Throwable interruptingError = null;
try {
- // we might have lingering log file from a previous dirty run and it might be somehow
- // locked (details unknown). Make sure it's writable when test is run.
- precreateLogFile();
executeShellCommandAndReadOutput(command, parser);
} catch (Throwable ex) {
interruptingError = ex;
@@ -1521,9 +1462,7 @@
if (interruptingError instanceof AdbComLinkOpenError) {
mDeviceRecovery.recoverConnectionRefused();
} else if (interruptingError instanceof AdbComLinkKilledError) {
- mDeviceRecovery.recoverCommandNotCompleted();
- } else if (interruptingError instanceof FileRecreateFailedException) {
- mDeviceRecovery.recoverCommandNotCompleted();
+ mDeviceRecovery.recoverComLinkKilled();
} else if (interruptingError instanceof RunInterruptedException) {
// external run interruption request. Terminate immediately.
throw (RunInterruptedException)interruptingError;
@@ -1534,7 +1473,7 @@
// recoverXXX did not throw => recovery succeeded
} else if (!parser.wasSuccessful()) {
- mDeviceRecovery.recoverCommandNotCompleted();
+ mDeviceRecovery.recoverComLinkKilled();
// recoverXXX did not throw => recovery succeeded
}
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/TestPackageDef.java b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/TestPackageDef.java
index f276f1d..12c3ddd 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/TestPackageDef.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/TestPackageDef.java
@@ -308,9 +308,6 @@
instrTest.setRunName(mAppPackageName);
instrTest.setPackageName(mAppNameSpace);
instrTest.setRunnerName(mRunner);
- instrTest.setTestPackageName(mTestPackageName);
- instrTest.setClassName(mClassName);
- instrTest.setMethodName(mMethodName);
instrTest.setAbi(mAbi);
instrTest.setTestsToRun(mTests, false
/* force batch mode off to always run using testFile */);
diff --git a/tools/tradefed-host/tests/src/com/android/cts/tradefed/testtype/DeqpTestRunnerTest.java b/tools/tradefed-host/tests/src/com/android/cts/tradefed/testtype/DeqpTestRunnerTest.java
index 4c879b4..7ec09c9 100644
--- a/tools/tradefed-host/tests/src/com/android/cts/tradefed/testtype/DeqpTestRunnerTest.java
+++ b/tools/tradefed-host/tests/src/com/android/cts/tradefed/testtype/DeqpTestRunnerTest.java
@@ -106,7 +106,7 @@
* {@inheritDoc}
*/
@Override
- public void recoverCommandNotCompleted() throws DeviceNotAvailableException {
+ public void recoverComLinkKilled() throws DeviceNotAvailableException {
}
};
@@ -1717,14 +1717,11 @@
EasyMock.expect(mockDevice.executeShellCommand(EasyMock.eq("rm " + CASE_LIST_FILE_NAME)))
.andReturn("").once();
- EasyMock.expect(mockDevice.pushString("{dEQP-GLES3{loss{instance}}}\n", CASE_LIST_FILE_NAME))
- .andReturn(true).once();
-
EasyMock.expect(mockDevice.executeShellCommand(EasyMock.eq("rm " + LOG_FILE_NAME)))
.andReturn("").once();
- EasyMock.expect(mockDevice.doesFileExist(LOG_FILE_NAME)).andReturn(false).once();
- EasyMock.expect(mockDevice.pushString("", LOG_FILE_NAME)).andReturn(true).once();
- EasyMock.expect(mockDevice.doesFileExist(LOG_FILE_NAME)).andReturn(true).once();
+
+ EasyMock.expect(mockDevice.pushString("{dEQP-GLES3{loss{instance}}}\n", CASE_LIST_FILE_NAME))
+ .andReturn(true).once();
String command = String.format(
"am instrument %s -w -e deqpLogFileName \"%s\" -e deqpCmdLine \""
@@ -1756,10 +1753,10 @@
});
if (!recoverySuccessful) {
- mockRecovery.recoverCommandNotCompleted();
+ mockRecovery.recoverComLinkKilled();
EasyMock.expectLastCall().andThrow(new DeviceNotAvailableException()).once();
} else {
- mockRecovery.recoverCommandNotCompleted();
+ mockRecovery.recoverComLinkKilled();
EasyMock.expectLastCall().once();
// retry running config B
@@ -1863,7 +1860,7 @@
recovery.recoverConnectionRefused();
break;
case FAIL_LINK_KILLED:
- recovery.recoverCommandNotCompleted();
+ recovery.recoverComLinkKilled();
break;
}
}
@@ -2144,7 +2141,7 @@
orderedControl.replay();
recovery.setDevice(mockDevice);
recovery.setSleepProvider(mockSleepProvider);
- recovery.recoverCommandNotCompleted();
+ recovery.recoverComLinkKilled();
orderedControl.verify();
}
@@ -2315,216 +2312,16 @@
EasyMock.verify(mockDevice, mockIDevice);
}
- /**
- * Test log file precreate persistent failure
- */
- public void testPrecreate_persistentFailure() throws Exception {
- final TestIdentifier testId = new TestIdentifier("dEQP-GLES3.precreate", "test");
- final String testTrie = "{dEQP-GLES3{precreate{test}}}";
-
- Collection<TestIdentifier> tests = new ArrayList<TestIdentifier>();
- tests.add(testId);
-
- Map<TestIdentifier, List<Map<String, String>>> instance = new HashMap<>();
- instance.put(testId, DEFAULT_INSTANCE_ARGS);
-
- ITestInvocationListener mockListener
- = EasyMock.createStrictMock(ITestInvocationListener.class);
- ITestDevice mockDevice = EasyMock.createMock(ITestDevice.class);
- IDevice mockIDevice = EasyMock.createMock(IDevice.class);
- DeqpTestRunner.ISleepProvider mockSleepProvider =
- EasyMock.createMock(DeqpTestRunner.ISleepProvider.class);
- DeqpTestRunner.IRecovery mockRecovery =
- EasyMock.createMock(DeqpTestRunner.IRecovery.class);
-
- DeqpTestRunner deqpTest = new DeqpTestRunner(NAME, NAME, tests, instance);
- deqpTest.setAbi(UnitTests.ABI);
- deqpTest.setDevice(mockDevice);
- deqpTest.setBuildHelper(new StubCtsBuildHelper());
- deqpTest.setSleepProvider(mockSleepProvider);
- deqpTest.setRecovery(mockRecovery);
-
- mockRecovery.setDevice(mockDevice);
- EasyMock.expectLastCall().atLeastOnce();
-
- int version = 3 << 16;
- EasyMock.expect(mockDevice.getProperty("ro.opengles.version"))
- .andReturn(Integer.toString(version)).atLeastOnce();
-
- EasyMock.expect(mockDevice.uninstallPackage(EasyMock.eq(DEQP_ONDEVICE_PKG))).
- andReturn("").once();
-
- EasyMock.expect(mockDevice.installPackage(EasyMock.<File>anyObject(),
- EasyMock.eq(true),
- EasyMock.eq(AbiUtils.createAbiFlag(UnitTests.ABI.getName())))).andReturn(null)
- .once();
-
- expectRenderConfigQuery(mockDevice,
- "--deqp-gl-config-name=rgba8888d24s8 --deqp-screen-rotation=unspecified "
- + "--deqp-surface-type=window --deqp-gl-major-version=3 "
- + "--deqp-gl-minor-version=0");
-
- EasyMock.expect(mockDevice.executeShellCommand(EasyMock.eq("rm " + CASE_LIST_FILE_NAME)))
- .andReturn("").once();
-
- EasyMock.expect(mockDevice.pushString(testTrie + "\n", CASE_LIST_FILE_NAME))
- .andReturn(true).once();
-
- // fail persistently...
- EasyMock.expect(mockDevice.executeShellCommand(EasyMock.eq("rm " + LOG_FILE_NAME)))
- .andReturn("").anyTimes();
- EasyMock.expect(mockDevice.doesFileExist(LOG_FILE_NAME)).andReturn(true).anyTimes();
- mockSleepProvider.sleep(EasyMock.gt(0));
- EasyMock.expectLastCall().anyTimes();
-
- // ..and when retries won't help, trigger recovery tactics
- mockRecovery.recoverCommandNotCompleted();
- EasyMock.expectLastCall().andThrow(new DeviceNotAvailableException()).once();
-
- mockListener.testRunStarted(ID, 1);
- EasyMock.expectLastCall().once();
-
- EasyMock.replay(mockDevice, mockIDevice);
- EasyMock.replay(mockListener);
- EasyMock.replay(mockSleepProvider);
- EasyMock.replay(mockRecovery);
- try {
- deqpTest.run(mockListener);
- fail("expected DeviceNotAvailableException");
- } catch (DeviceNotAvailableException ex) {
- // expected
- }
- EasyMock.verify(mockRecovery);
- EasyMock.verify(mockSleepProvider);
- EasyMock.verify(mockListener);
- EasyMock.verify(mockDevice, mockIDevice);
- }
-
- /**
- * Test log file precreate transient failure
- */
- public void testPrecreate_transientFailure() throws Exception {
- final TestIdentifier testId = new TestIdentifier("dEQP-GLES3.precreate", "test");
- final String testPath = "dEQP-GLES3.precreate.test";
- final String testTrie = "{dEQP-GLES3{precreate{test}}}";
- final String output = "INSTRUMENTATION_STATUS: dEQP-SessionInfo-Name=releaseName\r\n"
- + "INSTRUMENTATION_STATUS: dEQP-EventType=SessionInfo\r\n"
- + "INSTRUMENTATION_STATUS: dEQP-SessionInfo-Value=2014.x\r\n"
- + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
- + "INSTRUMENTATION_STATUS: dEQP-SessionInfo-Name=releaseId\r\n"
- + "INSTRUMENTATION_STATUS: dEQP-EventType=SessionInfo\r\n"
- + "INSTRUMENTATION_STATUS: dEQP-SessionInfo-Value=0xcafebabe\r\n"
- + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
- + "INSTRUMENTATION_STATUS: dEQP-SessionInfo-Name=targetName\r\n"
- + "INSTRUMENTATION_STATUS: dEQP-EventType=SessionInfo\r\n"
- + "INSTRUMENTATION_STATUS: dEQP-SessionInfo-Value=android\r\n"
- + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
- + "INSTRUMENTATION_STATUS: dEQP-EventType=BeginSession\r\n"
- + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
- + "INSTRUMENTATION_STATUS: dEQP-EventType=BeginTestCase\r\n"
- + "INSTRUMENTATION_STATUS: dEQP-BeginTestCase-TestCasePath=" + testPath + "\r\n"
- + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
- + "INSTRUMENTATION_STATUS: dEQP-TestCaseResult-Code=Pass\r\n"
- + "INSTRUMENTATION_STATUS: dEQP-TestCaseResult-Details=DetailPass\r\n"
- + "INSTRUMENTATION_STATUS: dEQP-EventType=TestCaseResult\r\n"
- + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
- + "INSTRUMENTATION_STATUS: dEQP-EventType=EndTestCase\r\n"
- + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
- + "INSTRUMENTATION_STATUS: dEQP-EventType=EndSession\r\n"
- + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
- + "INSTRUMENTATION_CODE: 0\r\n";
-
- Collection<TestIdentifier> tests = new ArrayList<TestIdentifier>();
- tests.add(testId);
-
- Map<TestIdentifier, List<Map<String, String>>> instance = new HashMap<>();
- instance.put(testId, DEFAULT_INSTANCE_ARGS);
-
- ITestInvocationListener mockListener
- = EasyMock.createStrictMock(ITestInvocationListener.class);
- ITestDevice mockDevice = EasyMock.createMock(ITestDevice.class);
- IDevice mockIDevice = EasyMock.createMock(IDevice.class);
- DeqpTestRunner.ISleepProvider mockSleepProvider =
- EasyMock.createMock(DeqpTestRunner.ISleepProvider.class);
-
- DeqpTestRunner deqpTest = new DeqpTestRunner(NAME, NAME, tests, instance);
- deqpTest.setAbi(UnitTests.ABI);
- deqpTest.setDevice(mockDevice);
- deqpTest.setBuildHelper(new StubCtsBuildHelper());
- deqpTest.setSleepProvider(mockSleepProvider);
-
- int version = 3 << 16;
- EasyMock.expect(mockDevice.getProperty("ro.opengles.version"))
- .andReturn(Integer.toString(version)).atLeastOnce();
-
- EasyMock.expect(mockDevice.uninstallPackage(EasyMock.eq(DEQP_ONDEVICE_PKG))).
- andReturn("").once();
-
- EasyMock.expect(mockDevice.installPackage(EasyMock.<File>anyObject(),
- EasyMock.eq(true),
- EasyMock.eq(AbiUtils.createAbiFlag(UnitTests.ABI.getName())))).andReturn(null)
- .once();
-
- expectRenderConfigQuery(mockDevice,
- "--deqp-gl-config-name=rgba8888d24s8 --deqp-screen-rotation=unspecified "
- + "--deqp-surface-type=window --deqp-gl-major-version=3 "
- + "--deqp-gl-minor-version=0");
-
- // fail once
- EasyMock.expect(mockDevice.executeShellCommand(EasyMock.eq("rm " + LOG_FILE_NAME)))
- .andReturn("").once();
- EasyMock.expect(mockDevice.doesFileExist(LOG_FILE_NAME)).andReturn(true).once();
- mockSleepProvider.sleep(EasyMock.gt(0));
- EasyMock.expectLastCall().once();
-
- String commandLine = String.format(
- "--deqp-caselist-file=%s --deqp-gl-config-name=rgba8888d24s8 "
- + "--deqp-screen-rotation=unspecified "
- + "--deqp-surface-type=window "
- + "--deqp-log-images=disable "
- + "--deqp-watchdog=enable",
- CASE_LIST_FILE_NAME);
-
- runInstrumentationLineAndAnswer(mockDevice, mockIDevice, testTrie, commandLine,
- output);
-
- EasyMock.expect(mockDevice.uninstallPackage(EasyMock.eq(DEQP_ONDEVICE_PKG))).
- andReturn("").once();
-
- mockListener.testRunStarted(ID, 1);
- EasyMock.expectLastCall().once();
-
- mockListener.testStarted(EasyMock.eq(testId));
- EasyMock.expectLastCall().once();
-
- mockListener.testEnded(EasyMock.eq(testId), EasyMock.<Map<String, String>>notNull());
- EasyMock.expectLastCall().once();
-
- mockListener.testRunEnded(EasyMock.anyLong(), EasyMock.<Map<String, String>>notNull());
- EasyMock.expectLastCall().once();
-
- EasyMock.replay(mockDevice, mockIDevice);
- EasyMock.replay(mockListener);
- EasyMock.replay(mockSleepProvider);
- deqpTest.run(mockListener);
- EasyMock.verify(mockSleepProvider);
- EasyMock.verify(mockListener);
- EasyMock.verify(mockDevice, mockIDevice);
- }
-
private void runInstrumentationLineAndAnswer(ITestDevice mockDevice, IDevice mockIDevice,
final String testTrie, final String cmd, final String output) throws Exception {
EasyMock.expect(mockDevice.executeShellCommand(EasyMock.eq("rm " + CASE_LIST_FILE_NAME)))
.andReturn("").once();
- EasyMock.expect(mockDevice.pushString(testTrie + "\n", CASE_LIST_FILE_NAME))
- .andReturn(true).once();
-
EasyMock.expect(mockDevice.executeShellCommand(EasyMock.eq("rm " + LOG_FILE_NAME)))
.andReturn("").once();
- EasyMock.expect(mockDevice.doesFileExist(LOG_FILE_NAME)).andReturn(false).once();
- EasyMock.expect(mockDevice.pushString("", LOG_FILE_NAME)).andReturn(true).once();
- EasyMock.expect(mockDevice.doesFileExist(LOG_FILE_NAME)).andReturn(true).once();
+
+ EasyMock.expect(mockDevice.pushString(testTrie + "\n", CASE_LIST_FILE_NAME))
+ .andReturn(true).once();
String command = String.format(
"am instrument %s -w -e deqpLogFileName \"%s\" -e deqpCmdLine \"%s\" "