Merge "Fix CTS: ViewGroupTests failing" into mnc-dev
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index d22f5ec..fa4203d 100644
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -1523,6 +1523,10 @@
Overlay view must be shown. Verify that there is a text view displaying \"Overlay View Dummy Text\"
when you tune to the \"Dummy\" channel.
</string>
+ <string name="tv_input_discover_test_verify_global_search">
+ Live Channels app should provide query results for 3rd-party input\'s channels and programs on
+ global search requests.
+ </string>
<string name="tv_input_discover_test_go_to_epg">
Press the \"Launch EPG\" button, and locate the channel named \"Dummy\".
</string>
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/camera/video/CameraVideoActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/camera/video/CameraVideoActivity.java
index 0a0e830..48ce03c 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/camera/video/CameraVideoActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/camera/video/CameraVideoActivity.java
@@ -547,7 +547,18 @@
break;
}
}
- // Second try to find one with similar if not the same aspect ratio
+ // Second try to find same ratio in size
+ if (matchedSize == null) {
+ for (int i = mPreviewSizes.size() - 1; i >= 0; i--) {
+ if (mPreviewSizes.get(i).width * recordSize.height ==
+ mPreviewSizes.get(i).height * recordSize.width) {
+ matchedSize = mCamera.new Size(mPreviewSizes.get(i).width,
+ mPreviewSizes.get(i).height);
+ break;
+ }
+ }
+ }
+ //Third try to find one with similar if not the same apect ratio
if (matchedSize == null) {
for (int i = mPreviewSizes.size() - 1; i >= 0; i--) {
if (Math.abs((float)mPreviewSizes.get(i).width * recordSize.height /
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/jobscheduler/ConnectivityConstraintTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/jobscheduler/ConnectivityConstraintTestActivity.java
old mode 100644
new mode 100755
index e97539d..8d10bda
--- a/apps/CtsVerifier/src/com/android/cts/verifier/jobscheduler/ConnectivityConstraintTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/jobscheduler/ConnectivityConstraintTestActivity.java
@@ -31,6 +31,8 @@
ConnectivityConstraintTestActivity.class.hashCode() + 1;
private static final int NO_CONNECTIVITY_JOB_ID =
ConnectivityConstraintTestActivity.class.hashCode() + 2;
+ private static final int NO_CONNECTIVITY_JOB_ID_2 =
+ ConnectivityConstraintTestActivity.class.hashCode() + 3;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -89,18 +91,25 @@
}
private void testNoConnectivityConstraintExecutes_noConnectivity() {
- JobInfo testJob = new JobInfo.Builder(NO_CONNECTIVITY_JOB_ID, mMockComponent)
+ JobInfo testJob1 = new JobInfo.Builder(NO_CONNECTIVITY_JOB_ID, mMockComponent)
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_NONE)
.setOverrideDeadline(100000L) // Will not expire.
.build();
+ JobInfo testJob2 = new JobInfo.Builder(NO_CONNECTIVITY_JOB_ID_2, mMockComponent)
+ .setRequiredNetworkType(JobInfo.NETWORK_TYPE_NONE)
+ .setOverrideDeadline(100000L) // Will not expire.
+ .build();
mTestEnvironment.setUp();
- mTestEnvironment.setExpectedExecutions(1);
+ mTestEnvironment.setExpectedExecutions(2);
- mJobScheduler.schedule(testJob);
+ mJobScheduler.schedule(testJob1);
+ mJobScheduler.schedule(testJob2);
+ /*
// Send intent to kick off ready jobs that the JobScheduler might be lazily holding on to.
sendBroadcastAndBlockForResult(EXPEDITE_STABLE_CHARGING);
+ */
boolean testPassed;
try {
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/tv/MockTvInputSetupActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/tv/MockTvInputSetupActivity.java
index 1d3fd40..c05b753 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/tv/MockTvInputSetupActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/tv/MockTvInputSetupActivity.java
@@ -33,11 +33,11 @@
public class MockTvInputSetupActivity extends Activity {
private static final String TAG = "MockTvInputSetupActivity";
- private static final String CHANNEL_NUMBER = "999-0";
- private static final String CHANNEL_NAME = "Dummy";
+ /* package-private */ static final String CHANNEL_NUMBER = "999-0";
+ /* package-private */ static final String CHANNEL_NAME = "Dummy";
- private static final String PROGRAM_TITLE = "Dummy Program";
- private static final String PROGRAM_DESCRIPTION = "Dummy Program Description";
+ /* package-private */ static final String PROGRAM_TITLE = "Dummy Program";
+ /* package-private */ static final String PROGRAM_DESCRIPTION = "Dummy Program Description";
private static final long PROGRAM_LENGTH_MILLIS = 60 * 60 * 1000;
private static final int PROGRAM_COUNT = 24;
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/tv/SearchUtil.java b/apps/CtsVerifier/src/com/android/cts/verifier/tv/SearchUtil.java
new file mode 100644
index 0000000..4513123
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/tv/SearchUtil.java
@@ -0,0 +1,136 @@
+/*
+ * 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.tv;
+
+import android.app.SearchManager;
+import android.app.SearchableInfo;
+import android.content.ContentProviderClient;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteException;
+import android.media.tv.TvContract;
+import android.net.Uri;
+import android.os.RemoteException;
+import android.text.TextUtils;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * A utility class for verifying channel/program results on global search requests.
+ */
+public class SearchUtil {
+ private SearchUtil() {}
+
+ /**
+ * Returns {@code true} if one of the search results matches the given {@code expectedResult}.
+ *
+ * @param context The context object to be used for getting content resolver
+ * @param searchable The {@link android.app.SearchableInfo} the TV app implements
+ * @param query A query string to search for
+ * @param expectedResult The expected search result
+ */
+ public static boolean verifySearchResult(Context context, SearchableInfo searchable,
+ String query, String expectedResult) {
+ Uri.Builder uriBuilder = getSearchUri(searchable).buildUpon();
+ String selection = searchable.getSuggestSelection();
+ String[] selectionArg = null;
+ if (selection != null) {
+ selectionArg = new String[] { query };
+ } else {
+ uriBuilder.appendPath(query);
+ }
+
+ Uri uri = uriBuilder.build();
+ ContentProviderClient provider = context.getContentResolver()
+ .acquireUnstableContentProviderClient(uri);
+ try (Cursor c = provider.query(uri, null, selection, selectionArg, null, null)) {
+ while (c.moveToNext()) {
+ int index = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_TEXT_1);
+ if (index >= 0) {
+ if (TextUtils.equals(expectedResult, c.getString(index))) {
+ return true;
+ }
+ }
+ }
+ } catch (SQLiteException | RemoteException e) {
+ return false;
+ } finally {
+ provider.release();
+ }
+ return false;
+ }
+
+ /**
+ * Returns the {@link android.app.SearchableInfo} instances which should provide search results
+ * for channels and programs in TvProvider.
+ *
+ * @param context The context object to used for accessing system services
+ */
+ public static List<SearchableInfo> getSearchableInfos(Context context) {
+ // Just in case EPG is provided by a separate package, collect all possible TV packages
+ // that can be searchable.
+ PackageManager pm = context.getPackageManager();
+ Set<String> tvPackages = new HashSet<>();
+ List<ResolveInfo> infos = pm.queryIntentActivities(new Intent(Intent.ACTION_VIEW,
+ TvContract.Channels.CONTENT_URI), 0);
+ for (ResolveInfo info : infos) {
+ tvPackages.add(info.activityInfo.packageName);
+ }
+ infos = pm.queryIntentActivities(new Intent(Intent.ACTION_VIEW,
+ TvContract.Programs.CONTENT_URI), 0);
+ for (ResolveInfo info : infos) {
+ tvPackages.add(info.activityInfo.packageName);
+ }
+ SearchManager sm = (SearchManager) context.getSystemService(Context.SEARCH_SERVICE);
+ List<SearchableInfo> globalSearchableInfos = sm.getSearchablesInGlobalSearch();
+ List<SearchableInfo> tvSearchableInfos = new ArrayList<>();
+ for (SearchableInfo info : globalSearchableInfos) {
+ if (tvPackages.contains(info.getSearchActivity().getPackageName())) {
+ tvSearchableInfos.add(info);
+ }
+ }
+ return tvSearchableInfos;
+ }
+
+ private static Uri getSearchUri(SearchableInfo searchable) {
+ if (searchable == null) {
+ return null;
+ }
+ String authority = searchable.getSuggestAuthority();
+ if (authority == null) {
+ return null;
+ }
+ Uri.Builder uriBuilder = new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(authority);
+
+ final String contentPath = searchable.getSuggestPath();
+ if (contentPath != null) {
+ uriBuilder.appendEncodedPath(contentPath);
+ }
+
+ uriBuilder.appendPath(SearchManager.SUGGEST_URI_PATH_QUERY);
+ return uriBuilder.build();
+ }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/tv/TvInputDiscoveryTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/tv/TvInputDiscoveryTestActivity.java
index 4d12d52..06f4f6f 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/tv/TvInputDiscoveryTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/tv/TvInputDiscoveryTestActivity.java
@@ -16,12 +16,17 @@
package com.android.cts.verifier.tv;
+import android.app.SearchableInfo;
+import android.content.Context;
import android.content.Intent;
import android.media.tv.TvContract;
+import android.os.AsyncTask;
import android.view.View;
import com.android.cts.verifier.R;
+import java.util.List;
+
/**
* Tests for verifying TV app behavior for third-party TV input apps.
*/
@@ -41,10 +46,12 @@
private View mTuneToChannelItem;
private View mVerifyTuneItem;
private View mVerifyOverlayViewItem;
+ private View mVerifyGlobalSearchItem;
private View mGoToEpgItem;
private View mVerifyEpgItem;
private boolean mTuneVerified;
private boolean mOverlayViewVerified;
+ private boolean mGlobalSearchVerified;
@Override
public void onClick(View v) {
@@ -96,6 +103,7 @@
goToNextState(postTarget, failCallback);
}
});
+ verifyGlobalSearch(postTarget, failCallback);
startActivity(TV_APP_INTENT);
} else if (containsButton(mGoToEpgItem, v)) {
startActivity(EPG_INTENT);
@@ -118,22 +126,52 @@
mVerifyTuneItem = createAutoItem(R.string.tv_input_discover_test_verify_tune);
mVerifyOverlayViewItem = createAutoItem(
R.string.tv_input_discover_test_verify_overlay_view);
+ mVerifyGlobalSearchItem = createAutoItem(
+ R.string.tv_input_discover_test_verify_global_search);
mGoToEpgItem = createUserItem(R.string.tv_input_discover_test_go_to_epg,
R.string.tv_launch_epg, this);
mVerifyEpgItem = createUserItem(R.string.tv_input_discover_test_verify_epg,
R.string.tv_input_discover_test_yes, this);
}
+ @Override
+ protected void setInfoResources() {
+ setInfoResources(R.string.tv_input_discover_test,
+ R.string.tv_input_discover_test_info, -1);
+ }
+
private void goToNextState(View postTarget, Runnable failCallback) {
- if (mTuneVerified && mOverlayViewVerified) {
+ if (mTuneVerified && mOverlayViewVerified && mGlobalSearchVerified) {
postTarget.removeCallbacks(failCallback);
setButtonEnabled(mGoToEpgItem, true);
}
}
- @Override
- protected void setInfoResources() {
- setInfoResources(R.string.tv_input_discover_test,
- R.string.tv_input_discover_test_info, -1);
+ private void verifyGlobalSearch(final View postTarget, final Runnable failCallback) {
+ new AsyncTask<Void, Void, Boolean>() {
+ @Override
+ protected Boolean doInBackground(Void... params) {
+ Context context = TvInputDiscoveryTestActivity.this;
+ for (SearchableInfo info : SearchUtil.getSearchableInfos(context)) {
+ if (SearchUtil.verifySearchResult(context, info,
+ MockTvInputSetupActivity.CHANNEL_NAME,
+ MockTvInputSetupActivity.PROGRAM_TITLE)
+ && SearchUtil.verifySearchResult(context, info,
+ MockTvInputSetupActivity.PROGRAM_TITLE,
+ MockTvInputSetupActivity.PROGRAM_TITLE)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ protected void onPostExecute(Boolean result) {
+ super.onPostExecute(result);
+ setPassState(mVerifyGlobalSearchItem, result);
+ mGlobalSearchVerified = result;
+ goToNextState(postTarget, failCallback);
+ }
+ }.execute();
}
}
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/BurstCaptureRawTest.java b/tests/tests/hardware/src/android/hardware/camera2/cts/BurstCaptureRawTest.java
index a64ceb9..3c9c061 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/BurstCaptureRawTest.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/BurstCaptureRawTest.java
@@ -37,12 +37,14 @@
import java.util.ArrayList;
/**
- * Basic tests for burst capture in RAW10/16.
+ * Basic tests for burst capture in RAW formats.
*/
public class BurstCaptureRawTest extends Camera2SurfaceViewTestCase {
private static final String TAG = "BurstCaptureRawTest";
private static final int RAW_FORMATS[] = {
- ImageFormat.RAW10, ImageFormat.RAW_SENSOR };
+ ImageFormat.RAW10, ImageFormat.RAW12, ImageFormat.RAW_SENSOR };
+ private static final int NONSTALL_RAW_FORMATS[] = {
+ ImageFormat.RAW10, ImageFormat.RAW12 };
private static final long EXPOSURE_MULTIPLIERS[] = {
1, 3, 5 };
private static final int SENSITIVITY_MLTIPLIERS[] = {
@@ -70,7 +72,7 @@
openDevice(id);
ArrayList<Integer> supportedRawList = new ArrayList<Integer>(RAW_FORMATS.length);
- if (!checkCapability(supportedRawList)) {
+ if (!checkCapability(supportedRawList, RAW_FORMATS)) {
Log.i(TAG, "Capability is not supported on camera " + id
+ ". Skip the test.");
continue;
@@ -104,13 +106,13 @@
public void testMetadataRoundDown() throws Exception {
Log.i(TAG, "Begin testMetadataRoundDown");
- performTestRoutine(new TestMetaDataRoundDownRoutine());
+ performTestRoutine(new TestMetaDataRoundDownRoutine(), RAW_FORMATS);
Log.i(TAG, "End testMetadataRoundDown");
}
/**
- * Manual and Auto setting test in RAW10/16
+ * Manual and Auto setting test in RAW formats
* <p>
* Make sure switching between manual and auto setting would not make the capture results out of
* sync.
@@ -119,18 +121,18 @@
public void testManualAutoSwitch() throws Exception {
Log.i(TAG, "Begin testManualAutoSwitch");
- performTestRoutine(new TestManualAutoSwitch());
+ performTestRoutine(new TestManualAutoSwitch(), RAW_FORMATS);
Log.i(TAG, "End testManualAutoSwitch");
}
/**
- * Per frame timestamp test in RAW10/16
+ * Per frame timestamp test in non-stalled RAW formats
*/
public void testTimestamp() throws Exception {
Log.i(TAG, "Begin testTimestamp");
- performTestRoutine(new TestTimestamp());
+ performTestRoutine(new TestTimestamp(), NONSTALL_RAW_FORMATS);
Log.i(TAG, "End testTimestamp");
}
@@ -439,7 +441,7 @@
*
* @return true if the it is has the capability to execute the test.
*/
- private boolean checkCapability(ArrayList<Integer> supportedRawList) {
+ private boolean checkCapability(ArrayList<Integer> supportedRawList, int[] testedFormats) {
// make sure the sensor has manual support
if (!mStaticInfo.isCapabilitySupported(
CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL)) {
@@ -453,7 +455,7 @@
// check for the RAW support
supportedRawList.clear();
- for (int rawFormat : RAW_FORMATS) {
+ for (int rawFormat : testedFormats) {
if (!config.isOutputSupportedFor(rawFormat)) {
continue;
}
@@ -479,6 +481,8 @@
switch (format) {
case ImageFormat.RAW10:
return "RAW10";
+ case ImageFormat.RAW12:
+ return "RAW12";
case ImageFormat.RAW_SENSOR:
return "RAW_SENSOR";
}
@@ -668,14 +672,15 @@
stopPreview();
}
- private void performTestRoutine(TestRoutine routine) throws Exception
+ private void performTestRoutine(TestRoutine routine, int[] testedFormats) throws Exception
{
+ final int PREPARE_TIMEOUT_MS = 10000;
for (String id : mCameraIds) {
try {
openDevice(id);
ArrayList<Integer> supportedRawList = new ArrayList<Integer>(RAW_FORMATS.length);
- if (!checkCapability(supportedRawList)) {
+ if (!checkCapability(supportedRawList, testedFormats)) {
Log.i(TAG, "Capability is not supported on camera " + id
+ ". Skip the test.");
continue;
@@ -705,6 +710,11 @@
previewCaptureSize, rawCaptureSize, rawFormat, previewCaptureCallback,
MAX_FRAMES_BURST, rawReaderListener);
+ // Prepare still surface to prevent large allocations slow down capture
+ mSession.prepare(mReaderSurface);
+ mSessionListener.waitForSurfacePrepared(
+ mSession, mReaderSurface, PREPARE_TIMEOUT_MS);
+
// execute test routine
routine.execute(rawBurstBuilder, rawCaptureCallback, rawReaderListener,
rawFormat);
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/CameraTestUtils.java b/tests/tests/hardware/src/android/hardware/camera2/cts/CameraTestUtils.java
index f12bd1c..afd71f5 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/CameraTestUtils.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/CameraTestUtils.java
@@ -115,12 +115,6 @@
private static final float EXIF_EXPOSURE_TIME_MIN_ERROR_MARGIN_SEC = 0.002f;
private static final float EXIF_APERTURE_ERROR_MARGIN = 0.001f;
- // Some exif tags that are not defined by ExifInterface but supported.
- private static final String TAG_DATETIME_DIGITIZED = "DateTimeDigitized";
- private static final String TAG_SUBSEC_TIME = "SubSecTime";
- private static final String TAG_SUBSEC_TIME_ORIG = "SubSecTimeOriginal";
- private static final String TAG_SUBSEC_TIME_DIG = "SubSecTimeDigitized";
-
private static final Location sTestLocation0 = new Location(LocationManager.GPS_PROVIDER);
private static final Location sTestLocation1 = new Location(LocationManager.GPS_PROVIDER);
private static final Location sTestLocation2 = new Location(LocationManager.NETWORK_PROVIDER);
@@ -1959,7 +1953,7 @@
}
// TAG_DATETIME_DIGITIZED (a.k.a Create time for digital cameras).
- String digitizedTime = exif.getAttribute(TAG_DATETIME_DIGITIZED);
+ String digitizedTime = exif.getAttribute(ExifInterface.TAG_DATETIME_DIGITIZED);
collector.expectNotNull("Exif TAG_DATETIME_DIGITIZED shouldn't be null", digitizedTime);
if (digitizedTime != null) {
String expectedDateTime = exif.getAttribute(ExifInterface.TAG_DATETIME);
@@ -1977,16 +1971,18 @@
* this exif tag either doesn't exist or is a non-numerical invalid
* string. Same rule applies to the rest of sub second tags.
*/
- int subSecTime = exif.getAttributeInt(TAG_SUBSEC_TIME, /*defaultValue*/-1);
+ int subSecTime = exif.getAttributeInt(ExifInterface.TAG_SUBSEC_TIME, /*defaultValue*/-1);
collector.expectTrue("Exif TAG_SUBSEC_TIME value is null or invalid!", subSecTime > 0);
// TAG_SUBSEC_TIME_ORIG
- int subSecTimeOrig = exif.getAttributeInt(TAG_SUBSEC_TIME_ORIG, /*defaultValue*/-1);
+ int subSecTimeOrig = exif.getAttributeInt(ExifInterface.TAG_SUBSEC_TIME_ORIG,
+ /*defaultValue*/-1);
collector.expectTrue("Exif TAG_SUBSEC_TIME_ORIG value is null or invalid!",
subSecTimeOrig > 0);
// TAG_SUBSEC_TIME_DIG
- int subSecTimeDig = exif.getAttributeInt(TAG_SUBSEC_TIME_DIG, /*defaultValue*/-1);
+ int subSecTimeDig = exif.getAttributeInt(ExifInterface.TAG_SUBSEC_TIME_DIG,
+ /*defaultValue*/-1);
collector.expectTrue(
"Exif TAG_SUBSEC_TIME_DIG value is null or invalid!", subSecTimeDig > 0);
}
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/PerformanceTest.java b/tests/tests/hardware/src/android/hardware/camera2/cts/PerformanceTest.java
index 31a8d98..8dbceae 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/PerformanceTest.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/PerformanceTest.java
@@ -119,7 +119,9 @@
double[] stopPreviewTimes = new double[NUM_TEST_LOOPS];
double[] cameraCloseTimes = new double[NUM_TEST_LOOPS];
double[] cameraLaunchTimes = new double[NUM_TEST_LOOPS];
+ double[] avgCameraLaunchTimes = new double[mCameraIds.length];
+ int counter = 0;
for (String id : mCameraIds) {
try {
initializeImageReader(id, ImageFormat.YUV_420_888);
@@ -167,6 +169,7 @@
}
}
+ avgCameraLaunchTimes[counter] = Stat.getAverage(cameraLaunchTimes);
// Finish the data collection, report the KPIs.
mReportLog.printArray("Camera " + id
+ ": Camera open time", cameraOpenTimes,
@@ -186,14 +189,14 @@
mReportLog.printArray("Camera " + id
+ ": Camera launch time", cameraLaunchTimes,
ResultType.LOWER_BETTER, ResultUnit.MS);
- mReportLog.printSummary("Camera launch average time for Camera " + id,
- Stat.getAverage(cameraLaunchTimes),
- ResultType.LOWER_BETTER, ResultUnit.MS);
}
finally {
closeImageReader();
}
+ counter++;
}
+ mReportLog.printSummary("Camera launch average time for all cameras ",
+ Stat.getAverage(avgCameraLaunchTimes), ResultType.LOWER_BETTER, ResultUnit.MS);
}
/**
@@ -213,7 +216,9 @@
double[] captureTimes = new double[NUM_TEST_LOOPS];
double[] getPartialTimes = new double[NUM_TEST_LOOPS];
double[] getResultTimes = new double[NUM_TEST_LOOPS];
+ double[] avgResultTimes = new double[mCameraIds.length];
+ int counter = 0;
for (String id : mCameraIds) {
try {
openDevice(id);
@@ -291,16 +296,18 @@
+ ": Camera capture result latency", getResultTimes,
ResultType.LOWER_BETTER, ResultUnit.MS);
- // Result will not be reported in CTS report if no summary is printed.
- mReportLog.printSummary("Camera capture result average latency for Camera " + id,
- Stat.getAverage(getResultTimes),
- ResultType.LOWER_BETTER, ResultUnit.MS);
+ avgResultTimes[counter] = Stat.getAverage(getResultTimes);
}
finally {
closeImageReader();
closeDevice();
}
+ counter++;
}
+
+ // Result will not be reported in CTS report if no summary is printed.
+ mReportLog.printSummary("Camera capture result average latency for all cameras ",
+ Stat.getAverage(avgResultTimes), ResultType.LOWER_BETTER, ResultUnit.MS);
}
/**
diff --git a/tests/tests/media/src/android/media/cts/MediaBrowserServiceTest.java b/tests/tests/media/src/android/media/cts/MediaBrowserServiceTest.java
new file mode 100644
index 0000000..996ddf7
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/MediaBrowserServiceTest.java
@@ -0,0 +1,133 @@
+/*
+ * 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.content.ComponentName;
+import android.media.browse.MediaBrowser;
+import android.media.browse.MediaBrowser.MediaItem;
+import android.os.Bundle;
+import android.service.media.MediaBrowserService;
+import android.service.media.MediaBrowserService.BrowserRoot;
+import android.test.InstrumentationTestCase;
+
+import java.util.List;
+
+/**
+ * Test {@link android.media.browse.MediaBrowserService}.
+ */
+public class MediaBrowserServiceTest extends InstrumentationTestCase {
+ // The maximum time to wait for an operation.
+ private static final long TIME_OUT_MS = 3000L;
+ private static final long WAIT_TIME_FOR_NO_RESPONSE_MS = 500L;
+ private static final ComponentName TEST_BROWSER_SERVICE = new ComponentName(
+ "com.android.cts.media", "android.media.cts.StubMediaBrowserService");
+ private final Object mWaitLock = new Object();
+ private final MediaBrowser.ConnectionCallback mConnectionCallback =
+ new MediaBrowser.ConnectionCallback() {
+ @Override
+ public void onConnected() {
+ synchronized (mWaitLock) {
+ mMediaBrowserService = StubMediaBrowserService.sInstance;
+ mWaitLock.notify();
+ }
+ }
+ };
+
+ private final MediaBrowser.SubscriptionCallback mSubscriptionCallback =
+ new MediaBrowser.SubscriptionCallback() {
+ @Override
+ public void onChildrenLoaded(String parentId, List<MediaItem> children) {
+ synchronized (mWaitLock) {
+ mOnChildrenLoaded = true;
+ mWaitLock.notify();
+ }
+ }
+ };
+
+ private MediaBrowser mMediaBrowser;
+ private StubMediaBrowserService mMediaBrowserService;
+ private boolean mOnChildrenLoaded;
+
+ @Override
+ protected void setUp() throws Exception {
+ getInstrumentation().runOnMainSync(new Runnable() {
+ @Override
+ public void run() {
+ mMediaBrowser = new MediaBrowser(getInstrumentation().getTargetContext(),
+ TEST_BROWSER_SERVICE, mConnectionCallback, null);
+ }
+ });
+ synchronized (mWaitLock) {
+ mMediaBrowser.connect();
+ mWaitLock.wait(TIME_OUT_MS);
+ }
+ assertNotNull(mMediaBrowserService);
+ }
+
+ public void testGetSessionToken() {
+ assertEquals(StubMediaBrowserService.sSession.getSessionToken(),
+ mMediaBrowserService.getSessionToken());
+ }
+
+ public void testNotifyChildrenChanged() throws Exception {
+ synchronized (mWaitLock) {
+ mMediaBrowser.subscribe(StubMediaBrowserService.MEDIA_ID_ROOT, mSubscriptionCallback);
+ mWaitLock.wait(TIME_OUT_MS);
+ assertTrue(mOnChildrenLoaded);
+
+ mOnChildrenLoaded = false;
+ mMediaBrowserService.notifyChildrenChanged(StubMediaBrowserService.MEDIA_ID_ROOT);
+ mWaitLock.wait(TIME_OUT_MS);
+ assertTrue(mOnChildrenLoaded);
+ }
+ }
+
+ public void testDelayedNotifyChildrenChanged() throws Exception {
+ synchronized (mWaitLock) {
+ mOnChildrenLoaded = false;
+ mMediaBrowser.subscribe(StubMediaBrowserService.MEDIA_ID_CHILDREN_DELAYED,
+ mSubscriptionCallback);
+ mWaitLock.wait(WAIT_TIME_FOR_NO_RESPONSE_MS);
+ assertFalse(mOnChildrenLoaded);
+
+ mMediaBrowserService.sendDelayedNotifyChildrenChanged();
+ mWaitLock.wait(TIME_OUT_MS);
+ assertTrue(mOnChildrenLoaded);
+
+ mOnChildrenLoaded = false;
+ mMediaBrowserService.notifyChildrenChanged(
+ StubMediaBrowserService.MEDIA_ID_CHILDREN_DELAYED);
+ mWaitLock.wait(WAIT_TIME_FOR_NO_RESPONSE_MS);
+ assertFalse(mOnChildrenLoaded);
+
+ mMediaBrowserService.sendDelayedNotifyChildrenChanged();
+ mWaitLock.wait(TIME_OUT_MS);
+ assertTrue(mOnChildrenLoaded);
+ }
+ }
+
+ public void testBrowserRoot() {
+ final String id = "test-id";
+ final String key = "test-key";
+ final String val = "test-val";
+ final Bundle extras = new Bundle();
+ extras.putString(key, val);
+
+ MediaBrowserService.BrowserRoot browserRoot = new BrowserRoot(id, extras);
+ assertEquals(id, browserRoot.getRootId());
+ assertEquals(val, browserRoot.getExtras().getString(key));
+ }
+}
diff --git a/tests/tests/media/src/android/media/cts/MediaBrowserTest.java b/tests/tests/media/src/android/media/cts/MediaBrowserTest.java
index 976e5a6..51d43d9 100644
--- a/tests/tests/media/src/android/media/cts/MediaBrowserTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaBrowserTest.java
@@ -27,7 +27,7 @@
*/
public class MediaBrowserTest extends InstrumentationTestCase {
// The maximum time to wait for an operation.
- private static final long TIME_OUT_MS = 1000L;
+ private static final long TIME_OUT_MS = 3000L;
private static final ComponentName TEST_BROWSER_SERVICE = new ComponentName(
"com.android.cts.media", "android.media.cts.StubMediaBrowserService");
private static final ComponentName TEST_INVALID_BROWSER_SERVICE = new ComponentName(
diff --git a/tests/tests/media/src/android/media/cts/MediaControllerTest.java b/tests/tests/media/src/android/media/cts/MediaControllerTest.java
index b934516..a153c4d 100644
--- a/tests/tests/media/src/android/media/cts/MediaControllerTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaControllerTest.java
@@ -15,13 +15,16 @@
*/
package android.media.cts;
+import android.media.AudioManager;
import android.media.Rating;
+import android.media.VolumeProvider;
import android.media.session.MediaController;
import android.media.session.MediaSession;
import android.media.session.PlaybackState.CustomAction;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
+import android.os.ResultReceiver;
import android.test.AndroidTestCase;
/**
@@ -29,129 +32,233 @@
*/
public class MediaControllerTest extends AndroidTestCase {
// The maximum time to wait for an operation.
- private static final long TIME_OUT_MS = 5000L;
+ private static final long TIME_OUT_MS = 3000L;
private static final String SESSION_TAG = "test-session";
private static final String EXTRAS_KEY = "test-key";
private static final String EXTRAS_VALUE = "test-val";
+ private final Object mWaitLock = new Object();
private Handler mHandler = new Handler(Looper.getMainLooper());
+ private MediaSession mSession;
+ private MediaSessionCallback mCallback = new MediaSessionCallback();
+ private MediaController mController;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mSession = new MediaSession(getContext(), SESSION_TAG);
+ mSession.setCallback(mCallback, mHandler);
+ mController = mSession.getController();
+ }
+
+ public void testSendCommand() throws Exception {
+ synchronized (mWaitLock) {
+ mCallback.reset();
+ final String command = "test-command";
+ final Bundle extras = new Bundle();
+ extras.putString(EXTRAS_KEY, EXTRAS_VALUE);
+ mController.sendCommand(command, extras, new ResultReceiver(null));
+ mWaitLock.wait(TIME_OUT_MS);
+ assertTrue(mCallback.mOnCommandCalled);
+ assertNotNull(mCallback.mCommandCallback);
+ assertEquals(command, mCallback.mCommand);
+ assertEquals(EXTRAS_VALUE, mCallback.mExtras.getString(EXTRAS_KEY));
+ }
+ }
+
+ public void testVolumeControl() throws Exception {
+ VolumeProvider vp = new VolumeProvider(VolumeProvider.VOLUME_CONTROL_ABSOLUTE, 11, 5) {
+ @Override
+ public void onSetVolumeTo(int volume) {
+ synchronized (mWaitLock) {
+ setCurrentVolume(volume);
+ mWaitLock.notify();
+ }
+ }
+
+ @Override
+ public void onAdjustVolume(int direction) {
+ synchronized (mWaitLock) {
+ switch (direction) {
+ case AudioManager.ADJUST_LOWER:
+ setCurrentVolume(getCurrentVolume() - 1);
+ break;
+ case AudioManager.ADJUST_RAISE:
+ setCurrentVolume(getCurrentVolume() + 1);
+ break;
+ }
+ mWaitLock.notify();
+ }
+ }
+ };
+ mSession.setPlaybackToRemote(vp);
+
+ synchronized (mWaitLock) {
+ // test setVolumeTo
+ mController.setVolumeTo(7, 0);
+ mWaitLock.wait(TIME_OUT_MS);
+ assertEquals(7, vp.getCurrentVolume());
+
+ // test adjustVolume
+ mController.adjustVolume(AudioManager.ADJUST_LOWER, 0);
+ mWaitLock.wait(TIME_OUT_MS);
+ assertEquals(6, vp.getCurrentVolume());
+
+ mController.adjustVolume(AudioManager.ADJUST_RAISE, 0);
+ mWaitLock.wait(TIME_OUT_MS);
+ assertEquals(7, vp.getCurrentVolume());
+ }
+ }
public void testTransportControlsAndMediaSessionCallback() throws Exception {
- Object waitLock = new Object();
- MediaSession session = new MediaSession(getContext(), SESSION_TAG);
- MediaSessionCallback callback = new MediaSessionCallback(waitLock);
- session.setCallback(callback, mHandler);
-
- MediaController.TransportControls controls =
- session.getController().getTransportControls();
- synchronized (waitLock) {
+ MediaController.TransportControls controls = mController.getTransportControls();
+ synchronized (mWaitLock) {
+ mCallback.reset();
controls.play();
- waitLock.wait(TIME_OUT_MS);
- assertTrue(callback.mOnPlayCalled);
+ mWaitLock.wait(TIME_OUT_MS);
+ assertTrue(mCallback.mOnPlayCalled);
+ mCallback.reset();
controls.pause();
- waitLock.wait(TIME_OUT_MS);
- assertTrue(callback.mOnPauseCalled);
+ mWaitLock.wait(TIME_OUT_MS);
+ assertTrue(mCallback.mOnPauseCalled);
+ mCallback.reset();
controls.stop();
- waitLock.wait(TIME_OUT_MS);
- assertTrue(callback.mOnStopCalled);
+ mWaitLock.wait(TIME_OUT_MS);
+ assertTrue(mCallback.mOnStopCalled);
+ mCallback.reset();
controls.fastForward();
- waitLock.wait(TIME_OUT_MS);
- assertTrue(callback.mOnFastForwardCalled);
+ mWaitLock.wait(TIME_OUT_MS);
+ assertTrue(mCallback.mOnFastForwardCalled);
+ mCallback.reset();
controls.rewind();
- waitLock.wait(TIME_OUT_MS);
- assertTrue(callback.mOnRewindCalled);
+ mWaitLock.wait(TIME_OUT_MS);
+ assertTrue(mCallback.mOnRewindCalled);
+ mCallback.reset();
controls.skipToPrevious();
- waitLock.wait(TIME_OUT_MS);
- assertTrue(callback.mOnSkipToPreviousCalled);
+ mWaitLock.wait(TIME_OUT_MS);
+ assertTrue(mCallback.mOnSkipToPreviousCalled);
+ mCallback.reset();
controls.skipToNext();
- waitLock.wait(TIME_OUT_MS);
- assertTrue(callback.mOnSkipToNextCalled);
+ mWaitLock.wait(TIME_OUT_MS);
+ assertTrue(mCallback.mOnSkipToNextCalled);
+ mCallback.reset();
final long seekPosition = 1000;
controls.seekTo(seekPosition);
- waitLock.wait(TIME_OUT_MS);
- assertTrue(callback.mOnSeekToCalled);
- assertEquals(seekPosition, callback.mSeekPosition);
+ mWaitLock.wait(TIME_OUT_MS);
+ assertTrue(mCallback.mOnSeekToCalled);
+ assertEquals(seekPosition, mCallback.mSeekPosition);
+ mCallback.reset();
final Rating rating = Rating.newStarRating(Rating.RATING_5_STARS, 3f);
controls.setRating(rating);
- waitLock.wait(TIME_OUT_MS);
- assertTrue(callback.mOnSetRatingCalled);
- assertEquals(rating.getRatingStyle(), callback.mRating.getRatingStyle());
- assertEquals(rating.getStarRating(), callback.mRating.getStarRating());
+ mWaitLock.wait(TIME_OUT_MS);
+ assertTrue(mCallback.mOnSetRatingCalled);
+ assertEquals(rating.getRatingStyle(), mCallback.mRating.getRatingStyle());
+ assertEquals(rating.getStarRating(), mCallback.mRating.getStarRating());
+ mCallback.reset();
final String mediaId = "test-media-id";
final Bundle extras = new Bundle();
extras.putString(EXTRAS_KEY, EXTRAS_VALUE);
controls.playFromMediaId(mediaId, extras);
- waitLock.wait(TIME_OUT_MS);
- assertTrue(callback.mOnPlayFromMediaIdCalled);
- assertEquals(mediaId, callback.mMediaId);
- assertEquals(EXTRAS_VALUE, callback.mExtras.getString(EXTRAS_KEY));
+ mWaitLock.wait(TIME_OUT_MS);
+ assertTrue(mCallback.mOnPlayFromMediaIdCalled);
+ assertEquals(mediaId, mCallback.mMediaId);
+ assertEquals(EXTRAS_VALUE, mCallback.mExtras.getString(EXTRAS_KEY));
+ mCallback.reset();
final String query = "test-query";
controls.playFromSearch(query, extras);
- waitLock.wait(TIME_OUT_MS);
- assertTrue(callback.mOnPlayFromSearchCalled);
- assertEquals(query, callback.mQuery);
- assertEquals(EXTRAS_VALUE, callback.mExtras.getString(EXTRAS_KEY));
+ mWaitLock.wait(TIME_OUT_MS);
+ assertTrue(mCallback.mOnPlayFromSearchCalled);
+ assertEquals(query, mCallback.mQuery);
+ assertEquals(EXTRAS_VALUE, mCallback.mExtras.getString(EXTRAS_KEY));
+ mCallback.reset();
final String action = "test-action";
controls.sendCustomAction(action, extras);
- waitLock.wait(TIME_OUT_MS);
- assertTrue(callback.mOnCustomActionCalled);
- assertEquals(action, callback.mAction);
- assertEquals(EXTRAS_VALUE, callback.mExtras.getString(EXTRAS_KEY));
+ mWaitLock.wait(TIME_OUT_MS);
+ assertTrue(mCallback.mOnCustomActionCalled);
+ assertEquals(action, mCallback.mAction);
+ assertEquals(EXTRAS_VALUE, mCallback.mExtras.getString(EXTRAS_KEY));
- callback.mOnCustomActionCalled = false;
+ mCallback.reset();
+ mCallback.mOnCustomActionCalled = false;
final CustomAction customAction =
new CustomAction.Builder(action, action, -1).setExtras(extras).build();
controls.sendCustomAction(customAction, extras);
- waitLock.wait(TIME_OUT_MS);
- assertTrue(callback.mOnCustomActionCalled);
- assertEquals(action, callback.mAction);
- assertEquals(EXTRAS_VALUE, callback.mExtras.getString(EXTRAS_KEY));
+ mWaitLock.wait(TIME_OUT_MS);
+ assertTrue(mCallback.mOnCustomActionCalled);
+ assertEquals(action, mCallback.mAction);
+ assertEquals(EXTRAS_VALUE, mCallback.mExtras.getString(EXTRAS_KEY));
+ mCallback.reset();
final long queueItemId = 1000;
controls.skipToQueueItem(queueItemId);
- waitLock.wait(TIME_OUT_MS);
- assertTrue(callback.mOnSkipToQueueItemCalled);
- assertEquals(queueItemId, callback.mQueueItemId);
+ mWaitLock.wait(TIME_OUT_MS);
+ assertTrue(mCallback.mOnSkipToQueueItemCalled);
+ assertEquals(queueItemId, mCallback.mQueueItemId);
}
}
private class MediaSessionCallback extends MediaSession.Callback {
- private Object mWaitLock;
- private long mSeekPosition;
- private long mQueueItemId;
- private Rating mRating;
- private String mMediaId;
- private String mQuery;
- private String mAction;
- private Bundle mExtras;
+ private volatile long mSeekPosition;
+ private volatile long mQueueItemId;
+ private volatile Rating mRating;
+ private volatile String mMediaId;
+ private volatile String mQuery;
+ private volatile String mAction;
+ private volatile String mCommand;
+ private volatile Bundle mExtras;
+ private volatile ResultReceiver mCommandCallback;
- private boolean mOnPlayCalled;
- private boolean mOnPauseCalled;
- private boolean mOnStopCalled;
- private boolean mOnFastForwardCalled;
- private boolean mOnRewindCalled;
- private boolean mOnSkipToPreviousCalled;
- private boolean mOnSkipToNextCalled;
- private boolean mOnSeekToCalled;
- private boolean mOnSetRatingCalled;
- private boolean mOnPlayFromMediaIdCalled;
- private boolean mOnPlayFromSearchCalled;
- private boolean mOnCustomActionCalled;
- private boolean mOnSkipToQueueItemCalled;
+ private volatile boolean mOnPlayCalled;
+ private volatile boolean mOnPauseCalled;
+ private volatile boolean mOnStopCalled;
+ private volatile boolean mOnFastForwardCalled;
+ private volatile boolean mOnRewindCalled;
+ private volatile boolean mOnSkipToPreviousCalled;
+ private volatile boolean mOnSkipToNextCalled;
+ private volatile boolean mOnSeekToCalled;
+ private volatile boolean mOnSkipToQueueItemCalled;
+ private volatile boolean mOnSetRatingCalled;
+ private volatile boolean mOnPlayFromMediaIdCalled;
+ private volatile boolean mOnPlayFromSearchCalled;
+ private volatile boolean mOnCustomActionCalled;
+ private volatile boolean mOnCommandCalled;
- public MediaSessionCallback(Object lock) {
- mWaitLock = lock;
+ public void reset() {
+ mSeekPosition = -1;
+ mQueueItemId = -1;
+ mRating = null;
+ mMediaId = null;
+ mQuery = null;
+ mAction = null;
+ mExtras = null;
+ mCommand = null;
+ mCommandCallback = null;
+
+ mOnPlayCalled = false;
+ mOnPauseCalled = false;
+ mOnStopCalled = false;
+ mOnFastForwardCalled = false;
+ mOnRewindCalled = false;
+ mOnSkipToPreviousCalled = false;
+ mOnSkipToNextCalled = false;
+ mOnSkipToQueueItemCalled = false;
+ mOnSeekToCalled = false;
+ mOnSetRatingCalled = false;
+ mOnPlayFromMediaIdCalled = false;
+ mOnPlayFromSearchCalled = false;
+ mOnCustomActionCalled = false;
+ mOnCommandCalled = false;
}
@Override
@@ -266,5 +373,16 @@
mWaitLock.notify();
}
}
+
+ @Override
+ public void onCommand(String command, Bundle extras, ResultReceiver cb) {
+ synchronized (mWaitLock) {
+ mOnCommandCalled = true;
+ mCommand = command;
+ mExtras = extras;
+ mCommandCallback = cb;
+ mWaitLock.notify();
+ }
+ }
}
}
diff --git a/tests/tests/media/src/android/media/cts/MediaSessionTest.java b/tests/tests/media/src/android/media/cts/MediaSessionTest.java
index 7999092..a2dbe7d 100644
--- a/tests/tests/media/src/android/media/cts/MediaSessionTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaSessionTest.java
@@ -175,6 +175,10 @@
PendingIntent pi = PendingIntent.getActivity(getContext(), 555, intent, 0);
session.setSessionActivity(pi);
assertEquals(pi, controller.getSessionActivity());
+
+ // test setActivity
+ session.setActive(true);
+ assertTrue(session.isActive());
}
public void testSendSessionEvent() throws Exception {
diff --git a/tests/tests/media/src/android/media/cts/StubMediaBrowserService.java b/tests/tests/media/src/android/media/cts/StubMediaBrowserService.java
index bfd6db7..35e88f0 100644
--- a/tests/tests/media/src/android/media/cts/StubMediaBrowserService.java
+++ b/tests/tests/media/src/android/media/cts/StubMediaBrowserService.java
@@ -23,8 +23,11 @@
import android.service.media.MediaBrowserService;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
+import junit.framework.Assert;
+
/**
* Stub implementation of (@link android.service.media.MediaBrowserService}.
*/
@@ -32,18 +35,24 @@
static final String MEDIA_ID_ROOT = "test_media_id_root";
static final String EXTRAS_KEY = "test_extras_key";
static final String EXTRAS_VALUE = "test_extras_value";
+ static final String MEDIA_ID_CHILDREN_DELAYED = "test_media_id_children_delayed";
static final String[] MEDIA_ID_CHILDREN = new String[] {
"test_media_id_children_0", "test_media_id_children_1",
- "test_media_id_children_2", "test_media_id_children_3"
+ "test_media_id_children_2", "test_media_id_children_3",
+ MEDIA_ID_CHILDREN_DELAYED
};
+ static StubMediaBrowserService sInstance;
+
/* package private */ static MediaSession sSession;
private Bundle mExtras;
+ private Result<List<MediaItem>> mPendingResult;
@Override
public void onCreate() {
super.onCreate();
- sSession = new MediaSession(this, "MediaBrowserStubService");
+ sInstance = this;
+ sSession = new MediaSession(this, "StubMediaBrowserService");
setSessionToken(sSession.getSessionToken());
}
@@ -62,7 +71,18 @@
mediaItems.add(new MediaItem(new MediaDescription.Builder()
.setMediaId(id).build(), MediaItem.FLAG_BROWSABLE));
}
+ result.sendResult(mediaItems);
+ } else if (MEDIA_ID_CHILDREN_DELAYED.equals(parentMediaId)) {
+ Assert.assertNull(mPendingResult);
+ mPendingResult = result;
+ result.detach();
}
- result.sendResult(mediaItems);
+ }
+
+ public void sendDelayedNotifyChildrenChanged() {
+ if (mPendingResult != null) {
+ mPendingResult.sendResult(Collections.<MediaItem>emptyList());
+ mPendingResult = null;
+ }
}
}
diff --git a/tests/tests/security/src/android/security/cts/CertificateData.java b/tests/tests/security/src/android/security/cts/CertificateData.java
index 5122f24..0c311e0 100644
--- a/tests/tests/security/src/android/security/cts/CertificateData.java
+++ b/tests/tests/security/src/android/security/cts/CertificateData.java
@@ -164,7 +164,6 @@
"9D:70:BB:01:A5:A4:A0:18:11:2E:F7:1C:01:B9:32:C5:34:E7:88:A8",
"96:C9:1B:0B:95:B4:10:98:42:FA:D0:D8:22:79:FE:60:FA:B9:16:83",
"D8:A6:33:2C:E0:03:6F:B1:85:F6:63:4F:7D:6A:06:65:26:32:28:27",
- "9F:AD:91:A6:CE:6A:C6:C5:00:47:C4:4E:C9:D4:A5:0D:92:D8:49:79",
"CC:AB:0E:A0:4C:23:01:D6:69:7B:DD:37:9F:CD:12:EB:24:E3:94:9D",
"48:12:BD:92:3C:A8:C4:39:06:E7:30:6D:27:96:E6:A4:CF:22:2E:7D",
"F9:B5:B6:32:45:5F:9C:BE:EC:57:5F:80:DC:E9:6E:2C:C7:B2:78:B7",
diff --git a/tests/tests/telecom/src/android/telecom/cts/BaseTelecomTestWithMockServices.java b/tests/tests/telecom/src/android/telecom/cts/BaseTelecomTestWithMockServices.java
new file mode 100644
index 0000000..a569058
--- /dev/null
+++ b/tests/tests/telecom/src/android/telecom/cts/BaseTelecomTestWithMockServices.java
@@ -0,0 +1,423 @@
+/*
+ * 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.content.ComponentName;
+import android.content.Context;
+import android.graphics.Color;
+import android.net.Uri;
+import android.os.Bundle;
+import android.telecom.Call;
+import android.telecom.CallAudioState;
+import android.telecom.Connection;
+import android.telecom.ConnectionRequest;
+import android.telecom.InCallService;
+import android.telecom.PhoneAccount;
+import android.telecom.PhoneAccountHandle;
+import android.telecom.TelecomManager;
+import android.telecom.cts.MockConnectionService.ConnectionServiceCallbacks;
+import android.telecom.cts.MockInCallService.InCallServiceCallbacks;
+import android.test.InstrumentationTestCase;
+import android.text.TextUtils;
+import android.util.Log;
+
+import java.util.Arrays;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Base class for Telecom CTS tests that require a {@link MockConnectionService} and
+ * {@link MockInCallService} to verify Telecom functionality.
+ */
+public class BaseTelecomTestWithMockServices extends InstrumentationTestCase {
+ public static final PhoneAccountHandle TEST_PHONE_ACCOUNT_HANDLE =
+ new PhoneAccountHandle(new ComponentName(PACKAGE, COMPONENT), ACCOUNT_ID);
+
+ public static final PhoneAccount TEST_PHONE_ACCOUNT = PhoneAccount.builder(
+ TEST_PHONE_ACCOUNT_HANDLE, LABEL)
+ .setAddress(Uri.parse("tel:555-TEST"))
+ .setSubscriptionAddress(Uri.parse("tel:555-TEST"))
+ .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
+ .setHighlightColor(Color.RED)
+ .setShortDescription(LABEL)
+ .setSupportedUriSchemes(Arrays.asList("tel"))
+ .build();
+
+ private static int sCounter = 0;
+
+ Context mContext;
+ TelecomManager mTelecomManager;
+ InCallServiceCallbacks mInCallCallbacks;
+ ConnectionServiceCallbacks mConnectionCallbacks;
+ String mPreviousDefaultDialer = null;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mContext = getInstrumentation().getContext();
+ mTelecomManager = (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
+
+ if (shouldTestTelecom(mContext)) {
+ mTelecomManager.registerPhoneAccount(TEST_PHONE_ACCOUNT);
+ TestUtils.enablePhoneAccount(getInstrumentation(), TEST_PHONE_ACCOUNT_HANDLE);
+ mPreviousDefaultDialer = TestUtils.getDefaultDialer(getInstrumentation());
+ TestUtils.setDefaultDialer(getInstrumentation(), PACKAGE);
+ setupCallbacks();
+ }
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ if (shouldTestTelecom(mContext)) {
+ if (!TextUtils.isEmpty(mPreviousDefaultDialer)) {
+ TestUtils.setDefaultDialer(getInstrumentation(), mPreviousDefaultDialer);
+ }
+ mTelecomManager.unregisterPhoneAccount(TEST_PHONE_ACCOUNT_HANDLE);
+ }
+ super.tearDown();
+ }
+
+ private void sleep(long ms) {
+ try {
+ Thread.sleep(ms);
+ } catch (InterruptedException e) {
+ }
+ }
+
+ private void setupCallbacks() {
+ mInCallCallbacks = new InCallServiceCallbacks() {
+ @Override
+ public void onCallAdded(Call call, int numCalls) {
+ this.lock.release();
+ }
+ };
+
+ MockInCallService.setCallbacks(mInCallCallbacks);
+
+ mConnectionCallbacks = new ConnectionServiceCallbacks() {
+ @Override
+ public void onCreateOutgoingConnection(MockConnection connection,
+ ConnectionRequest request) {
+ this.lock.release();
+ }
+
+ @Override
+ public void onCreateIncomingConnection(MockConnection connection,
+ ConnectionRequest request) {
+ this.lock.release();
+ }
+ };
+
+ MockConnectionService.setCallbacks(mConnectionCallbacks);
+ }
+
+ /**
+ * Puts Telecom in a state where there is an incoming call provided by the
+ * {@link MockConnectionService} which can be tested.
+ */
+ void addAndVerifyNewIncomingCall(Uri incomingHandle, Bundle extras) {
+ if (extras == null) {
+ extras = new Bundle();
+ }
+ extras.putParcelable(TelecomManager.EXTRA_INCOMING_CALL_ADDRESS, incomingHandle);
+ mTelecomManager.addNewIncomingCall(TEST_PHONE_ACCOUNT_HANDLE, extras);
+
+ try {
+ if (!mInCallCallbacks.lock.tryAcquire(3, TimeUnit.SECONDS)) {
+ fail("No call added to InCallService.");
+ }
+ } catch (InterruptedException e) {
+ Log.i(TAG, "Test interrupted!");
+ }
+
+ assertEquals("InCallService should contain 1 call after adding a call.", 1,
+ mInCallCallbacks.getService().getCallCount());
+ }
+
+ /**
+ * Puts Telecom in a state where there is an active call provided by the
+ * {@link MockConnectionService} which can be tested.
+ */
+ void placeAndVerifyCall() {
+ placeAndVerifyCall(null);
+ }
+
+ /**
+ * Puts Telecom in a state where there is an active call provided by the
+ * {@link MockConnectionService} which can be tested.
+ */
+ void placeAndVerifyCall(Bundle extras) {
+ placeNewCallWithPhoneAccount(extras);
+
+ try {
+ if (!mInCallCallbacks.lock.tryAcquire(3, TimeUnit.SECONDS)) {
+ fail("No call added to InCallService.");
+ }
+ } catch (InterruptedException e) {
+ Log.i(TAG, "Test interrupted!");
+ }
+
+ assertEquals("InCallService should contain 1 call after adding a call.", 1,
+ mInCallCallbacks.getService().getCallCount());
+ }
+
+ void verifyConnectionForOutgoingCall() {
+ try {
+ if (!mConnectionCallbacks.lock.tryAcquire(3, TimeUnit.SECONDS)) {
+ fail("No outgoing call connection requested by Telecom");
+ }
+ } catch (InterruptedException e) {
+ Log.i(TAG, "Test interrupted!");
+ }
+
+ assertNotNull("Telecom should bind to and create ConnectionService",
+ mConnectionCallbacks.getService());
+ assertNotNull("Telecom should create outgoing connection for outgoing call",
+ mConnectionCallbacks.outgoingConnection);
+ assertNull("Telecom should not create incoming connection for outgoing call",
+ mConnectionCallbacks.incomingConnection);
+
+ final MockConnection connection = mConnectionCallbacks.outgoingConnection;
+ connection.setDialing();
+ connection.setActive();
+
+ assertEquals(Connection.STATE_ACTIVE, connection.getState());
+ }
+
+ void verifyConnectionForIncomingCall() {
+ try {
+ if (!mConnectionCallbacks.lock.tryAcquire(3, TimeUnit.SECONDS)) {
+ fail("No incoming call connection requested by Telecom");
+ }
+ } catch (InterruptedException e) {
+ Log.i(TAG, "Test interrupted!");
+ }
+
+ assertNotNull("Telecom should bind to and create ConnectionService",
+ mConnectionCallbacks.getService());
+ assertNull("Telecom should not create outgoing connection for outgoing call",
+ mConnectionCallbacks.outgoingConnection);
+ assertNotNull("Telecom should create incoming connection for outgoing call",
+ mConnectionCallbacks.incomingConnection);
+
+ final MockConnection connection = mConnectionCallbacks.incomingConnection;
+ connection.setRinging();
+ assertEquals(Connection.STATE_RINGING, connection.getState());
+ }
+
+ /**
+ * Disconnect the created test call, verify that Telecom has cleared all calls and has
+ * unbound from the {@link ConnectionService}.
+ */
+ void cleanupAndVerifyUnbind() {
+ if (mInCallCallbacks != null && mInCallCallbacks.getService() != null) {
+ mInCallCallbacks.prepareForUnbind();
+
+ mInCallCallbacks.getService().disconnectLastCall();
+ assertNumCalls(mInCallCallbacks.getService(), 0);
+
+ try {
+ if (!mInCallCallbacks.unbindLock.tryAcquire(3, TimeUnit.SECONDS)) {
+ fail("Telecom did not unbind from InCallService after all calls removed.");
+ }
+ } catch (InterruptedException e) {
+ Log.i(TAG, "Test interrupted!");
+ }
+ }
+ }
+
+ /**
+ * Place a new outgoing call via the {@link MockConnectionService}
+ */
+ private void placeNewCallWithPhoneAccount(Bundle extras) {
+ if (extras == null) {
+ extras = new Bundle();
+ }
+ extras.putParcelable(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, TEST_PHONE_ACCOUNT_HANDLE);
+ mTelecomManager.placeCall(getTestNumber(), extras);
+ }
+
+ /**
+ * Create a new number each time for a new test. Telecom has special logic to reuse certain
+ * calls if multiple calls to the same number are placed within a short period of time which
+ * can cause certain tests to fail.
+ */
+ Uri getTestNumber() {
+ return Uri.fromParts("tel", String.valueOf(sCounter++), null);
+ }
+
+ void assertNumCalls(final MockInCallService inCallService, final int numCalls) {
+ waitUntilConditionIsTrueOrTimeout(new Condition() {
+ @Override
+ public Object expected() {
+ return numCalls;
+ }
+ @Override
+ public Object actual() {
+ return inCallService.getCallCount();
+ }
+ },
+ WAIT_FOR_STATE_CHANGE_TIMEOUT_MS,
+ "InCallService should contain " + numCalls + " calls."
+ );
+ }
+
+ void assertMuteState(final InCallService incallService, final boolean isMuted) {
+ waitUntilConditionIsTrueOrTimeout(
+ new Condition() {
+ @Override
+ public Object expected() {
+ return isMuted;
+ }
+
+ @Override
+ public Object actual() {
+ final CallAudioState state = incallService.getCallAudioState();
+ return state == null ? null : state.isMuted();
+ }
+ },
+ WAIT_FOR_STATE_CHANGE_TIMEOUT_MS,
+ "Phone's mute state should be: " + isMuted
+ );
+ }
+
+ void assertMuteState(final MockConnection connection, final boolean isMuted) {
+ waitUntilConditionIsTrueOrTimeout(
+ new Condition() {
+ @Override
+ public Object expected() {
+ return isMuted;
+ }
+
+ @Override
+ public Object actual() {
+ final CallAudioState state = connection.getCallAudioState();
+ return state == null ? null : state.isMuted();
+ }
+ },
+ WAIT_FOR_STATE_CHANGE_TIMEOUT_MS,
+ "Connection's mute state should be: " + isMuted
+ );
+ }
+
+ void assertAudioRoute(final InCallService incallService, final int route) {
+ waitUntilConditionIsTrueOrTimeout(
+ new Condition() {
+ @Override
+ public Object expected() {
+ return route;
+ }
+
+ @Override
+ public Object actual() {
+ final CallAudioState state = incallService.getCallAudioState();
+ return state == null ? null : state.getRoute();
+ }
+ },
+ WAIT_FOR_STATE_CHANGE_TIMEOUT_MS,
+ "Phone's audio route should be: " + route
+ );
+ }
+
+ void assertAudioRoute(final MockConnection connection, final int route) {
+ waitUntilConditionIsTrueOrTimeout(
+ new Condition() {
+ @Override
+ public Object expected() {
+ return route;
+ }
+
+ @Override
+ public Object actual() {
+ final CallAudioState state = connection.getCallAudioState();
+ return state == null ? null : state.getRoute();
+ }
+ },
+ WAIT_FOR_STATE_CHANGE_TIMEOUT_MS,
+ "Connection's audio route should be: " + route
+ );
+ }
+
+ void assertConnectionState(final Connection connection, final int state) {
+ waitUntilConditionIsTrueOrTimeout(
+ new Condition() {
+ @Override
+ public Object expected() {
+ return state;
+ }
+
+ @Override
+ public Object actual() {
+ return connection.getState();
+ }
+ },
+ WAIT_FOR_STATE_CHANGE_TIMEOUT_MS,
+ "Connection should be in state " + state
+ );
+ }
+
+ void assertCallState(final Call call, final int state) {
+ waitUntilConditionIsTrueOrTimeout(
+ new Condition() {
+ @Override
+ public Object expected() {
+ return state;
+ }
+
+ @Override
+ public Object actual() {
+ return call.getState();
+ }
+ },
+ WAIT_FOR_STATE_CHANGE_TIMEOUT_MS,
+ "Call should be in state " + state
+ );
+ }
+
+ void assertDtmfString(final MockConnection connection, final String dtmfString) {
+ waitUntilConditionIsTrueOrTimeout(new Condition() {
+ @Override
+ public Object expected() {
+ return dtmfString;
+ }
+
+ @Override
+ public Object actual() {
+ return connection.getDtmfString();
+ }
+ },
+ WAIT_FOR_STATE_CHANGE_TIMEOUT_MS,
+ "DTMF string should be equivalent to entered DTMF characters: " + dtmfString
+ );
+ }
+
+ void waitUntilConditionIsTrueOrTimeout(Condition condition, long timeout,
+ String description) {
+ final long start = System.currentTimeMillis();
+ while (!condition.expected().equals(condition.actual())
+ && System.currentTimeMillis() - start < timeout) {
+ sleep(50);
+ }
+ assertEquals(description, condition.expected(), condition.actual());
+ }
+
+ private interface Condition {
+ Object expected();
+ Object actual();
+ }
+}
diff --git a/tests/tests/telecom/src/android/telecom/cts/ExtendedInCallServiceTest.java b/tests/tests/telecom/src/android/telecom/cts/ExtendedInCallServiceTest.java
index 1a9d8d7..c4ec5c4 100644
--- a/tests/tests/telecom/src/android/telecom/cts/ExtendedInCallServiceTest.java
+++ b/tests/tests/telecom/src/android/telecom/cts/ExtendedInCallServiceTest.java
@@ -18,85 +18,30 @@
import static android.telecom.cts.TestUtils.*;
-import android.telecom.cts.MockConnectionService.ConnectionServiceCallbacks;
-import android.telecom.cts.MockInCallService.InCallServiceCallbacks;
-
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.graphics.Color;
-import android.net.Uri;
import android.telecom.CallAudioState;
import android.telecom.Call;
import android.telecom.Connection;
-import android.telecom.ConnectionRequest;
import android.telecom.ConnectionService;
import android.telecom.InCallService;
-import android.telecom.PhoneAccount;
-import android.telecom.PhoneAccountHandle;
-import android.telecom.TelecomManager;
-import android.test.InstrumentationTestCase;
-import android.text.TextUtils;
-import android.util.Log;
-
-import java.util.Arrays;
-import java.util.concurrent.TimeUnit;
/**
- * Extended suite of tests that use {@MockConnectionService} and {@MockInCallService} to verify
- * the functionality of the Telecom service. Requires that the version of GmsCore installed on the
- * device has the REGISTER_CALL_PROVIDER permission.
+ * Extended suite of tests that use {@link MockConnectionService} and {@link MockInCallService} to
+ * verify the functionality of the Telecom service.
*/
-public class ExtendedInCallServiceTest extends InstrumentationTestCase {
- public static final PhoneAccountHandle TEST_PHONE_ACCOUNT_HANDLE =
- new PhoneAccountHandle(new ComponentName(PACKAGE, COMPONENT), ACCOUNT_ID);
-
- public static final PhoneAccount TEST_PHONE_ACCOUNT = PhoneAccount.builder(
- TEST_PHONE_ACCOUNT_HANDLE, LABEL)
- .setAddress(Uri.parse("tel:555-TEST"))
- .setSubscriptionAddress(Uri.parse("tel:555-TEST"))
- .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
- .setHighlightColor(Color.RED)
- .setShortDescription(LABEL)
- .setSupportedUriSchemes(Arrays.asList("tel"))
- .build();
-
- private Context mContext;
- private TelecomManager mTelecomManager;
- private InCallServiceCallbacks mInCallCallbacks;
- private ConnectionServiceCallbacks mConnectionCallbacks;
- private String mPreviousDefaultDialer = null;
-
- private static int sCounter = 0;
-
+public class ExtendedInCallServiceTest extends BaseTelecomTestWithMockServices {
@Override
protected void setUp() throws Exception {
super.setUp();
- mContext = getInstrumentation().getContext();
- mTelecomManager = (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
-
if (shouldTestTelecom(mContext)) {
- mTelecomManager.registerPhoneAccount(TEST_PHONE_ACCOUNT);
- TestUtils.enablePhoneAccount(getInstrumentation(), TEST_PHONE_ACCOUNT_HANDLE);
- mPreviousDefaultDialer = TestUtils.getDefaultDialer(getInstrumentation());
- TestUtils.setDefaultDialer(getInstrumentation(), PACKAGE);
- setupCallbacks();
placeAndVerifyCall();
- verifyConnectionService();
+ verifyConnectionForOutgoingCall();
}
}
@Override
protected void tearDown() throws Exception {
if (shouldTestTelecom(mContext)) {
- if (mInCallCallbacks != null && mInCallCallbacks.getService() != null) {
- mInCallCallbacks.getService().disconnectLastCall();
- assertNumCalls(mInCallCallbacks.getService(), 0);
- }
- if (!TextUtils.isEmpty(mPreviousDefaultDialer)) {
- TestUtils.setDefaultDialer(getInstrumentation(), mPreviousDefaultDialer);
- }
- mTelecomManager.unregisterPhoneAccount(TEST_PHONE_ACCOUNT_HANDLE);
+ cleanupAndVerifyUnbind();
}
super.tearDown();
}
@@ -208,232 +153,4 @@
assertCallState(call, Call.STATE_ACTIVE);
assertEquals(Connection.STATE_ACTIVE, connection.getState());
}
-
- private void sleep(long ms) {
- try {
- Thread.sleep(ms);
- } catch (InterruptedException e) {
- }
- }
-
- private void setupCallbacks() {
- mInCallCallbacks = new InCallServiceCallbacks() {
- @Override
- public void onCallAdded(Call call, int numCalls) {
- this.lock.release();
- }
- };
-
- MockInCallService.setCallbacks(mInCallCallbacks);
-
- mConnectionCallbacks = new ConnectionServiceCallbacks() {
- @Override
- public void onCreateOutgoingConnection(MockConnection connection,
- ConnectionRequest request) {
- this.lock.release();
- }
- };
-
- MockConnectionService.setCallbacks(mConnectionCallbacks);
- }
-
- /**
- * Puts Telecom in a state where there is an active call provided by the
- * {@link MockConnectionService} which can be tested.
- */
- private void placeAndVerifyCall() {
- placeNewCallWithPhoneAccount();
-
- try {
- if (!mInCallCallbacks.lock.tryAcquire(3, TimeUnit.SECONDS)) {
- fail("No call added to InCallService.");
- }
- } catch (InterruptedException e) {
- Log.i(TAG, "Test interrupted!");
- }
-
- assertEquals("InCallService should contain 1 call after adding a call.", 1,
- mInCallCallbacks.getService().getCallCount());
- assertTrue("TelecomManager should be in a call", mTelecomManager.isInCall());
- }
-
- private void verifyConnectionService() {
- try {
- if (!mConnectionCallbacks.lock.tryAcquire(3, TimeUnit.SECONDS)) {
- fail("No outgoing call connection requested by Telecom");
- }
- } catch (InterruptedException e) {
- Log.i(TAG, "Test interrupted!");
- }
-
- assertNotNull("Telecom should bind to and create ConnectionService",
- mConnectionCallbacks.getService());
- assertNotNull("Telecom should create outgoing connection for outgoing call",
- mConnectionCallbacks.outgoingConnection);
- assertNull("Telecom should not create incoming connection for outgoing call",
- mConnectionCallbacks.incomingConnection);
-
- final MockConnection connection = mConnectionCallbacks.outgoingConnection;
- connection.setDialing();
- connection.setActive();
-
- assertEquals(Connection.STATE_ACTIVE, connection.getState());
- }
-
- /**
- * Place a new outgoing call via the {@link MockConnectionService}
- */
- private void placeNewCallWithPhoneAccount() {
- final Intent intent = new Intent(Intent.ACTION_CALL, getTestNumber());
- intent.putExtra(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, TEST_PHONE_ACCOUNT_HANDLE);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- mContext.startActivity(intent);
- }
-
- /**
- * Create a new number each time for a new test. Telecom has special logic to reuse certain
- * calls if multiple calls to the same number are placed within a short period of time which
- * can cause certain tests to fail.
- */
- private Uri getTestNumber() {
- return Uri.fromParts("tel", String.valueOf(sCounter++), null);
- }
-
- private void assertNumCalls(final MockInCallService inCallService, final int numCalls) {
- waitUntilConditionIsTrueOrTimeout(new Condition() {
- @Override
- public Object expected() {
- return numCalls;
- }
- @Override
- public Object actual() {
- return inCallService.getCallCount();
- }
- },
- WAIT_FOR_STATE_CHANGE_TIMEOUT_MS,
- "InCallService should contain " + numCalls + " calls."
- );
- }
-
- private void assertMuteState(final InCallService incallService, final boolean isMuted) {
- waitUntilConditionIsTrueOrTimeout(
- new Condition() {
- @Override
- public Object expected() {
- return isMuted;
- }
-
- @Override
- public Object actual() {
- return incallService.getCallAudioState().isMuted();
- }
- },
- WAIT_FOR_STATE_CHANGE_TIMEOUT_MS,
- "Phone's mute state should be: " + isMuted
- );
- }
-
- private void assertMuteState(final MockConnection connection, final boolean isMuted) {
- waitUntilConditionIsTrueOrTimeout(
- new Condition() {
- @Override
- public Object expected() {
- return isMuted;
- }
-
- @Override
- public Object actual() {
- return connection.getCallAudioState().isMuted();
- }
- },
- WAIT_FOR_STATE_CHANGE_TIMEOUT_MS,
- "Connection's mute state should be: " + isMuted
- );
- }
-
- private void assertAudioRoute(final InCallService incallService, final int route) {
- waitUntilConditionIsTrueOrTimeout(
- new Condition() {
- @Override
- public Object expected() {
- return route;
- }
-
- @Override
- public Object actual() {
- return incallService.getCallAudioState().getRoute();
- }
- },
- WAIT_FOR_STATE_CHANGE_TIMEOUT_MS,
- "Phone's audio route should be: " + route
- );
- }
-
- private void assertAudioRoute(final MockConnection connection, final int route) {
- waitUntilConditionIsTrueOrTimeout(
- new Condition() {
- @Override
- public Object expected() {
- return route;
- }
-
- @Override
- public Object actual() {
- return connection.getCallAudioState().getRoute();
- }
- },
- WAIT_FOR_STATE_CHANGE_TIMEOUT_MS,
- "Connection's audio route should be: " + route
- );
- }
-
- private void assertCallState(final Call call, final int state) {
- waitUntilConditionIsTrueOrTimeout(
- new Condition() {
- @Override
- public Object expected() {
- return state;
- }
-
- @Override
- public Object actual() {
- return call.getState();
- }
- },
- WAIT_FOR_STATE_CHANGE_TIMEOUT_MS,
- "Call should be in state " + state
- );
- }
-
- private void assertDtmfString(final MockConnection connection, final String dtmfString) {
- waitUntilConditionIsTrueOrTimeout(new Condition() {
- @Override
- public Object expected() {
- return dtmfString;
- }
-
- @Override
- public Object actual() {
- return connection.getDtmfString();
- }
- },
- WAIT_FOR_STATE_CHANGE_TIMEOUT_MS,
- "DTMF string should be equivalent to entered DTMF characters: " + dtmfString
- );
- }
-
- private void waitUntilConditionIsTrueOrTimeout(Condition condition, long timeout,
- String description) {
- final long start = System.currentTimeMillis();
- while (!condition.expected().equals(condition.actual())
- && System.currentTimeMillis() - start < timeout) {
- sleep(50);
- }
- assertEquals(description, condition.expected(), condition.actual());
- }
-
- private interface Condition {
- Object expected();
- Object actual();
- }
}
diff --git a/tests/tests/telecom/src/android/telecom/cts/MockInCallService.java b/tests/tests/telecom/src/android/telecom/cts/MockInCallService.java
index cecc603..3c48ddd 100644
--- a/tests/tests/telecom/src/android/telecom/cts/MockInCallService.java
+++ b/tests/tests/telecom/src/android/telecom/cts/MockInCallService.java
@@ -16,6 +16,7 @@
package android.telecom.cts;
+import android.content.Intent;
import android.telecom.Call;
import android.telecom.InCallService;
@@ -31,6 +32,7 @@
public static abstract class InCallServiceCallbacks {
private MockInCallService mService;
public Semaphore lock = new Semaphore(0);
+ public Semaphore unbindLock = null;
public void onCallAdded(Call call, int numCalls) {};
public void onCallRemoved(Call call, int numCalls) {};
@@ -43,6 +45,10 @@
final public void setService(MockInCallService service) {
mService = service;
}
+
+ final public void prepareForUnbind() {
+ unbindLock = new Semaphore(0);
+ }
}
private Call.Callback mCallCallback = new Call.Callback() {
@@ -63,6 +69,14 @@
}
@Override
+ public boolean onUnbind(Intent intent) {
+ if (getCallbacks() != null && getCallbacks().unbindLock != null) {
+ getCallbacks().unbindLock.release();
+ }
+ return super.onUnbind(intent);
+ }
+
+ @Override
public void onCallAdded(Call call) {
if (!mCalls.contains(call)) {
mCalls.add(call);
diff --git a/tests/tests/telecom/src/android/telecom/cts/OutgoingCallTest.java b/tests/tests/telecom/src/android/telecom/cts/OutgoingCallTest.java
new file mode 100644
index 0000000..5895267
--- /dev/null
+++ b/tests/tests/telecom/src/android/telecom/cts/OutgoingCallTest.java
@@ -0,0 +1,75 @@
+/*
+ * 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.shouldTestTelecom;
+
+import android.os.Bundle;
+import android.telecom.CallAudioState;
+import android.telecom.TelecomManager;
+
+/**
+ * Verifies the behavior of Telecom during various outgoing call flows.
+ */
+public class OutgoingCallTest extends BaseTelecomTestWithMockServices {
+
+ @Override
+ protected void tearDown() throws Exception {
+ if (shouldTestTelecom(mContext)) {
+ cleanupAndVerifyUnbind();
+ }
+ super.tearDown();
+ }
+
+ // TODO: Need to send some commands to the UserManager via adb to do setup
+ public void testDisallowOutgoingCallsForSecondaryUser() {
+
+ }
+
+ // TODO: Need to figure out a way to mock emergency calls without adb root
+ public void testOutgoingCallBroadcast_isSentForAllCalls() {
+
+ }
+
+ /**
+ * Verifies that providing the EXTRA_START_CALL_WITH_SPEAKERPHONE extra starts the call with
+ * speakerphone automatically enabled.
+ *
+ * @see {@link TelecomManager#EXTRA_START_CALL_WITH_SPEAKERPHONE}
+ */
+ public void testStartCallWithSpeakerphoneTrue_SpeakerphoneOnInCall() {
+ final Bundle extras = new Bundle();
+ extras.putBoolean(TelecomManager.EXTRA_START_CALL_WITH_SPEAKERPHONE, true);
+ placeAndVerifyCall(extras);
+ verifyConnectionForOutgoingCall();
+ assertAudioRoute(mInCallCallbacks.getService(), CallAudioState.ROUTE_SPEAKER);
+ }
+
+ public void testStartCallWithSpeakerphoneFalse_SpeakerphoneOffInCall() {
+ final Bundle extras = new Bundle();
+ extras.putBoolean(TelecomManager.EXTRA_START_CALL_WITH_SPEAKERPHONE, false);
+ placeAndVerifyCall(extras);
+ verifyConnectionForOutgoingCall();
+ assertAudioRoute(mInCallCallbacks.getService(), CallAudioState.ROUTE_EARPIECE);
+ }
+
+ public void testStartCallWithSpeakerphoneNotProvided_SpeakerphoneOffByDefault() {
+ placeAndVerifyCall();
+ verifyConnectionForOutgoingCall();
+ assertAudioRoute(mInCallCallbacks.getService(), CallAudioState.ROUTE_EARPIECE);
+ }
+}
diff --git a/tests/tests/telecom/src/android/telecom/cts/WiredHeadsetTest.java b/tests/tests/telecom/src/android/telecom/cts/WiredHeadsetTest.java
new file mode 100644
index 0000000..4e154cf
--- /dev/null
+++ b/tests/tests/telecom/src/android/telecom/cts/WiredHeadsetTest.java
@@ -0,0 +1,118 @@
+/*
+ * 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 android.telecom.Call;
+import android.telecom.CallAudioState;
+import android.telecom.Connection;
+
+/**
+ * Verifies Telecom behavior with regards to interactions with a wired headset. These tests
+ * validate behavior that occurs as a result of short pressing or long pressing a wired headset's
+ * media button.
+ */
+public class WiredHeadsetTest extends BaseTelecomTestWithMockServices {
+ @Override
+ protected void tearDown() throws Exception {
+ if (mInCallCallbacks != null && mInCallCallbacks.getService() != null) {
+ mInCallCallbacks.getService().disconnectLastCall();
+ assertNumCalls(mInCallCallbacks.getService(), 0);
+ }
+ super.tearDown();
+ }
+
+ public void testIncomingCallShortPress_acceptsCall() throws Exception {
+ addAndVerifyNewIncomingCall(getTestNumber(), null);
+ verifyConnectionForIncomingCall();
+
+ final MockConnection connection = mConnectionCallbacks.incomingConnection;
+ final Call call = mInCallCallbacks.getService().getLastCall();
+ assertCallState(call, Call.STATE_RINGING);
+ assertConnectionState(connection, Connection.STATE_RINGING);
+
+ sendMediaButtonShortPress();
+ assertCallState(call, Call.STATE_ACTIVE);
+ assertConnectionState(connection, Connection.STATE_ACTIVE);
+ }
+
+ public void testIncomingCallLongPress_rejectsCall() throws Exception {
+ addAndVerifyNewIncomingCall(getTestNumber(), null);
+ verifyConnectionForIncomingCall();
+
+ final MockConnection connection = mConnectionCallbacks.incomingConnection;
+ final Call call = mInCallCallbacks.getService().getLastCall();
+ assertCallState(call, Call.STATE_RINGING);
+ assertConnectionState(connection, Connection.STATE_RINGING);
+
+ sendMediaButtonLongPress();
+ assertCallState(call, Call.STATE_DISCONNECTED);
+ assertConnectionState(connection, Connection.STATE_DISCONNECTED);
+ }
+
+ public void testInCallShortPress_togglesMute() throws Exception {
+ placeAndVerifyCall();
+ verifyConnectionForOutgoingCall();
+ final MockConnection connection = mConnectionCallbacks.outgoingConnection;
+ final MockInCallService incallService = mInCallCallbacks.getService();
+
+ // Verify that sending short presses in succession toggles the mute state of the
+ // connection.
+ // Before the audio state is changed for the first time, the connection might not
+ // know about its audio state yet.
+ assertMuteState(incallService, false);
+ sendMediaButtonShortPress();
+ assertMuteState(connection, true);
+ assertMuteState(incallService, true);
+ sendMediaButtonShortPress();
+ assertMuteState(connection, false);
+ assertMuteState(incallService, false);
+ }
+
+ public void testInCallLongPress_hangupCall() throws Exception {
+ placeAndVerifyCall();
+ verifyConnectionForOutgoingCall();
+
+ final MockConnection connection = mConnectionCallbacks.outgoingConnection;
+ final Call call = mInCallCallbacks.getService().getLastCall();
+ assertCallState(call, Call.STATE_ACTIVE);
+ assertConnectionState(connection, Connection.STATE_ACTIVE);
+
+ sendMediaButtonLongPress();
+ assertCallState(call, Call.STATE_DISCONNECTED);
+ assertConnectionState(connection, Connection.STATE_DISCONNECTED);
+ }
+
+ public void testStartCallWithSpeakerphoneNotProvided_SpeakerphoneOffByDefault() {
+ placeAndVerifyCall();
+ verifyConnectionForOutgoingCall();
+ assertAudioRoute(mInCallCallbacks.getService(), CallAudioState.ROUTE_EARPIECE);
+ }
+
+ private void sendMediaButtonShortPress() throws Exception {
+ sendMediaButtonPress(false /* longPress */);
+ }
+
+ private void sendMediaButtonLongPress() throws Exception {
+ sendMediaButtonPress(true /* longPress */);
+ }
+
+ private void sendMediaButtonPress(boolean longPress) throws Exception {
+ final String command = "input keyevent " + (longPress ? "--longpress" : "--shortpress")
+ + " KEYCODE_HEADSETHOOK";
+ TestUtils.executeShellCommand(getInstrumentation(), command);
+ }
+}
diff --git a/tests/tests/telephony/src/android/telephony/cts/SmsUsageMonitorShortCodeTest.java b/tests/tests/telephony/src/android/telephony/cts/SmsUsageMonitorShortCodeTest.java
index 0527e9a..145cc84 100644
--- a/tests/tests/telephony/src/android/telephony/cts/SmsUsageMonitorShortCodeTest.java
+++ b/tests/tests/telephony/src/android/telephony/cts/SmsUsageMonitorShortCodeTest.java
@@ -299,7 +299,7 @@
new ShortCodeTest("it", "112", CATEGORY_NOT_SHORT_CODE),
new ShortCodeTest("it", "116117", CATEGORY_FREE_SHORT_CODE),
new ShortCodeTest("it", "4567", CATEGORY_NOT_SHORT_CODE),
- new ShortCodeTest("it", "48000", CATEGORY_PREMIUM_SHORT_CODE),
+ new ShortCodeTest("it", "48000", CATEGORY_FREE_SHORT_CODE),
new ShortCodeTest("it", "45678", CATEGORY_PREMIUM_SHORT_CODE),
new ShortCodeTest("it", "56789", CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE),
new ShortCodeTest("it", "456789", CATEGORY_NOT_SHORT_CODE),
diff --git a/tests/tests/telephony/src/android/telephony/cts/TelephonyManagerTest.java b/tests/tests/telephony/src/android/telephony/cts/TelephonyManagerTest.java
index 8575c32..2be1dcb 100644
--- a/tests/tests/telephony/src/android/telephony/cts/TelephonyManagerTest.java
+++ b/tests/tests/telephony/src/android/telephony/cts/TelephonyManagerTest.java
@@ -81,9 +81,11 @@
mListener = new PhoneStateListener() {
@Override
public void onCellLocationChanged(CellLocation location) {
- synchronized (mLock) {
- mOnCellLocationChangedCalled = true;
- mLock.notify();
+ if(!mOnCellLocationChangedCalled) {
+ synchronized (mLock) {
+ mOnCellLocationChangedCalled = true;
+ mLock.notify();
+ }
}
}
};
diff --git a/tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTest.java b/tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTest.java
old mode 100644
new mode 100755
index d267d63..3c6028f
--- a/tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTest.java
+++ b/tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTest.java
@@ -115,6 +115,9 @@
// Wait for things to settle.
getUiDevice().waitForIdle();
+ // Wait for Activity draw finish
+ getInstrumentation().waitForIdleSync();
+
// Find the application window.
final int windowId = findAppWindowId(uiAutomation.getWindows());
assertTrue(windowId >= 0);