Merge "Added CTS tests for AudioDeviceInfo accessors." into mnc-dev
diff --git a/hostsidetests/devicepolicy/app/IntentSender/Android.mk b/hostsidetests/devicepolicy/app/IntentSender/Android.mk
index e5246c5..21d2866 100644
--- a/hostsidetests/devicepolicy/app/IntentSender/Android.mk
+++ b/hostsidetests/devicepolicy/app/IntentSender/Android.mk
@@ -24,9 +24,7 @@
LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_JAVA_LIBRARIES := android.test.runner
-
-LOCAL_STATIC_JAVA_LIBRARIES := android-support-v4 ctstestrunner
+LOCAL_JAVA_LIBRARIES := android.test.runner android-support-v4
LOCAL_SDK_VERSION := current
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/Android.mk b/hostsidetests/devicepolicy/app/ManagedProfile/Android.mk
index f4adb31..b74a7b6 100644
--- a/hostsidetests/devicepolicy/app/ManagedProfile/Android.mk
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/Android.mk
@@ -24,9 +24,9 @@
LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_JAVA_LIBRARIES := android.test.runner cts-junit
+LOCAL_JAVA_LIBRARIES := android.test.runner cts-junit android-support-v4
-LOCAL_STATIC_JAVA_LIBRARIES = android-support-v4 ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
LOCAL_SDK_VERSION := current
diff --git a/hostsidetests/devicepolicy/app/SimpleApp/AndroidManifest.xml b/hostsidetests/devicepolicy/app/SimpleApp/AndroidManifest.xml
index 848317c..af74f57 100644
--- a/hostsidetests/devicepolicy/app/SimpleApp/AndroidManifest.xml
+++ b/hostsidetests/devicepolicy/app/SimpleApp/AndroidManifest.xml
@@ -31,6 +31,18 @@
<activity android:name=".NonLauncherActivity">
android:exported="true">
</activity>
+ <activity android:name=".SimpleActivityImmediateExit" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ <activity android:name=".SimpleActivityChainExit" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
</application>
</manifest>
diff --git a/hostsidetests/devicepolicy/app/SimpleApp/src/com/android/cts/launcherapps/simpleapp/SimpleActivityChainExit.java b/hostsidetests/devicepolicy/app/SimpleApp/src/com/android/cts/launcherapps/simpleapp/SimpleActivityChainExit.java
new file mode 100644
index 0000000..49f14da
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/SimpleApp/src/com/android/cts/launcherapps/simpleapp/SimpleActivityChainExit.java
@@ -0,0 +1,80 @@
+/*
+ * 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.launcherapps.simpleapp;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.util.Log;
+
+/**
+ * This activity starts another activity. Once the other activity gets terminated, this one will
+ * terminate as well.
+ */
+public class SimpleActivityChainExit extends Activity {
+ private static final String TAG = "SimpleActivityChainExit";
+ // This action.
+ private final static String ACTIVITY_CHAIN_EXIT_ACTION =
+ "com.android.cts.launchertests.LauncherAppsTests.CHAIN_EXIT_ACTION";
+ // The action which will be called from here and then immediately exit again.
+ private static final String SIMPLE_ACTIVITY_IMMEDIATE_EXIT = ".SimpleActivityImmediateExit";
+ // Our package name.
+ private static final String SIMPLE_PACKAGE_NAME = "com.android.cts.launcherapps.simpleapp";
+ // Set to true once the activity was paused. Upon next resume the activity gets finished.
+ private boolean mPaused = false;
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ Log.i(TAG, "Created SimpleActivityChainExit.");
+ }
+
+ @Override
+ public void onStart() {
+ super.onStart();
+ // Start our second activity which will quit itself immediately giving back control.
+ Intent intent = new Intent(Intent.ACTION_MAIN);
+ intent.setClassName(SIMPLE_PACKAGE_NAME,
+ SIMPLE_PACKAGE_NAME + SIMPLE_ACTIVITY_IMMEDIATE_EXIT);
+ startActivityForResult(intent, 0);
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ mPaused = true;
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ // We ignore any resumes coming in before we got at least paused once.
+ if (mPaused) {
+ // Since we were paused once we can finish ourselves now.
+ finish();
+ }
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ // Notify a listener that this activity will end now.
+ Intent reply = new Intent();
+ reply.setAction(ACTIVITY_CHAIN_EXIT_ACTION);
+ sendBroadcast(reply);
+ }
+}
diff --git a/hostsidetests/devicepolicy/app/SimpleApp/src/com/android/cts/launcherapps/simpleapp/SimpleActivityImmediateExit.java b/hostsidetests/devicepolicy/app/SimpleApp/src/com/android/cts/launcherapps/simpleapp/SimpleActivityImmediateExit.java
new file mode 100644
index 0000000..15cc3f6
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/SimpleApp/src/com/android/cts/launcherapps/simpleapp/SimpleActivityImmediateExit.java
@@ -0,0 +1,52 @@
+/*
+ * 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.launcherapps.simpleapp;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.util.Log;
+
+/**
+ * A simple activity which quits itself immediately after starting.
+ */
+public class SimpleActivityImmediateExit extends Activity {
+ private final static String ACTIVITY_EXIT_ACTION =
+ "com.android.cts.launchertests.LauncherAppsTests.EXIT_ACTION";
+ private static final String TAG = "SimpleActivityImmediateExit";
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ Log.i(TAG, "Created SimpleActivityImmediateExit.");
+ }
+
+ @Override
+ public void onStart() {
+ super.onStart();
+ finish();
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ // Notify any listener that this activity is about to end now.
+ Intent reply = new Intent();
+ reply.setAction(ACTIVITY_EXIT_ACTION);
+ sendBroadcast(reply);
+ }
+}
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 28b4feb..d8c3afb 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
@@ -23,11 +23,13 @@
import android.media.Image;
import android.media.Image.Plane;
import android.media.MediaCodec;
+import android.media.MediaCodec.BufferInfo;
import android.media.MediaCodecInfo;
import android.media.MediaCodecInfo.CodecCapabilities;
import android.media.MediaCodecList;
import android.media.MediaFormat;
import android.util.Log;
+import android.util.Pair;
import android.util.Range;
import android.util.Size;
@@ -40,6 +42,7 @@
import java.nio.ByteBuffer;
import java.lang.System;
import java.util.ArrayList;
+import java.util.LinkedList;
import java.util.Random;
import java.util.Vector;
@@ -82,7 +85,7 @@
private int mVideoHeight;
private int mFrameRate;
- private Vector<ByteBuffer> mEncodedOutputBuffer;
+ private LinkedList<Pair<ByteBuffer, BufferInfo>> mEncodedOutputBuffer;
// check this many pixels per each decoded frame
// checking too many points decreases decoder frame rates a lot.
private static final int PIXEL_CHECK_PER_FRAME = 1000;
@@ -100,7 +103,7 @@
@Override
protected void setUp() throws Exception {
- mEncodedOutputBuffer = new Vector<ByteBuffer>(TOTAL_FRAMES * 2);
+ mEncodedOutputBuffer = new LinkedList<Pair<ByteBuffer, BufferInfo>>();
// Use time as a seed, hoping to prevent checking pixels in the same pattern
long now = System.currentTimeMillis();
mRandom = new Random(now);
@@ -803,7 +806,9 @@
int l = info.size;
ByteBuffer copied = ByteBuffer.allocate(l);
output.get(copied.array(), 0, l);
- mEncodedOutputBuffer.add(copied);
+ BufferInfo savedInfo = new BufferInfo();
+ savedInfo.set(0, l, info.presentationTimeUs, info.flags);
+ mEncodedOutputBuffer.addLast(Pair.create(copied, savedInfo));
codec.releaseOutputBuffer(index, false /* render */);
}
@@ -842,7 +847,8 @@
if (inputBufIndex >= 0) {
ByteBuffer dstBuf = codecInputBuffers[inputBufIndex];
dstBuf.clear();
- ByteBuffer src = mEncodedOutputBuffer.get(inputBufferCount);
+ ByteBuffer src = mEncodedOutputBuffer.get(inputBufferCount).first;
+ BufferInfo srcInfo = mEncodedOutputBuffer.get(inputBufferCount).second;
int writeSize = src.capacity();
dstBuf.put(src.array(), 0, writeSize);
@@ -850,8 +856,8 @@
inputBufIndex,
0 /* offset */,
writeSize,
- 0,
- (inputLeft == 1) ? MediaCodec.BUFFER_FLAG_END_OF_STREAM : 0);
+ srcInfo.presentationTimeUs,
+ srcInfo.flags);
inputLeft --;
inputBufferCount ++;
}
diff --git a/tests/tests/app/src/android/app/cts/ActivityManagerTest.java b/tests/tests/app/src/android/app/cts/ActivityManagerTest.java
index ab41eea..e531ac6 100644
--- a/tests/tests/app/src/android/app/cts/ActivityManagerTest.java
+++ b/tests/tests/app/src/android/app/cts/ActivityManagerTest.java
@@ -21,19 +21,22 @@
import android.app.Activity;
import android.app.ActivityManager;
-import android.app.Instrumentation;
import android.app.ActivityManager.ProcessErrorStateInfo;
import android.app.ActivityManager.RecentTaskInfo;
import android.app.ActivityManager.RunningAppProcessInfo;
import android.app.ActivityManager.RunningServiceInfo;
import android.app.ActivityManager.RunningTaskInfo;
+import android.app.ActivityOptions;
+import android.app.Instrumentation;
import android.app.Instrumentation.ActivityMonitor;
import android.app.Instrumentation.ActivityResult;
+import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ConfigurationInfo;
+import android.os.Bundle;
import android.test.InstrumentationTestCase;
public class ActivityManagerTest extends InstrumentationTestCase {
@@ -44,10 +47,20 @@
// A secondary test activity from another APK.
private static final String SIMPLE_PACKAGE_NAME = "com.android.cts.launcherapps.simpleapp";
private static final String SIMPLE_ACTIVITY = ".SimpleActivity";
+ private static final String SIMPLE_ACTIVITY_IMMEDIATE_EXIT = ".SimpleActivityImmediateExit";
+ private static final String SIMPLE_ACTIVITY_CHAIN_EXIT = ".SimpleActivityChainExit";
// The action sent back by the SIMPLE_APP after a restart.
private static final String ACTIVITY_LAUNCHED_ACTION =
"com.android.cts.launchertests.LauncherAppsTests.LAUNCHED_ACTION";
-
+ // The action sent back by the SIMPLE_APP_IMMEDIATE_EXIT when it terminates.
+ private static final String ACTIVITY_EXIT_ACTION =
+ "com.android.cts.launchertests.LauncherAppsTests.EXIT_ACTION";
+ // The action sent back by the SIMPLE_APP_CHAIN_EXIT when the task chain ends.
+ private static final String ACTIVITY_CHAIN_EXIT_ACTION =
+ "com.android.cts.launchertests.LauncherAppsTests.CHAIN_EXIT_ACTION";
+ // The action sent to identify the time track info.
+ private static final String ACTIVITY_TIME_TRACK_INFO = "com.android.cts.TIME_TRACK_INFO";
+ // Return states of the ActivityReceiverFilter.
public static final int RESULT_PASS = 1;
public static final int RESULT_FAIL = 2;
public static final int RESULT_TIMEOUT = 3;
@@ -145,15 +158,12 @@
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.setClassName(SIMPLE_PACKAGE_NAME, SIMPLE_PACKAGE_NAME + SIMPLE_ACTIVITY);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- ActivityLaunchedReceiver receiver = new ActivityLaunchedReceiver();
- IntentFilter filter = new IntentFilter();
- filter.addAction(ACTIVITY_LAUNCHED_ACTION);
- mInstrumentation.getTargetContext().registerReceiver(receiver, filter);
+ ActivityReceiverFilter receiver = new ActivityReceiverFilter(ACTIVITY_LAUNCHED_ACTION);
mContext.startActivity(intent);
// Make sure the activity has really started.
assertEquals(RESULT_PASS, receiver.waitForActivity());
- mInstrumentation.getTargetContext().unregisterReceiver(receiver);
+ receiver.close();
// There shouldn't be any more tasks in this list at this time.
recentTaskList = mActivityManager.getRecentTasks(maxNum, flags);
@@ -161,11 +171,37 @@
assertTrue(numberOfEntriesSecondRun == numberOfEntriesFirstRun);
}
- private static class ActivityLaunchedReceiver extends BroadcastReceiver {
+ // The receiver filter needs to be instantiated with the command to filter for before calling
+ // startActivity.
+ private class ActivityReceiverFilter extends BroadcastReceiver {
+ // The activity we want to filter for.
+ private String mActivityToFilter;
+ private int result = RESULT_TIMEOUT;
+ public long mTimeUsed = 0;
+ private static final int TIMEOUT_IN_MS = 1000;
+
+ // Create the filter with the intent to look for.
+ public ActivityReceiverFilter(String activityToFilter) {
+ mActivityToFilter = activityToFilter;
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(mActivityToFilter);
+ mInstrumentation.getTargetContext().registerReceiver(this, filter);
+ }
+
+ // Turn off the filter.
+ public void close() {
+ mInstrumentation.getTargetContext().unregisterReceiver(this);
+ }
+
@Override
public void onReceive(Context context, Intent intent) {
- if (intent.getAction().equals(ACTIVITY_LAUNCHED_ACTION)) {
+ if (intent.getAction().equals(mActivityToFilter)) {
synchronized(this) {
+ result = RESULT_PASS;
+ if (mActivityToFilter.equals(ACTIVITY_TIME_TRACK_INFO)) {
+ mTimeUsed = intent.getExtras().getLong(
+ ActivityOptions.EXTRA_USAGE_REPORT_TIME);
+ }
notifyAll();
}
}
@@ -174,12 +210,11 @@
public int waitForActivity() {
synchronized(this) {
try {
- wait(5000);
- return RESULT_PASS;
+ wait(TIMEOUT_IN_MS);
} catch (InterruptedException e) {
}
}
- return RESULT_TIMEOUT;
+ return result;
}
}
@@ -337,4 +372,158 @@
assertFalse("isRunningInTestHarness must be false in production builds",
ActivityManager.isRunningInTestHarness());
}
+
+ /**
+ * Go back to the home screen since running applications can interfere with application
+ * lifetime tests.
+ */
+ private void launchHome() throws Exception {
+ Intent intent = new Intent(Intent.ACTION_MAIN);
+ intent.addCategory(Intent.CATEGORY_HOME);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ mContext.startActivity(intent);
+ Thread.sleep(WAIT_TIME);
+ }
+
+ /**
+ * Verify that the TimeTrackingAPI works properly when starting and ending an activity.
+ */
+ public void testTimeTrackingAPI_SimpleStartExit() throws Exception {
+ launchHome();
+ // Prepare to start an activity from another APK.
+ Intent intent = new Intent(Intent.ACTION_MAIN);
+ intent.setClassName(SIMPLE_PACKAGE_NAME,
+ SIMPLE_PACKAGE_NAME + SIMPLE_ACTIVITY_IMMEDIATE_EXIT);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+ // Prepare the time receiver action.
+ Context context = mInstrumentation.getTargetContext();
+ ActivityOptions options = ActivityOptions.makeBasic();
+ Intent receiveIntent = new Intent(ACTIVITY_TIME_TRACK_INFO);
+ options.requestUsageTimeReport(PendingIntent.getBroadcast(context,
+ 0, receiveIntent, PendingIntent.FLAG_CANCEL_CURRENT));
+
+ // The application finished tracker.
+ ActivityReceiverFilter appEndReceiver = new ActivityReceiverFilter(ACTIVITY_EXIT_ACTION);
+
+ // The filter for the time event.
+ ActivityReceiverFilter timeReceiver = new ActivityReceiverFilter(ACTIVITY_TIME_TRACK_INFO);
+
+ // Run the activity.
+ mContext.startActivity(intent, options.toBundle());
+
+ // Wait until it finishes and end the reciever then.
+ assertEquals(RESULT_PASS, appEndReceiver.waitForActivity());
+ appEndReceiver.close();
+
+ // At this time the timerReceiver should not fire, even though the activity has shut down,
+ // because we are back to the home screen.
+ assertEquals(RESULT_TIMEOUT, timeReceiver.waitForActivity());
+ assertTrue(timeReceiver.mTimeUsed == 0);
+
+ // Issuing now another activity will trigger the timing information release.
+ final Intent dummyIntent = new Intent(context, MockApplicationActivity.class);
+ dummyIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ final Activity activity = mInstrumentation.startActivitySync(dummyIntent);
+
+ // Wait until it finishes and end the reciever then.
+ assertEquals(RESULT_PASS, timeReceiver.waitForActivity());
+ timeReceiver.close();
+ assertTrue(timeReceiver.mTimeUsed != 0);
+ }
+
+ /**
+ * Verify that the TimeTrackingAPI works properly when switching away from the monitored task.
+ */
+ public void testTimeTrackingAPI_SwitchAwayTriggers() throws Exception {
+ launchHome();
+
+ // Prepare to start an activity from another APK.
+ Intent intent = new Intent(Intent.ACTION_MAIN);
+ intent.setClassName(SIMPLE_PACKAGE_NAME, SIMPLE_PACKAGE_NAME + SIMPLE_ACTIVITY);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+ // Prepare the time receiver action.
+ Context context = mInstrumentation.getTargetContext();
+ ActivityOptions options = ActivityOptions.makeBasic();
+ Intent receiveIntent = new Intent(ACTIVITY_TIME_TRACK_INFO);
+ options.requestUsageTimeReport(PendingIntent.getBroadcast(context,
+ 0, receiveIntent, PendingIntent.FLAG_CANCEL_CURRENT));
+
+ // The application started tracker.
+ ActivityReceiverFilter appStartedReceiver = new ActivityReceiverFilter(
+ ACTIVITY_LAUNCHED_ACTION);
+
+ // The filter for the time event.
+ ActivityReceiverFilter timeReceiver = new ActivityReceiverFilter(ACTIVITY_TIME_TRACK_INFO);
+
+ // Run the activity.
+ mContext.startActivity(intent, options.toBundle());
+
+ // Wait until it finishes and end the reciever then.
+ assertEquals(RESULT_PASS, appStartedReceiver.waitForActivity());
+ appStartedReceiver.close();
+
+ // At this time the timerReceiver should not fire since our app is running.
+ assertEquals(RESULT_TIMEOUT, timeReceiver.waitForActivity());
+ assertTrue(timeReceiver.mTimeUsed == 0);
+
+ // Starting now another activity will put ours into the back hence releasing the timing.
+ final Intent dummyIntent = new Intent(context, MockApplicationActivity.class);
+ dummyIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ final Activity activity = mInstrumentation.startActivitySync(dummyIntent);
+
+ // Wait until it finishes and end the reciever then.
+ assertEquals(RESULT_PASS, timeReceiver.waitForActivity());
+ timeReceiver.close();
+ assertTrue(timeReceiver.mTimeUsed != 0);
+ }
+
+ /**
+ * Verify that the TimeTrackingAPI works properly when handling an activity chain gets started
+ * and ended.
+ */
+ public void testTimeTrackingAPI_ChainedActivityExit() throws Exception {
+ launchHome();
+ // Prepare to start an activity from another APK.
+ Intent intent = new Intent(Intent.ACTION_MAIN);
+ intent.setClassName(SIMPLE_PACKAGE_NAME,
+ SIMPLE_PACKAGE_NAME + SIMPLE_ACTIVITY_CHAIN_EXIT);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+ // Prepare the time receiver action.
+ Context context = mInstrumentation.getTargetContext();
+ ActivityOptions options = ActivityOptions.makeBasic();
+ Intent receiveIntent = new Intent(ACTIVITY_TIME_TRACK_INFO);
+ options.requestUsageTimeReport(PendingIntent.getBroadcast(context,
+ 0, receiveIntent, PendingIntent.FLAG_CANCEL_CURRENT));
+
+ // The application finished tracker.
+ ActivityReceiverFilter appEndReceiver = new ActivityReceiverFilter(
+ ACTIVITY_CHAIN_EXIT_ACTION);
+
+ // The filter for the time event.
+ ActivityReceiverFilter timeReceiver = new ActivityReceiverFilter(ACTIVITY_TIME_TRACK_INFO);
+
+ // Run the activity.
+ mContext.startActivity(intent, options.toBundle());
+
+ // Wait until it finishes and end the reciever then.
+ assertEquals(RESULT_PASS, appEndReceiver.waitForActivity());
+ appEndReceiver.close();
+
+ // At this time the timerReceiver should not fire, even though the activity has shut down.
+ assertEquals(RESULT_TIMEOUT, timeReceiver.waitForActivity());
+ assertTrue(timeReceiver.mTimeUsed == 0);
+
+ // Issue another activity so that the timing information gets released.
+ final Intent dummyIntent = new Intent(context, MockApplicationActivity.class);
+ dummyIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ final Activity activity = mInstrumentation.startActivitySync(dummyIntent);
+
+ // Wait until it finishes and end the reciever then.
+ assertEquals(RESULT_PASS, timeReceiver.waitForActivity());
+ timeReceiver.close();
+ assertTrue(timeReceiver.mTimeUsed != 0);
+ }
}
diff --git a/tests/tests/content/AndroidManifest.xml b/tests/tests/content/AndroidManifest.xml
index d54bc02..6cddfd1 100644
--- a/tests/tests/content/AndroidManifest.xml
+++ b/tests/tests/content/AndroidManifest.xml
@@ -39,7 +39,10 @@
android:label="Test Tree"/>
<!-- Used for PackageManager test, don't delete this permission-group -->
- <permission-group android:name="android.permission-group.COST_MONEY"/>
+ <permission-group android:name="android.permission-group.COST_MONEY"
+ android:label="@string/permlab_costMoney"
+ android:description="@string/permdesc_costMoney"/>
+
<!-- Used for PackageManager test, don't delete! -->
<uses-configuration/>
<uses-feature android:name="android.hardware.camera" />
diff --git a/tests/tests/content/res/values/strings.xml b/tests/tests/content/res/values/strings.xml
index c167278..c546d8a 100644
--- a/tests/tests/content/res/values/strings.xml
+++ b/tests/tests/content/res/values/strings.xml
@@ -176,4 +176,8 @@
text, I would love to see the kind of devices you guys now use! Guys, maybe some devices need longer string!
I think so, so how about double this string, like copy and paste! </string>
<string name="rectangle200">"M 0,0 l 200,0 l 0, 200 l -200, 0 z"</string>
+
+ <string name="permlab_costMoney">Cost money</string>
+ <string name="permdesc_costMoney">Do things that can cost you money.</string>
+
</resources>
diff --git a/tests/tests/content/src/android/content/pm/cts/PermissionGroupInfoTest.java b/tests/tests/content/src/android/content/pm/cts/PermissionGroupInfoTest.java
index fc8d9b8..8b00624 100644
--- a/tests/tests/content/src/android/content/pm/cts/PermissionGroupInfoTest.java
+++ b/tests/tests/content/src/android/content/pm/cts/PermissionGroupInfoTest.java
@@ -24,8 +24,9 @@
import android.test.AndroidTestCase;
public class PermissionGroupInfoTest extends AndroidTestCase {
- private static final String PERMISSIONGROUP_NAME = "android.permission-group.COST_MONEY";
- private static final String DEFAULT_DISCRIPTION = "Do things that can cost you money.";
+ private static final String GROUP = "android.permission-group.COST_MONEY";
+ private static final String GROUP_NAME = "Cost money";
+ private static final String GROUP_DESCRIPTION = "Do things that can cost you money.";
public void testPermissionGroupInfo() throws NameNotFoundException {
PackageManager pm = getContext().getPackageManager();
@@ -33,14 +34,15 @@
// Test constructors
new PermissionGroupInfo();
PermissionGroupInfo permissionGroupInfo = pm
- .getPermissionGroupInfo(PERMISSIONGROUP_NAME, 0);
+ .getPermissionGroupInfo(GROUP, 0);
PermissionGroupInfo infoFromExisted = new PermissionGroupInfo(permissionGroupInfo);
checkInfoSame(permissionGroupInfo, infoFromExisted);
// Test toString, describeContents, loadDescription
assertNotNull(permissionGroupInfo.toString());
assertEquals(0, permissionGroupInfo.describeContents());
- assertEquals(DEFAULT_DISCRIPTION, permissionGroupInfo.loadDescription(pm));
+ assertEquals(GROUP_NAME, permissionGroupInfo.loadLabel(pm));
+ assertEquals(GROUP_DESCRIPTION, permissionGroupInfo.loadDescription(pm));
// Test writeToParcel
permissionGroupInfo.writeToParcel(p, 0);
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 d39ff1f..f062545 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/CameraTestUtils.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/CameraTestUtils.java
@@ -313,6 +313,9 @@
public static class SimpleCaptureCallback extends CameraCaptureSession.CaptureCallback {
private final LinkedBlockingQueue<TotalCaptureResult> mQueue =
new LinkedBlockingQueue<TotalCaptureResult>();
+ private final LinkedBlockingQueue<CaptureFailure> mFailureQueue =
+ new LinkedBlockingQueue<>();
+
private AtomicLong mNumFramesArrived = new AtomicLong(0);
@Override
@@ -336,6 +339,12 @@
@Override
public void onCaptureFailed(CameraCaptureSession session, CaptureRequest request,
CaptureFailure failure) {
+ try {
+ mFailureQueue.put(failure);
+ } catch (InterruptedException e) {
+ throw new UnsupportedOperationException(
+ "Can't handle InterruptedException in onCaptureFailed");
+ }
}
@Override
@@ -481,6 +490,35 @@
+ "waiting for " + numResultsWait + " results");
}
+ /**
+ * Get an array list of {@link #CaptureFailure capture failure} with maxNumFailures entries
+ * at most. If it times out before maxNumFailures failures are received, return the failures
+ * received so far.
+ *
+ * @param maxNumFailures The maximal number of failures to return. If it times out before
+ * the maximal number of failures are received, return the received
+ * failures so far.
+ * @throws UnsupportedOperationException If an error happens while waiting on the failure.
+ */
+ public ArrayList<CaptureFailure> getCaptureFailures(long maxNumFailures) {
+ ArrayList<CaptureFailure> failures = new ArrayList<>();
+ try {
+ for (int i = 0; i < maxNumFailures; i++) {
+ CaptureFailure failure = mFailureQueue.poll(CAPTURE_RESULT_TIMEOUT_MS,
+ TimeUnit.MILLISECONDS);
+ if (failure == null) {
+ // If waiting on a failure times out, return the failures so far.
+ break;
+ }
+ failures.add(failure);
+ }
+ } catch (InterruptedException e) {
+ throw new UnsupportedOperationException("Unhandled interrupted exception", e);
+ }
+
+ return failures;
+ }
+
public boolean hasMoreResults()
{
return mQueue.isEmpty();
@@ -489,6 +527,7 @@
public void drain() {
mQueue.clear();
mNumFramesArrived.getAndSet(0);
+ mFailureQueue.clear();
}
}
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/ReprocessCaptureTest.java b/tests/tests/hardware/src/android/hardware/camera2/cts/ReprocessCaptureTest.java
index 94cbbf7..4061412 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/ReprocessCaptureTest.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/ReprocessCaptureTest.java
@@ -24,6 +24,7 @@
import android.media.ImageWriter;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
+import android.hardware.camera2.CaptureFailure;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.CaptureResult;
import android.hardware.camera2.TotalCaptureResult;
@@ -75,7 +76,8 @@
private enum CaptureTestCase {
SINGLE_SHOT,
BURST,
- MIXED_BURST
+ MIXED_BURST,
+ ABORT_CAPTURE
}
/**
@@ -334,26 +336,76 @@
}
/**
+ * Test aborting reprocess capture requests of the largest input and output sizes for each
+ * supported format.
+ */
+ public void testReprocessAbort() throws Exception {
+ for (String id : mCameraIds) {
+ if (!isYuvReprocessSupported(id) && !isOpaqueReprocessSupported(id)) {
+ continue;
+ }
+
+ try {
+ // open Camera device
+ openDevice(id);
+
+ int[] supportedInputFormats =
+ mStaticInfo.getAvailableFormats(StaticMetadata.StreamDirection.Input);
+ for (int inputFormat : supportedInputFormats) {
+ int[] supportedReprocessOutputFormats =
+ mStaticInfo.getValidOutputFormatsForInput(inputFormat);
+ for (int reprocessOutputFormat : supportedReprocessOutputFormats) {
+ testReprocessingMaxSizes(id, inputFormat, reprocessOutputFormat,
+ /*previewSize*/null, CaptureTestCase.ABORT_CAPTURE);
+ }
+ }
+ } finally {
+ closeDevice();
+ }
+ }
+ }
+
+ /**
* Test the input format and output format with the largest input and output sizes.
*/
- private void testBasicReprocessing(String cameraId, int inputFormat, int reprocessOutputFormat)
- throws Exception {
+ private void testBasicReprocessing(String cameraId, int inputFormat,
+ int reprocessOutputFormat) throws Exception {
try {
openDevice(cameraId);
- Size maxInputSize =
- getMaxSize(inputFormat, StaticMetadata.StreamDirection.Input);
- Size maxReprocessOutputSize =
- getMaxSize(reprocessOutputFormat, StaticMetadata.StreamDirection.Output);
-
- testReprocess(cameraId, maxInputSize, inputFormat, maxReprocessOutputSize,
- reprocessOutputFormat, /* previewSize */null, /*numReprocessCaptures*/1);
+ testReprocessingMaxSizes(cameraId, inputFormat, reprocessOutputFormat,
+ /* previewSize */null, CaptureTestCase.SINGLE_SHOT);
} finally {
closeDevice();
}
}
/**
+ * Test the input format and output format with the largest input and output sizes for a
+ * certain test case.
+ */
+ private void testReprocessingMaxSizes(String cameraId, int inputFormat,
+ int reprocessOutputFormat, Size previewSize, CaptureTestCase captureTestCase)
+ throws Exception {
+ Size maxInputSize = getMaxSize(inputFormat, StaticMetadata.StreamDirection.Input);
+ Size maxReprocessOutputSize =
+ getMaxSize(reprocessOutputFormat, StaticMetadata.StreamDirection.Output);
+
+ switch (captureTestCase) {
+ case SINGLE_SHOT:
+ testReprocess(cameraId, maxInputSize, inputFormat, maxReprocessOutputSize,
+ reprocessOutputFormat, previewSize, NUM_REPROCESS_CAPTURES);
+ break;
+ case ABORT_CAPTURE:
+ testReprocessAbort(cameraId, maxInputSize, inputFormat, maxReprocessOutputSize,
+ reprocessOutputFormat);
+ break;
+ default:
+ throw new IllegalArgumentException("Invalid test case");
+ }
+ }
+
+ /**
* Test all input format, input size, output format, and output size combinations.
*/
private void testReprocessingAllCombinations(String cameraId, Size previewSize,
@@ -393,7 +445,7 @@
NUM_REPROCESS_BURST);
break;
default:
- throw new IllegalArgumentException("Invalid capture type");
+ throw new IllegalArgumentException("Invalid test case");
}
}
}
@@ -597,6 +649,99 @@
}
/**
+ * Test aborting a burst reprocess capture and multiple single reprocess captures.
+ */
+ private void testReprocessAbort(String cameraId, Size inputSize, int inputFormat,
+ Size reprocessOutputSize, int reprocessOutputFormat) throws Exception {
+ if (VERBOSE) {
+ Log.v(TAG, "testReprocessAbort: cameraId: " + cameraId + " inputSize: " +
+ inputSize + " inputFormat: " + inputFormat + " reprocessOutputSize: " +
+ reprocessOutputSize + " reprocessOutputFormat: " + reprocessOutputFormat);
+ }
+
+ try {
+ setupImageReaders(inputSize, inputFormat, reprocessOutputSize, reprocessOutputFormat,
+ NUM_REPROCESS_CAPTURES);
+ setupReprocessableSession(/*previewSurface*/null, NUM_REPROCESS_CAPTURES);
+
+ // Test two cases: submitting reprocess requests one by one and in a burst.
+ boolean submitInBursts[] = {false, true};
+ for (boolean submitInBurst : submitInBursts) {
+ // Prepare reprocess capture requests.
+ ArrayList<CaptureRequest> reprocessRequests =
+ new ArrayList<>(NUM_REPROCESS_CAPTURES);
+
+ for (int i = 0; i < NUM_REPROCESS_CAPTURES; i++) {
+ TotalCaptureResult result = submitCaptureRequest(mFirstImageReader.getSurface(),
+ /*inputResult*/null);
+
+ mImageWriter.queueInputImage(
+ mFirstImageReaderListener.getImage(CAPTURE_TIMEOUT_MS));
+ CaptureRequest.Builder builder = mCamera.createReprocessCaptureRequest(result);
+ if (mShareOneImageReader) {
+ builder.addTarget(mFirstImageReader.getSurface());
+ } else {
+ builder.addTarget(mSecondImageReader.getSurface());
+ }
+ reprocessRequests.add(builder.build());
+ }
+
+ SimpleCaptureCallback captureCallback = new SimpleCaptureCallback();
+
+ // Submit reprocess capture requests.
+ if (submitInBurst) {
+ mSession.captureBurst(reprocessRequests, captureCallback, mHandler);
+ } else {
+ for (CaptureRequest request : reprocessRequests) {
+ mSession.capture(request, captureCallback, mHandler);
+ }
+ }
+
+ // Abort after getting the first result
+ TotalCaptureResult reprocessResult =
+ captureCallback.getTotalCaptureResultForRequest(reprocessRequests.get(0),
+ CAPTURE_TIMEOUT_FRAMES);
+ mSession.abortCaptures();
+
+ // Wait until the session is ready again.
+ mSessionListener.getStateWaiter().waitForState(
+ BlockingSessionCallback.SESSION_READY, SESSION_CLOSE_TIMEOUT_MS);
+
+ // Gather all failed requests.
+ ArrayList<CaptureFailure> failures =
+ captureCallback.getCaptureFailures(NUM_REPROCESS_CAPTURES - 1);
+ ArrayList<CaptureRequest> failedRequests = new ArrayList<>();
+ for (CaptureFailure failure : failures) {
+ failedRequests.add(failure.getRequest());
+ }
+
+ // For each request that didn't fail must have a valid result.
+ for (int i = 1; i < reprocessRequests.size(); i++) {
+ CaptureRequest request = reprocessRequests.get(i);
+ if (!failedRequests.contains(request)) {
+ captureCallback.getTotalCaptureResultForRequest(request,
+ CAPTURE_TIMEOUT_FRAMES);
+ }
+ }
+
+ // Drain the image reader listeners.
+ mFirstImageReaderListener.drain();
+ if (!mShareOneImageReader) {
+ mSecondImageReaderListener.drain();
+ }
+
+ // Make sure all input surfaces are released.
+ for (int i = 0; i < NUM_REPROCESS_CAPTURES; i++) {
+ mImageWriterListener.waitForImageReleased(CAPTURE_TIMEOUT_MS);
+ }
+ }
+ } finally {
+ closeReprossibleSession();
+ closeImageReaders();
+ }
+ }
+
+ /**
* Set up two image readers: one for regular capture (used for reprocess input) and one for
* reprocess capture.
*/
diff --git a/tests/tests/media/src/android/media/cts/MidiSoloTest.java b/tests/tests/media/src/android/media/cts/MidiSoloTest.java
new file mode 100644
index 0000000..4c1a5e8
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/MidiSoloTest.java
@@ -0,0 +1,203 @@
+/*
+ * 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 java.io.IOException;
+
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.cts.util.CtsAndroidTestCase;
+import android.media.midi.MidiDevice;
+import android.media.midi.MidiDevice.MidiConnection;
+import android.media.midi.MidiDeviceInfo;
+import android.media.midi.MidiDeviceStatus;
+import android.media.midi.MidiInputPort;
+import android.media.midi.MidiManager;
+import android.media.midi.MidiReceiver;
+import android.media.midi.MidiSender;
+import android.os.Handler;
+import android.os.Looper;
+
+/**
+ * Test MIDI when there may be no MIDI devices available. There is not much we
+ * can test without a device.
+ */
+public class MidiSoloTest extends CtsAndroidTestCase {
+ private static final String TAG = "MidiSoloTest";
+ private final static int LOCAL_STORAGE_SIZE = 256;
+
+ // Store received data so we can check it later.
+ class MyMidiReceiver extends MidiReceiver {
+ public int byteCount;
+ public byte[] data = new byte[LOCAL_STORAGE_SIZE];
+
+ public MyMidiReceiver(int maxMessageSize) {
+ super(maxMessageSize);
+ }
+
+ @Override
+ // Abstract method declared in MidiReceiver
+ public void onSend(byte[] msg, int offset, int count, long timestamp)
+ throws IOException {
+ assertTrue("Message too large.", (count <= getMaxMessageSize()));
+ try {
+ System.arraycopy(msg, offset, data, byteCount, count);
+ } catch (ArrayIndexOutOfBoundsException e) {
+ throw new IOException("Exceeded local storage.", e);
+ }
+ byteCount += count;
+ }
+
+ @Override
+ public void onFlush() {
+ byteCount = 0;
+ }
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ // setup for each test case.
+ super.setUp();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ // Test case clean up.
+ super.tearDown();
+ }
+
+ public void testMidiManager() throws Exception {
+ PackageManager pm = getContext().getPackageManager();
+ if (!pm.hasSystemFeature(PackageManager.FEATURE_MIDI)) {
+ return; // Not supported so don't test it.
+ }
+
+ MidiManager midiManager = (MidiManager) getContext().getSystemService(
+ Context.MIDI_SERVICE);
+ assertTrue("MidiManager not supported.", midiManager != null);
+
+ MidiDeviceInfo[] infos = midiManager.getDevices();
+ assertTrue("Device list was null.", infos != null);
+
+ 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()));
+ midiManager.registerDeviceCallback(callback, new Handler(Looper.getMainLooper()));
+ 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 {
+ PackageManager pm = getContext().getPackageManager();
+ if (!pm.hasSystemFeature(PackageManager.FEATURE_MIDI)) {
+ return; // Not supported so don't test it.
+ }
+
+ MidiReceiver receiver = new MidiReceiver() {
+ @Override
+ public void onSend(byte[] msg, int offset, int count,
+ long timestamp) throws IOException {
+ }
+ };
+ assertEquals("MidiReceiver default size wrong.", Integer.MAX_VALUE,
+ receiver.getMaxMessageSize());
+
+ int maxSize = 11;
+ MyMidiReceiver myReceiver = new MyMidiReceiver(maxSize);
+ assertEquals("MidiReceiver set size wrong.", maxSize,
+ myReceiver.getMaxMessageSize());
+
+ // Fill array with predictable data.
+ byte[] bar = new byte[200];
+ for (int i = 0; i < bar.length; i++) {
+ bar[i] = (byte) (i ^ 15);
+ }
+ // Small message with no offset.
+ int offset = 0;
+ int count = 3;
+ checkReceivedData(myReceiver, bar, offset, count);
+
+ // Small with an offset.
+ offset = 50;
+ count = 3;
+ checkReceivedData(myReceiver, bar, offset, count);
+
+ // Entire array.
+ offset = 0;
+ count = bar.length;
+ checkReceivedData(myReceiver, bar, offset, count);
+
+ offset = 20;
+ count = 100;
+ checkReceivedData(myReceiver, bar, offset, count);
+ }
+
+ public void testMidiReceiverException() throws Exception {
+ PackageManager pm = getContext().getPackageManager();
+ if (!pm.hasSystemFeature(PackageManager.FEATURE_MIDI)) {
+ return; // Not supported so don't test it.
+ }
+
+ int maxSize = 11;
+ MyMidiReceiver myReceiver = new MyMidiReceiver(maxSize);
+ assertEquals("MidiReceiver set size wrong.", maxSize,
+ myReceiver.getMaxMessageSize());
+
+ // Fill array with predictable data.
+ byte[] bar = new byte[200];
+ int offset = 0;
+ int count = bar.length;
+ myReceiver.flush(); // reset byte counter
+ IOException exception = null;
+ // Send too much data and intentionally cause an IOException.
+ try {
+ int sent = 0;
+ while (sent < LOCAL_STORAGE_SIZE) {
+ myReceiver.send(bar, offset, count);
+ sent += count;
+ }
+ } catch (IOException e) {
+ exception = e;
+ }
+ assertTrue("We should have caught an IOException", exception != null);
+ }
+
+ // Does the data we sent match the data received by the MidiReceiver?
+ private void checkReceivedData(MyMidiReceiver myReceiver, byte[] bar,
+ int offset, int count) throws IOException {
+ myReceiver.flush(); // reset byte counter
+ assertEquals("MidiReceiver flush ", 0, myReceiver.byteCount);
+ myReceiver.send(bar, offset, count);
+ // Did we get all the data
+ assertEquals("MidiReceiver count ", count, myReceiver.byteCount);
+ for (int i = 0; i < count; i++) {
+ assertEquals("MidiReceiver byte " + i + " + " + offset,
+ bar[i + offset], myReceiver.data[i]);
+ }
+ }
+}
diff --git a/tests/tests/permission/src/android/permission/cts/ContactsProviderTest.java b/tests/tests/permission/src/android/permission/cts/ContactsProviderTest.java
index d815a1d..984fd6c 100644
--- a/tests/tests/permission/src/android/permission/cts/ContactsProviderTest.java
+++ b/tests/tests/permission/src/android/permission/cts/ContactsProviderTest.java
@@ -117,4 +117,41 @@
// Expected Exception
}
}
+
+ /**
+ * Verifies that query(ContactsContract.CommonDataKinds.Phone.ENTERPRISE_CONTENT_URI) requires
+ * Permission.
+ * <p>
+ * Requires Permission: {@link android.Manifest.permission#INTERACT_ACROSS_USERS}.
+ */
+ @SmallTest
+ public void testQueryPhoneEnterprise() {
+ try {
+ getContext().getContentResolver().query(
+ ContactsContract.CommonDataKinds.Phone.ENTERPRISE_CONTENT_URI,
+ null, null, null, null);
+ fail("query(ContactsContract.CommonDataKinds.Phone.ENTERPRISE_CONTENT_URI) did not"
+ + " throw SecurityException as expected");
+ } catch (SecurityException se) {
+ // Expected Exception
+ }
+ }
+
+ /**
+ * Verifies that query(ContactsContract.RawContactsEntity.CORP_CONTENT_URI) requires
+ * Permission.
+ * <p>
+ * Requires Permission: {@link android.Manifest.permission#INTERACT_ACROSS_USERS}.
+ */
+ @SmallTest
+ public void testRawContactsEntityCorp() {
+ try {
+ getContext().getContentResolver().query(
+ ContactsContract.RawContactsEntity.CORP_CONTENT_URI, null, null, null, null);
+ fail("query(ContactsContract.RawContactsEntity.CORP_CONTENT_URI) did not throw"
+ + " SecurityException as expected");
+ } catch (SecurityException se) {
+ // Expected Exception
+ }
+ }
}
diff --git a/tests/tests/provider/src/android/provider/cts/ContactsContract_ContactsTest.java b/tests/tests/provider/src/android/provider/cts/ContactsContract_ContactsTest.java
index d16cb9d..f8f610a 100644
--- a/tests/tests/provider/src/android/provider/cts/ContactsContract_ContactsTest.java
+++ b/tests/tests/provider/src/android/provider/cts/ContactsContract_ContactsTest.java
@@ -27,6 +27,7 @@
import android.net.Uri;
import android.os.SystemClock;
import android.provider.ContactsContract;
+import android.provider.ContactsContract.CommonDataKinds.StructuredName;
import android.provider.ContactsContract.Contacts;
import android.provider.cts.ContactsContract_TestDataBuilder.TestContact;
import android.provider.cts.ContactsContract_TestDataBuilder.TestRawContact;
@@ -167,6 +168,74 @@
RawContactUtil.delete(mResolver, ids.mRawContactId, true);
}
+ public void testProjection() throws Exception {
+ final TestRawContact rawContact = mBuilder.newRawContact().insert().load();
+ rawContact.newDataRow(StructuredName.CONTENT_ITEM_TYPE)
+ .with(StructuredName.GIVEN_NAME, "xxx")
+ .insert();
+
+ final TestContact contact = rawContact.getContact().load();
+ final long contactId = contact.getId();
+ final String lookupKey = contact.getString(Contacts.LOOKUP_KEY);
+
+ final String[] PROJECTION = new String[]{
+ Contacts._ID,
+ Contacts.DISPLAY_NAME,
+ Contacts.DISPLAY_NAME_PRIMARY,
+ Contacts.DISPLAY_NAME_ALTERNATIVE,
+ Contacts.DISPLAY_NAME_SOURCE,
+ Contacts.PHONETIC_NAME,
+ Contacts.PHONETIC_NAME_STYLE,
+ Contacts.SORT_KEY_PRIMARY,
+ Contacts.SORT_KEY_ALTERNATIVE,
+ Contacts.LAST_TIME_CONTACTED,
+ Contacts.TIMES_CONTACTED,
+ Contacts.STARRED,
+ Contacts.PINNED,
+ Contacts.IN_DEFAULT_DIRECTORY,
+ Contacts.IN_VISIBLE_GROUP,
+ Contacts.PHOTO_ID,
+ Contacts.PHOTO_FILE_ID,
+ Contacts.PHOTO_URI,
+ Contacts.PHOTO_THUMBNAIL_URI,
+ Contacts.CUSTOM_RINGTONE,
+ Contacts.HAS_PHONE_NUMBER,
+ Contacts.SEND_TO_VOICEMAIL,
+ Contacts.IS_USER_PROFILE,
+ Contacts.LOOKUP_KEY,
+ Contacts.NAME_RAW_CONTACT_ID,
+ Contacts.CONTACT_PRESENCE,
+ Contacts.CONTACT_CHAT_CAPABILITY,
+ Contacts.CONTACT_STATUS,
+ Contacts.CONTACT_STATUS_TIMESTAMP,
+ Contacts.CONTACT_STATUS_RES_PACKAGE,
+ Contacts.CONTACT_STATUS_LABEL,
+ Contacts.CONTACT_STATUS_ICON,
+ Contacts.CONTACT_LAST_UPDATED_TIMESTAMP
+ };
+
+ // Contacts.CONTENT_URI
+ DatabaseAsserts.checkProjection(mResolver,
+ Contacts.CONTENT_URI,
+ PROJECTION,
+ new long[]{contact.getId()}
+ );
+
+ // Contacts.CONTENT_FILTER_URI
+ DatabaseAsserts.checkProjection(mResolver,
+ Contacts.CONTENT_FILTER_URI.buildUpon().appendEncodedPath("xxx").build(),
+ PROJECTION,
+ new long[]{contact.getId()}
+ );
+
+ // Contacts.CONTENT_LOOKUP_URI
+ DatabaseAsserts.checkProjection(mResolver,
+ Contacts.getLookupUri(contactId, lookupKey),
+ PROJECTION,
+ new long[]{contact.getId()}
+ );
+ }
+
/**
* Create a contact. Delete it. And assert that the contact record is no longer present.
*
diff --git a/tests/tests/provider/src/android/provider/cts/ContactsContract_FrequentsStrequentsTest.java b/tests/tests/provider/src/android/provider/cts/ContactsContract_FrequentsStrequentsTest.java
index b515550..b52915c 100644
--- a/tests/tests/provider/src/android/provider/cts/ContactsContract_FrequentsStrequentsTest.java
+++ b/tests/tests/provider/src/android/provider/cts/ContactsContract_FrequentsStrequentsTest.java
@@ -48,6 +48,85 @@
private ContentResolver mResolver;
private ContactsContract_TestDataBuilder mBuilder;
+ private static final String[] STREQUENT_PROJECTION = new String[]{
+ Contacts._ID,
+ Contacts.HAS_PHONE_NUMBER,
+ Contacts.NAME_RAW_CONTACT_ID,
+ Contacts.IS_USER_PROFILE,
+ Contacts.CUSTOM_RINGTONE,
+ Contacts.DISPLAY_NAME,
+ Contacts.DISPLAY_NAME_ALTERNATIVE,
+ Contacts.DISPLAY_NAME_SOURCE,
+ Contacts.IN_DEFAULT_DIRECTORY,
+ Contacts.IN_VISIBLE_GROUP,
+ Contacts.LAST_TIME_CONTACTED,
+ Contacts.LOOKUP_KEY,
+ Contacts.PHONETIC_NAME,
+ Contacts.PHONETIC_NAME_STYLE,
+ Contacts.PHOTO_ID,
+ Contacts.PHOTO_FILE_ID,
+ Contacts.PHOTO_URI,
+ Contacts.PHOTO_THUMBNAIL_URI,
+ Contacts.SEND_TO_VOICEMAIL,
+ Contacts.SORT_KEY_ALTERNATIVE,
+ Contacts.SORT_KEY_PRIMARY,
+ Contacts.STARRED,
+ Contacts.PINNED,
+ Contacts.TIMES_CONTACTED,
+ Contacts.CONTACT_LAST_UPDATED_TIMESTAMP,
+ Contacts.CONTACT_PRESENCE,
+ Contacts.CONTACT_CHAT_CAPABILITY,
+ Contacts.CONTACT_STATUS,
+ Contacts.CONTACT_STATUS_TIMESTAMP,
+ Contacts.CONTACT_STATUS_RES_PACKAGE,
+ Contacts.CONTACT_STATUS_LABEL,
+ Contacts.CONTACT_STATUS_ICON,
+ Data.TIMES_USED,
+ Data.LAST_TIME_USED,
+ };
+
+ private static final String[] STREQUENT_PHONE_ONLY_PROJECTION = new String[]{
+ Data._ID,
+ Contacts.HAS_PHONE_NUMBER,
+ Contacts.NAME_RAW_CONTACT_ID,
+ Contacts.IS_USER_PROFILE,
+ Contacts.CUSTOM_RINGTONE,
+ Contacts.DISPLAY_NAME,
+ Contacts.DISPLAY_NAME_ALTERNATIVE,
+ Contacts.DISPLAY_NAME_SOURCE,
+ Contacts.IN_DEFAULT_DIRECTORY,
+ Contacts.IN_VISIBLE_GROUP,
+ Contacts.LAST_TIME_CONTACTED,
+ Contacts.LOOKUP_KEY,
+ Contacts.PHONETIC_NAME,
+ Contacts.PHONETIC_NAME_STYLE,
+ Contacts.PHOTO_ID,
+ Contacts.PHOTO_FILE_ID,
+ Contacts.PHOTO_URI,
+ Contacts.PHOTO_THUMBNAIL_URI,
+ Contacts.SEND_TO_VOICEMAIL,
+ Contacts.SORT_KEY_ALTERNATIVE,
+ Contacts.SORT_KEY_PRIMARY,
+ Contacts.STARRED,
+ Contacts.PINNED,
+ Contacts.TIMES_CONTACTED,
+ Contacts.CONTACT_LAST_UPDATED_TIMESTAMP,
+ Contacts.CONTACT_PRESENCE,
+ Contacts.CONTACT_CHAT_CAPABILITY,
+ Contacts.CONTACT_STATUS,
+ Contacts.CONTACT_STATUS_TIMESTAMP,
+ Contacts.CONTACT_STATUS_RES_PACKAGE,
+ Contacts.CONTACT_STATUS_LABEL,
+ Contacts.CONTACT_STATUS_ICON,
+ Data.TIMES_USED,
+ Data.LAST_TIME_USED,
+ Phone.NUMBER,
+ Phone.TYPE,
+ Phone.LABEL,
+ Phone.IS_SUPER_PRIMARY,
+ Phone.CONTACT_ID,
+ };
+
public static ContentValues[] sContentValues = new ContentValues[3];
static {
ContentValues cv1 = new ContentValues();
@@ -182,48 +261,18 @@
starContact(ids[0]);
markDataAsUsed(mDataIds[2], 1);
- // Construct a uri for phone only favorites.
- Uri uri = Contacts.CONTENT_STREQUENT_URI;
-
- DatabaseAsserts.checkProjection(mResolver, uri,
- new String[]{
- Contacts._ID,
- Contacts.HAS_PHONE_NUMBER,
- Contacts.NAME_RAW_CONTACT_ID,
- Contacts.IS_USER_PROFILE,
- Contacts.CUSTOM_RINGTONE,
- Contacts.DISPLAY_NAME,
- Contacts.DISPLAY_NAME_ALTERNATIVE,
- Contacts.DISPLAY_NAME_SOURCE,
- Contacts.IN_DEFAULT_DIRECTORY,
- Contacts.IN_VISIBLE_GROUP,
- Contacts.LAST_TIME_CONTACTED,
- Contacts.LOOKUP_KEY,
- Contacts.PHONETIC_NAME,
- Contacts.PHONETIC_NAME_STYLE,
- Contacts.PHOTO_ID,
- Contacts.PHOTO_FILE_ID,
- Contacts.PHOTO_URI,
- Contacts.PHOTO_THUMBNAIL_URI,
- Contacts.SEND_TO_VOICEMAIL,
- Contacts.SORT_KEY_ALTERNATIVE,
- Contacts.SORT_KEY_PRIMARY,
- Contacts.STARRED,
- Contacts.PINNED,
- Contacts.TIMES_CONTACTED,
- Contacts.CONTACT_LAST_UPDATED_TIMESTAMP,
- Contacts.CONTACT_PRESENCE,
- Contacts.CONTACT_CHAT_CAPABILITY,
- Contacts.CONTACT_STATUS,
- Contacts.CONTACT_STATUS_TIMESTAMP,
- Contacts.CONTACT_STATUS_RES_PACKAGE,
- Contacts.CONTACT_STATUS_LABEL,
- Contacts.CONTACT_STATUS_ICON,
- Data.TIMES_USED,
- Data.LAST_TIME_USED,
- },
+ DatabaseAsserts.checkProjection(mResolver, Contacts.CONTENT_STREQUENT_URI,
+ STREQUENT_PROJECTION,
new long[]{ids[0], ids[2]}
);
+
+ // Strequent filter.
+ DatabaseAsserts.checkProjection(mResolver,
+ Contacts.CONTENT_STREQUENT_FILTER_URI.buildUpon()
+ .appendEncodedPath("Hot Tamale").build(),
+ STREQUENT_PROJECTION,
+ new long[]{ids[0]}
+ );
}
public void testStrequents_phoneOnly() throws Exception {
@@ -277,48 +326,8 @@
appendQueryParameter(ContactsContract.STREQUENT_PHONE_ONLY, "true").build();
DatabaseAsserts.checkProjection(mResolver, uri,
- new String[] {
- Data._ID,
- Contacts.HAS_PHONE_NUMBER,
- Contacts.NAME_RAW_CONTACT_ID,
- Contacts.IS_USER_PROFILE,
- Contacts.CUSTOM_RINGTONE,
- Contacts.DISPLAY_NAME,
- Contacts.DISPLAY_NAME_ALTERNATIVE,
- Contacts.DISPLAY_NAME_SOURCE,
- Contacts.IN_DEFAULT_DIRECTORY,
- Contacts.IN_VISIBLE_GROUP,
- Contacts.LAST_TIME_CONTACTED,
- Contacts.LOOKUP_KEY,
- Contacts.PHONETIC_NAME,
- Contacts.PHONETIC_NAME_STYLE,
- Contacts.PHOTO_ID,
- Contacts.PHOTO_FILE_ID,
- Contacts.PHOTO_URI,
- Contacts.PHOTO_THUMBNAIL_URI,
- Contacts.SEND_TO_VOICEMAIL,
- Contacts.SORT_KEY_ALTERNATIVE,
- Contacts.SORT_KEY_PRIMARY,
- Contacts.STARRED,
- Contacts.PINNED,
- Contacts.TIMES_CONTACTED,
- Contacts.CONTACT_LAST_UPDATED_TIMESTAMP,
- Contacts.CONTACT_PRESENCE,
- Contacts.CONTACT_CHAT_CAPABILITY,
- Contacts.CONTACT_STATUS,
- Contacts.CONTACT_STATUS_TIMESTAMP,
- Contacts.CONTACT_STATUS_RES_PACKAGE,
- Contacts.CONTACT_STATUS_LABEL,
- Contacts.CONTACT_STATUS_ICON,
- Data.TIMES_USED,
- Data.LAST_TIME_USED,
- Phone.NUMBER,
- Phone.TYPE,
- Phone.LABEL,
- Phone.IS_SUPER_PRIMARY,
- Phone.CONTACT_ID,
- },
- new long[] {mDataIds[0], mDataIds[2]} // Note _id from phone_only is data._id
+ STREQUENT_PHONE_ONLY_PROJECTION,
+ new long[]{mDataIds[0], mDataIds[2]} // Note _id from phone_only is data._id
);
}
@@ -345,6 +354,17 @@
true /* inOrder */, sContentValues[1], sContentValues[2], sContentValues[0]);
}
+ public void testFrequent_projection() throws Exception {
+ long[] ids = setupTestData();
+
+ markDataAsUsed(mDataIds[0], 10);
+
+ DatabaseAsserts.checkProjection(mResolver, Contacts.CONTENT_FREQUENT_URI,
+ STREQUENT_PROJECTION,
+ new long[]{ids[0]}
+ );
+ }
+
/**
* Given a uri, performs a query on the contacts provider for that uri and asserts that the
* cursor returned from the query matches the expected results.
diff --git a/tests/uiautomator/test-apps/CtsUiAutomatorApp/Android.mk b/tests/uiautomator/test-apps/CtsUiAutomatorApp/Android.mk
index 3827754..60a0ba6 100644
--- a/tests/uiautomator/test-apps/CtsUiAutomatorApp/Android.mk
+++ b/tests/uiautomator/test-apps/CtsUiAutomatorApp/Android.mk
@@ -24,7 +24,7 @@
LOCAL_SDK_VERSION := current
LOCAL_PACKAGE_NAME := CtsUiAutomatorApp
-LOCAL_STATIC_JAVA_LIBRARIES = android-support-v4
+LOCAL_JAVA_LIBRARIES = android-support-v4
LOCAL_PROGUARD_ENABLED := disabled