Merge "CTS test cases for IMS.setBackDisposition()"
diff --git a/hostsidetests/incident/src/com/android/server/cts/NotificationIncidentTest.java b/hostsidetests/incident/src/com/android/server/cts/NotificationIncidentTest.java
index 51b8474..ab2cf84 100644
--- a/hostsidetests/incident/src/com/android/server/cts/NotificationIncidentTest.java
+++ b/hostsidetests/incident/src/com/android/server/cts/NotificationIncidentTest.java
@@ -102,19 +102,21 @@
rp.getVisibility() <= VISIBILITY_PUBLIC));
}
- // Tests default state: zen mode off, no suppressors
+ // Tests default state: zen mode is a valid/expected value
public void testZenMode() throws Exception {
final NotificationServiceDumpProto dump = getDump(NotificationServiceDumpProto.parser(),
"dumpsys notification --proto");
ZenModeProto zenProto = dump.getZen();
- assertEquals(ZenMode.ZEN_MODE_OFF, zenProto.getZenMode());
- assertEquals(0, zenProto.getEnabledActiveConditionsCount());
-
- // b/64606626 Watches intentionally suppress notifications always
- if (!getDevice().hasFeature(FEATURE_WATCH)) {
- assertEquals(0, zenProto.getSuppressedEffects());
- assertEquals(0, zenProto.getSuppressorsCount());
+ switch(zenProto.getZenMode()) {
+ case ZEN_MODE_OFF:
+ case ZEN_MODE_IMPORTANT_INTERRUPTIONS:
+ case ZEN_MODE_NO_INTERRUPTIONS:
+ case ZEN_MODE_ALARMS:
+ break;
+ default:
+ fail("Unexpected ZenMode value");
+ break;
}
zenProto.getPolicy();
diff --git a/hostsidetests/incident/src/com/android/server/cts/PowerIncidentTest.java b/hostsidetests/incident/src/com/android/server/cts/PowerIncidentTest.java
index a0cfd07..f49b6ce 100644
--- a/hostsidetests/incident/src/com/android/server/cts/PowerIncidentTest.java
+++ b/hostsidetests/incident/src/com/android/server/cts/PowerIncidentTest.java
@@ -16,7 +16,7 @@
package com.android.server.cts;
-import android.app.ProcessState;
+import android.app.ProcessStateEnum;
import android.content.IntentProto;
import android.os.BatteryManagerProto;
import android.os.LooperProto;
@@ -75,12 +75,11 @@
assertEquals(uid.getUid(), SYSTEM_UID);
assertEquals(uid.getUidString(), Integer.toString(SYSTEM_UID));
assertTrue(uid.getIsActive());
- assertFalse(uid.getIsProcessStateUnknown());
for (PowerManagerServiceDumpProto.UidStateProto us : dump.getUidStatesList()) {
assertTrue(0 <= us.getUid());
assertTrue(0 <= us.getNumWakeLocks());
- assertTrue(ProcessState.getDescriptor()
+ assertTrue(ProcessStateEnum.getDescriptor()
.getValues()
.contains(us.getProcessState().getValueDescriptor()));
}
diff --git a/hostsidetests/jvmti/attaching/host/src/android/jvmti/cts/JvmtiAttachingHostTest.java b/hostsidetests/jvmti/attaching/host/src/android/jvmti/cts/JvmtiAttachingHostTest.java
index 52be162..e2408fc 100644
--- a/hostsidetests/jvmti/attaching/host/src/android/jvmti/cts/JvmtiAttachingHostTest.java
+++ b/hostsidetests/jvmti/attaching/host/src/android/jvmti/cts/JvmtiAttachingHostTest.java
@@ -15,6 +15,7 @@
package android.jvmti.cts;
import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
+import com.android.ddmlib.NullOutputReceiver;
import com.android.ddmlib.testrunner.ITestRunListener;
import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
import com.android.ddmlib.testrunner.TestIdentifier;
@@ -64,7 +65,106 @@
mAbi = arg0;
}
- public void testJvmtiAttach() throws Exception {
+ private static interface TestRun {
+ public void run(ITestDevice device, String pkg, String apk, String abiName);
+ }
+
+ private final static String AGENT = "libctsjvmtiattachagent.so";
+
+ public void testJvmtiAttachDuringBind() throws Exception {
+ runJvmtiAgentLoadTest((ITestDevice device, String pkg, String apk, String abiName) -> {
+ try {
+ runAttachTestCmd(device, pkg, "--attach-agent-bind " + AGENT);
+ } catch (Exception e) {
+ throw new RuntimeException("Failed bind-time attaching", e);
+ }
+ });
+ };
+
+ public void testJvmtiAttachEarly() throws Exception {
+ runJvmtiAgentLoadTest((ITestDevice device, String pkg, String apk, String abiName) -> {
+ try {
+ String pwd = device.executeShellCommand("run-as " + pkg + " pwd");
+ if (pwd == null) {
+ throw new RuntimeException("pwd failed");
+ }
+ pwd = pwd.trim();
+ if (pwd.isEmpty()) {
+ throw new RuntimeException("pwd failed");
+ }
+
+ // Give it a different name, so we do not have "contamination" from
+ // the test APK.
+ String libInDataData = AGENT.substring(0, AGENT.length() - ".so".length())
+ + "2.so";
+ String agentInDataData =
+ installLibToDataData(device, pkg, abiName, apk, pwd, AGENT,
+ libInDataData);
+ runAttachTestCmd(device, pkg, "--attach-agent " + agentInDataData);
+ } catch (Exception e) {
+ throw new RuntimeException("Failed pre-bind attaching", e);
+ }
+ });
+ };
+
+ public void testJvmtiAgentAppInternal() throws Exception {
+ runJvmtiAgentLoadTest((ITestDevice device, String pkg, String apk, String abiName) -> {
+ try {
+ String setAgentAppCmd = "cmd activity set-agent-app " + pkg + " " + AGENT;
+ device.executeShellCommand(setAgentAppCmd);
+ } catch (Exception e) {
+ throw new RuntimeException("Failed running set-agent-app", e);
+ }
+
+ try {
+ runAttachTestCmd(device, pkg, "");
+
+ // And again.
+ runAttachTestCmd(device, pkg, "");
+ } catch (Exception e) {
+ throw new RuntimeException("Failed agent-app attaching", e);
+ }
+ });
+ };
+
+ public void testJvmtiAgentAppExternal() throws Exception {
+ runJvmtiAgentLoadTest((ITestDevice device, String pkg, String apk, String abiName) -> {
+ try {
+ String pwd = device.executeShellCommand("run-as " + pkg + " pwd");
+ if (pwd == null) {
+ throw new RuntimeException("pwd failed");
+ }
+ pwd = pwd.trim();
+ if (pwd.isEmpty()) {
+ throw new RuntimeException("pwd failed");
+ }
+
+ // Give it a different name, so we do not have "contamination" from
+ // the test APK.
+ String libInDataData = AGENT.substring(0, AGENT.length() - ".so".length())
+ + "2.so";
+ String agentInDataData =
+ installLibToDataData(device, pkg, abiName, apk, pwd, AGENT,
+ libInDataData);
+
+ String setAgentAppCmd = "cmd activity set-agent-app " + pkg + " " + agentInDataData;
+ device.executeShellCommand(setAgentAppCmd);
+ } catch (Exception e) {
+ throw new RuntimeException("Failed running set-agent-app", e);
+ }
+
+ try {
+ runAttachTestCmd(device, pkg, "");
+
+ // And again.
+ runAttachTestCmd(device, pkg, "");
+ } catch (Exception e) {
+ throw new RuntimeException("Failed agent-app attaching", e);
+ }
+ });
+ };
+
+ private void runJvmtiAgentLoadTest(TestRun runner) throws Exception {
final ITestDevice device = getDevice();
String testingArch = AbiUtils.getBaseArchForAbi(mAbi.getName());
@@ -84,7 +184,7 @@
throw new IllegalStateException("Incorrect configuration");
}
- runAttachTest(device, mTestPackageName, mTestApk);
+ runner.run(device, mTestPackageName, mTestApk, mAbi.getName());
}
private String getDeviceBaseArch(ITestDevice device) throws Exception {
@@ -93,50 +193,19 @@
return AbiUtils.getBaseArchForAbi(abi);
}
- private void runAttachTestCmd(ITestDevice device, String pkg, String agentParams)
+ private static void runAttachTestCmd(ITestDevice device, String pkg, String agentParams)
throws Exception {
String attachCmd = "cmd activity start -S -W " + agentParams + " -n " + pkg
+ "/android.jvmti.JvmtiActivity";
- String attachReply = device.executeShellCommand(attachCmd);
// Don't try to parse the output. The test will time out anyways if this didn't
// work.
- if (attachReply != null && !attachReply.trim().isEmpty()) {
- CLog.e(attachReply);
- }
+ device.executeShellCommand(attachCmd, NullOutputReceiver.getReceiver(), 10,
+ TimeUnit.SECONDS, 1);
}
- private final static String AGENT = "libctsjvmtiattachagent.so";
-
- private void runAttachTest(ITestDevice device, String pkg, String apk) {
- try {
- runAttachTestCmd(device, pkg, "--attach-agent-bind " + AGENT);
- } catch (Exception e) {
- throw new RuntimeException("Failed bind-time attaching", e);
- }
- try {
- String pwd = device.executeShellCommand("run-as " + pkg + " pwd");
- if (pwd == null) {
- throw new RuntimeException("pwd failed");
- }
- pwd = pwd.trim();
- if (pwd.isEmpty()) {
- throw new RuntimeException("pwd failed");
- }
-
- // Give it a different name, so we do not have "contamination" from
- // the test APK.
- String libInDataData = AGENT.substring(0, AGENT.length() - ".so".length()) + "2.so";
- String agentInDataData =
- installLibToDataData(device, pkg, apk, pwd, AGENT, libInDataData);
- runAttachTestCmd(device, pkg, "--attach-agent " + agentInDataData);
- } catch (Exception e) {
- throw new RuntimeException("Failed pre-bind attaching", e);
- }
- }
-
- String installLibToDataData(ITestDevice device, String pkg, String apk, String dataData,
- String library, String newLibName) throws Exception {
+ private String installLibToDataData(ITestDevice device, String pkg, String abiName,
+ String apk, String dataData, String library, String newLibName) throws Exception {
ZipFile zf = null;
File tmpFile = null;
String libInTmp = null;
@@ -146,7 +215,7 @@
File apkFile = mBuildHelper.getTestFile(apk);
zf = new ZipFile(apkFile);
- String libPathInApk = "lib/" + mAbi.getName() + "/" + library;
+ String libPathInApk = "lib/" + abiName + "/" + library;
tmpFile = ZipUtil.extractFileFromZip(zf, libPathInApk);
libInTmp = "/data/local/tmp/" + tmpFile.getName();
diff --git a/hostsidetests/statsd/src/android/cts/statsd/atom/ProcStateAtomTests.java b/hostsidetests/statsd/src/android/cts/statsd/atom/ProcStateAtomTests.java
index 1a7f42e0..3052937 100644
--- a/hostsidetests/statsd/src/android/cts/statsd/atom/ProcStateAtomTests.java
+++ b/hostsidetests/statsd/src/android/cts/statsd/atom/ProcStateAtomTests.java
@@ -15,7 +15,7 @@
*/
package android.cts.statsd.atom;
-import android.app.ProcessState; // from atoms.proto's activitymanager.proto's enum.
+import android.app.ProcessStateEnum; // From enums.proto for atoms.proto's UidProcessStateChanged.
import com.android.os.AtomsProto.Atom;
import com.android.os.StatsLog.EventMetricData;
@@ -64,37 +64,37 @@
// The tests here are using the BatteryStats definition of 'background'.
private static final Set<Integer> BG_STATES = new HashSet<>(
Arrays.asList(
- ProcessState.PROCESS_STATE_IMPORTANT_BACKGROUND_VALUE,
- ProcessState.PROCESS_STATE_TRANSIENT_BACKGROUND_VALUE,
- ProcessState.PROCESS_STATE_BACKUP_VALUE,
- ProcessState.PROCESS_STATE_SERVICE_VALUE,
- ProcessState.PROCESS_STATE_RECEIVER_VALUE,
- ProcessState.PROCESS_STATE_HEAVY_WEIGHT_VALUE
+ ProcessStateEnum.PROCESS_STATE_IMPORTANT_BACKGROUND_VALUE,
+ ProcessStateEnum.PROCESS_STATE_TRANSIENT_BACKGROUND_VALUE,
+ ProcessStateEnum.PROCESS_STATE_BACKUP_VALUE,
+ ProcessStateEnum.PROCESS_STATE_SERVICE_VALUE,
+ ProcessStateEnum.PROCESS_STATE_RECEIVER_VALUE,
+ ProcessStateEnum.PROCESS_STATE_HEAVY_WEIGHT_VALUE
));
// Using the BatteryStats definition of 'cached', which is why HOME (etc) are considered cached.
private static final Set<Integer> CACHED_STATES = new HashSet<>(
Arrays.asList(
- ProcessState.PROCESS_STATE_HOME_VALUE,
- ProcessState.PROCESS_STATE_LAST_ACTIVITY_VALUE,
- ProcessState.PROCESS_STATE_CACHED_ACTIVITY_VALUE,
- ProcessState.PROCESS_STATE_CACHED_ACTIVITY_CLIENT_VALUE,
- ProcessState.PROCESS_STATE_CACHED_RECENT_VALUE,
- ProcessState.PROCESS_STATE_CACHED_EMPTY_VALUE
+ ProcessStateEnum.PROCESS_STATE_HOME_VALUE,
+ ProcessStateEnum.PROCESS_STATE_LAST_ACTIVITY_VALUE,
+ ProcessStateEnum.PROCESS_STATE_CACHED_ACTIVITY_VALUE,
+ ProcessStateEnum.PROCESS_STATE_CACHED_ACTIVITY_CLIENT_VALUE,
+ ProcessStateEnum.PROCESS_STATE_CACHED_RECENT_VALUE,
+ ProcessStateEnum.PROCESS_STATE_CACHED_EMPTY_VALUE
));
private static final Set<Integer> MISC_STATES = new HashSet<>(
Arrays.asList(
- ProcessState.PROCESS_STATE_PERSISTENT_VALUE, // TODO: untested
- ProcessState.PROCESS_STATE_PERSISTENT_UI_VALUE, // TODO: untested
- ProcessState.PROCESS_STATE_TOP_VALUE,
- ProcessState.PROCESS_STATE_BOUND_FOREGROUND_SERVICE_VALUE, // TODO: untested
- ProcessState.PROCESS_STATE_FOREGROUND_SERVICE_VALUE,
- ProcessState.PROCESS_STATE_IMPORTANT_FOREGROUND_VALUE,
- ProcessState.PROCESS_STATE_TOP_SLEEPING_VALUE,
+ ProcessStateEnum.PROCESS_STATE_PERSISTENT_VALUE, // TODO: untested
+ ProcessStateEnum.PROCESS_STATE_PERSISTENT_UI_VALUE, // TODO: untested
+ ProcessStateEnum.PROCESS_STATE_TOP_VALUE,
+ ProcessStateEnum.PROCESS_STATE_BOUND_FOREGROUND_SERVICE_VALUE, // TODO: untested
+ ProcessStateEnum.PROCESS_STATE_FOREGROUND_SERVICE_VALUE,
+ ProcessStateEnum.PROCESS_STATE_IMPORTANT_FOREGROUND_VALUE,
+ ProcessStateEnum.PROCESS_STATE_TOP_SLEEPING_VALUE,
- ProcessState.PROCESS_STATE_UNKNOWN_VALUE,
- ProcessState.PROCESS_STATE_NONEXISTENT_VALUE
+ ProcessStateEnum.PROCESS_STATE_UNKNOWN_VALUE,
+ ProcessStateEnum.PROCESS_STATE_NONEXISTENT_VALUE
));
private static final Set<Integer> ALL_STATES = Stream.of(MISC_STATES, CACHED_STATES, BG_STATES)
@@ -116,7 +116,7 @@
public void testForegroundService() throws Exception {
if (!TESTS_ENABLED) return;
Set<Integer> onStates = new HashSet<>(Arrays.asList(
- ProcessState.PROCESS_STATE_FOREGROUND_SERVICE_VALUE));
+ ProcessStateEnum.PROCESS_STATE_FOREGROUND_SERVICE_VALUE));
Set<Integer> offStates = complement(onStates);
List<Set<Integer>> stateSet = Arrays.asList(onStates, offStates); // state sets, in order
@@ -135,7 +135,7 @@
public void testForeground() throws Exception {
if (!TESTS_ENABLED) return;
Set<Integer> onStates = new HashSet<>(Arrays.asList(
- ProcessState.PROCESS_STATE_IMPORTANT_FOREGROUND_VALUE));
+ ProcessStateEnum.PROCESS_STATE_IMPORTANT_FOREGROUND_VALUE));
// There are no offStates, since the app remains in foreground until killed.
List<Set<Integer>> stateSet = Arrays.asList(onStates); // state sets, in order
@@ -176,7 +176,7 @@
public void testTop() throws Exception {
if (!TESTS_ENABLED) return;
Set<Integer> onStates = new HashSet<>(Arrays.asList(
- ProcessState.PROCESS_STATE_TOP_VALUE));
+ ProcessStateEnum.PROCESS_STATE_TOP_VALUE));
Set<Integer> offStates = complement(onStates);
List<Set<Integer>> stateSet = Arrays.asList(onStates, offStates); // state sets, in order
@@ -197,7 +197,7 @@
public void testTopSleeping() throws Exception {
if (!TESTS_ENABLED) return;
Set<Integer> onStates = new HashSet<>(Arrays.asList(
- ProcessState.PROCESS_STATE_TOP_SLEEPING_VALUE));
+ ProcessStateEnum.PROCESS_STATE_TOP_SLEEPING_VALUE));
Set<Integer> offStates = complement(onStates);
List<Set<Integer>> stateSet = Arrays.asList(onStates, offStates); // state sets, in order
@@ -252,6 +252,11 @@
assertStatesOccurred(stateSet, data, 1_000, PROC_STATE_FUNCTION);
}
+ public void testValidityOfStates() throws Exception {
+ assertFalse("UNKNOWN_TO_PROTO should not be a valid state",
+ ALL_STATES.contains(ProcessStateEnum.PROCESS_STATE_UNKNOWN_TO_PROTO_VALUE));
+ }
+
/**
* Runs a (background) service to perform the given action.
* @param actionValue the action code constants indicating the desired action to perform.
diff --git a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerConfigChangeTests.java b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerConfigChangeTests.java
index 18bf397..56aedd0 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerConfigChangeTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerConfigChangeTests.java
@@ -72,7 +72,6 @@
}
@Presubmit
- @FlakyTest(bugId = 71877849)
@Test
public void testChangeFontScaleRelaunch() throws Exception {
// Should relaunch and receive no onConfigurationChanged()
@@ -80,7 +79,6 @@
}
@Presubmit
- @FlakyTest(bugId = 71877849)
@Test
public void testChangeFontScaleNoRelaunch() throws Exception {
// Should receive onConfigurationChanged() and no relaunch
diff --git a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerSplitScreenTests.java b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerSplitScreenTests.java
index 36e6f04..c5f13f1 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerSplitScreenTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerSplitScreenTests.java
@@ -83,7 +83,6 @@
@Test
@Presubmit
- @FlakyTest(bugId = 71918731)
public void testStackList() throws Exception {
launchActivity(TEST_ACTIVITY_NAME);
mAmWmState.computeState(new String[] {TEST_ACTIVITY_NAME});
@@ -235,7 +234,6 @@
@Test
@Presubmit
- @FlakyTest(bugId = 71918731)
public void testLaunchToSideSingleInstance() throws Exception {
launchTargetToSide(SINGLE_INSTANCE_ACTIVITY_NAME, false);
}
@@ -245,7 +243,6 @@
launchTargetToSide(SINGLE_TASK_ACTIVITY_NAME, false);
}
- @FlakyTest
@Presubmit
@Test
public void testLaunchToSideMultipleWithDifferentIntent() throws Exception {
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/CrossAppDragAndDropTests.java b/tests/framework/base/windowmanager/src/android/server/wm/CrossAppDragAndDropTests.java
index 89ff760..14c0179 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/CrossAppDragAndDropTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/CrossAppDragAndDropTests.java
@@ -53,7 +53,6 @@
* Run: cts/tests/framework/base/activitymanager/util/run-test CtsWindowManagerDeviceTestCases android.server.wm.CrossAppDragAndDropTests
*/
@Presubmit
-@FlakyTest(bugId = 65739235)
public class CrossAppDragAndDropTests {
private static final String TAG = "CrossAppDragAndDrop";
diff --git a/tests/tests/content/AndroidManifest.xml b/tests/tests/content/AndroidManifest.xml
index eb6fecb..481c9a4 100644
--- a/tests/tests/content/AndroidManifest.xml
+++ b/tests/tests/content/AndroidManifest.xml
@@ -291,12 +291,20 @@
<activity android:name="com.android.cts.content.StubActivity"/>
- <service android:name="com.android.cts.content.SyncService">
+ <service android:name="com.android.cts.content.NotAlwaysSyncableSyncService">
<intent-filter>
<action android:name="android.content.SyncAdapter"/>
</intent-filter>
<meta-data android:name="android.content.SyncAdapter"
- android:resource="@xml/accountaccesssyncadapter" />
+ android:resource="@xml/not_always_syncable_account_access_adapter" />
+ </service>
+
+ <service android:name="com.android.cts.content.AlwaysSyncableSyncService">
+ <intent-filter>
+ <action android:name="android.content.SyncAdapter"/>
+ </intent-filter>
+ <meta-data android:name="android.content.SyncAdapter"
+ android:resource="@xml/always_syncable_account_access_adapter" />
</service>
</application>
diff --git a/tests/tests/content/CtsSyncAccountAccessOtherCertTests/Android.mk b/tests/tests/content/CtsSyncAccountAccessOtherCertTests/Android.mk
index 09523ba..14dd2c9 100644
--- a/tests/tests/content/CtsSyncAccountAccessOtherCertTests/Android.mk
+++ b/tests/tests/content/CtsSyncAccountAccessOtherCertTests/Android.mk
@@ -23,8 +23,6 @@
LOCAL_STATIC_JAVA_LIBRARIES := \
android-support-test \
ctstestrunner \
- ub-uiautomator \
- compatibility-device-util \
accountaccesslib
LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/tests/tests/content/CtsSyncAccountAccessOtherCertTests/AndroidManifest.xml b/tests/tests/content/CtsSyncAccountAccessOtherCertTests/AndroidManifest.xml
index 398a75b..e1fd828 100644
--- a/tests/tests/content/CtsSyncAccountAccessOtherCertTests/AndroidManifest.xml
+++ b/tests/tests/content/CtsSyncAccountAccessOtherCertTests/AndroidManifest.xml
@@ -24,7 +24,7 @@
<activity android:name=".StubActivity"/>
- <service android:name=".SyncService">
+ <service android:name=".AlwaysSyncableSyncService">
<intent-filter>
<action android:name="android.content.SyncAdapter"/>
</intent-filter>
diff --git a/tests/tests/content/CtsSyncAccountAccessOtherCertTests/src/com/android/cts/content/CtsSyncAccountAccessOtherCertTestCases.java b/tests/tests/content/CtsSyncAccountAccessOtherCertTests/src/com/android/cts/content/CtsSyncAccountAccessOtherCertTestCases.java
index 3c791fd..8ad7c19 100644
--- a/tests/tests/content/CtsSyncAccountAccessOtherCertTests/src/com/android/cts/content/CtsSyncAccountAccessOtherCertTestCases.java
+++ b/tests/tests/content/CtsSyncAccountAccessOtherCertTests/src/com/android/cts/content/CtsSyncAccountAccessOtherCertTestCases.java
@@ -16,29 +16,29 @@
package com.android.cts.content;
+import static com.android.cts.content.Utils.ALWAYS_SYNCABLE_AUTHORITY;
+import static com.android.cts.content.Utils.SYNC_TIMEOUT_MILLIS;
+import static com.android.cts.content.Utils.allowSyncAdapterRunInBackgroundAndDataInBackground;
+import static com.android.cts.content.Utils.disallowSyncAdapterRunInBackgroundAndDataInBackground;
+import static com.android.cts.content.Utils.getUiDevice;
+import static com.android.cts.content.Utils.hasDataConnection;
+import static com.android.cts.content.Utils.hasNotificationSupport;
+import static com.android.cts.content.Utils.isWatch;
+import static com.android.cts.content.Utils.requestSync;
+import static com.android.cts.content.Utils.withAccount;
+
import static org.junit.Assume.assumeFalse;
import static org.junit.Assume.assumeTrue;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.verify;
-import android.accounts.Account;
-import android.accounts.AccountManager;
-import android.app.Activity;
import android.app.ActivityManager;
import android.content.AbstractThreadedSyncAdapter;
import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
import android.content.SyncRequest;
-import android.content.pm.PackageManager;
-import android.content.res.Configuration;
-import android.net.ConnectivityManager;
-import android.net.NetworkInfo;
-import android.os.Bundle;
-import android.os.Process;
-import android.os.SystemClock;
-import android.support.test.InstrumentationRegistry;
+import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
import android.support.test.uiautomator.By;
import android.support.test.uiautomator.UiDevice;
@@ -54,17 +54,13 @@
import org.junit.runner.RunWith;
import java.io.ByteArrayOutputStream;
-import java.io.IOException;
import java.util.regex.Pattern;
-import com.android.compatibility.common.util.SystemUtil;
-
/**
* Tests whether a sync adapter can access accounts.
*/
@RunWith(AndroidJUnit4.class)
public class CtsSyncAccountAccessOtherCertTestCases {
- private static final long SYNC_TIMEOUT_MILLIS = 20000; // 20 sec
private static final long UI_TIMEOUT_MILLIS = 5000; // 5 sec
private static final String LOG_TAG =
CtsSyncAccountAccessOtherCertTestCases.class.getSimpleName();
@@ -72,11 +68,13 @@
private static final Pattern PERMISSION_REQUESTED = Pattern.compile(
"Permission Requested|Permission requested");
private static final Pattern ALLOW_SYNC = Pattern.compile("ALLOW|Allow");
- public static final String TOKEN_TYPE_REMOVE_ACCOUNTS = "TOKEN_TYPE_REMOVE_ACCOUNTS";
@Rule
public final TestRule mFlakyTestRule = new FlakyTestRule(3);
+ @Rule
+ public final ActivityTestRule<StubActivity> activity = new ActivityTestRule(StubActivity.class);
+
@Before
public void setUp() throws Exception {
allowSyncAdapterRunInBackgroundAndDataInBackground();
@@ -96,38 +94,16 @@
// the permission request will not trigger. b/72114924
assumeFalse(ActivityManager.isRunningInTestHarness());
- Intent intent = new Intent(getContext(), StubActivity.class);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- Activity activity = InstrumentationRegistry.getInstrumentation().startActivitySync(intent);
+ try (AutoCloseable ignored = withAccount(activity.getActivity())) {
+ AbstractThreadedSyncAdapter adapter = AlwaysSyncableSyncService.getInstance(
+ activity.getActivity()).setNewDelegate();
- AccountManager accountManager = getContext().getSystemService(AccountManager.class);
- Bundle result = accountManager.addAccount("com.stub", null, null, null, activity,
- null, null).getResult();
+ SyncRequest request = requestSync(ALWAYS_SYNCABLE_AUTHORITY);
+ Log.i(LOG_TAG, "Sync requested " + request);
- Account addedAccount = new Account(
- result.getString(AccountManager.KEY_ACCOUNT_NAME),
- result.getString(AccountManager.KEY_ACCOUNT_TYPE));
-
- waitForSyncManagerAccountChangeUpdate();
-
- try {
- AbstractThreadedSyncAdapter adapter = SyncAdapter.setNewDelegate();
-
- Bundle extras = new Bundle();
- extras.putBoolean(ContentResolver.SYNC_EXTRAS_DO_NOT_RETRY, true);
- extras.putBoolean(ContentResolver.SYNC_EXTRAS_PRIORITY, true);
- extras.getBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_SETTINGS, true);
- SyncRequest request = new SyncRequest.Builder()
- .setSyncAdapter(null, "com.android.cts.stub.provider")
- .syncOnce()
- .setExtras(extras)
- .setExpedited(true)
- .setManual(true)
- .build();
- ContentResolver.requestSync(request);
-
- verify(adapter, timeout(SYNC_TIMEOUT_MILLIS).times(0)).onPerformSync(any(), any(),
- any(), any(), any());
+ Thread.sleep(SYNC_TIMEOUT_MILLIS);
+ verify(adapter, never()).onPerformSync(any(), any(), any(), any(), any());
+ Log.i(LOG_TAG, "Did not get onPerformSync");
UiDevice uiDevice = getUiDevice();
if (isWatch()) {
@@ -162,11 +138,7 @@
verify(adapter, timeout(SYNC_TIMEOUT_MILLIS)).onPerformSync(any(), any(), any(), any(),
any());
- } finally {
- // Ask the differently signed authenticator to drop all accounts
- accountManager.getAuthToken(addedAccount, TOKEN_TYPE_REMOVE_ACCOUNTS,
- null, false, null, null);
- activity.finish();
+ Log.i(LOG_TAG, "Got onPerformSync");
}
}
@@ -198,54 +170,4 @@
1 /* endY */,
50 /* numberOfSteps */);
}
-
- private boolean isWatch() {
- return (getContext().getResources().getConfiguration().uiMode
- & Configuration.UI_MODE_TYPE_MASK) == Configuration.UI_MODE_TYPE_WATCH;
- }
-
- private Context getContext() {
- return InstrumentationRegistry.getInstrumentation().getContext();
- }
-
- private UiDevice getUiDevice() {
- return UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
- }
-
- private void waitForSyncManagerAccountChangeUpdate() {
- // Wait for the sync manager to be notified for the new account.
- // Unfortunately, there is no way to detect this event, sigh...
- SystemClock.sleep(SYNC_TIMEOUT_MILLIS);
- }
-
- private boolean hasDataConnection() {
- ConnectivityManager connectivityManager = getContext().getSystemService(
- ConnectivityManager.class);
- NetworkInfo activeNetwork = connectivityManager.getActiveNetworkInfo();
- return activeNetwork != null && activeNetwork.isConnectedOrConnecting();
- }
-
- private boolean hasNotificationSupport() {
- final PackageManager manager = getContext().getPackageManager();
- return !manager.hasSystemFeature(PackageManager.FEATURE_LEANBACK)
- && !manager.hasSystemFeature(PackageManager.FEATURE_EMBEDDED);
- }
-
- private void allowSyncAdapterRunInBackgroundAndDataInBackground() throws IOException {
- // Allow us to run in the background
- SystemUtil.runShellCommand(InstrumentationRegistry.getInstrumentation(),
- "cmd deviceidle whitelist +" + getContext().getPackageName());
- // Allow us to use data in the background
- SystemUtil.runShellCommand(InstrumentationRegistry.getInstrumentation(),
- "cmd netpolicy add restrict-background-whitelist " + Process.myUid());
- }
-
- private void disallowSyncAdapterRunInBackgroundAndDataInBackground() throws IOException {
- // Allow us to run in the background
- SystemUtil.runShellCommand(InstrumentationRegistry.getInstrumentation(),
- "cmd deviceidle whitelist -" + getContext().getPackageName());
- // Allow us to use data in the background
- SystemUtil.runShellCommand(InstrumentationRegistry.getInstrumentation(),
- "cmd netpolicy remove restrict-background-whitelist " + Process.myUid());
- }
}
diff --git a/tests/tests/content/SyncAccountAccessStubs/AndroidManifest.xml b/tests/tests/content/SyncAccountAccessStubs/AndroidManifest.xml
index 76c4fb4..a0dee84 100644
--- a/tests/tests/content/SyncAccountAccessStubs/AndroidManifest.xml
+++ b/tests/tests/content/SyncAccountAccessStubs/AndroidManifest.xml
@@ -35,6 +35,13 @@
android:syncable="true">
</provider>
+ <provider
+ android:name=".StubProvider2"
+ android:authorities="com.android.cts.stub.provider2"
+ android:exported="true"
+ android:syncable="true">
+ </provider>
+
</application>
</manifest>
diff --git a/tests/tests/content/SyncAccountAccessStubs/src/com/android/cts/stub/StubAuthenticator.java b/tests/tests/content/SyncAccountAccessStubs/src/com/android/cts/stub/StubAuthenticator.java
index eec9d21..0275fa9 100644
--- a/tests/tests/content/SyncAccountAccessStubs/src/com/android/cts/stub/StubAuthenticator.java
+++ b/tests/tests/content/SyncAccountAccessStubs/src/com/android/cts/stub/StubAuthenticator.java
@@ -30,6 +30,7 @@
public class StubAuthenticator extends Service {
public static final String TOKEN_TYPE_REMOVE_ACCOUNTS = "TOKEN_TYPE_REMOVE_ACCOUNTS";
+ private static long sNumAccountsAdded;
private Authenticator mAuthenticator;
@Override
@@ -59,10 +60,14 @@
String accountType, String tokenType, String[] strings,
Bundle bundle) throws NetworkErrorException {
AccountManager accountManager = getSystemService(AccountManager.class);
- accountManager.addAccountExplicitly(new Account("foo", accountType), "bar", null);
+
+ String accountName = "foo" + sNumAccountsAdded;
+ sNumAccountsAdded++;
+
+ accountManager.addAccountExplicitly(new Account(accountName, accountType), "bar", null);
Bundle result = new Bundle();
- result.putString(AccountManager.KEY_ACCOUNT_NAME, "foo");
+ result.putString(AccountManager.KEY_ACCOUNT_NAME, accountName);
result.putString(AccountManager.KEY_ACCOUNT_TYPE, accountType);
response.onResult(result);
diff --git a/tests/tests/content/SyncAccountAccessStubs/src/com/android/cts/stub/StubProvider2.java b/tests/tests/content/SyncAccountAccessStubs/src/com/android/cts/stub/StubProvider2.java
new file mode 100644
index 0000000..0ecb23b
--- /dev/null
+++ b/tests/tests/content/SyncAccountAccessStubs/src/com/android/cts/stub/StubProvider2.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2018 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.stub;
+
+public class StubProvider2 extends StubProvider {
+}
diff --git a/tests/tests/content/lib/accountaccess/Android.mk b/tests/tests/content/lib/accountaccess/Android.mk
index 559dc90..2832452 100644
--- a/tests/tests/content/lib/accountaccess/Android.mk
+++ b/tests/tests/content/lib/accountaccess/Android.mk
@@ -22,6 +22,8 @@
LOCAL_MODULE := accountaccesslib
-LOCAL_STATIC_JAVA_LIBRARIES := mockito-target
+LOCAL_STATIC_JAVA_LIBRARIES := mockito-target \
+ ub-uiautomator \
+ compatibility-device-util
include $(BUILD_STATIC_JAVA_LIBRARY)
\ No newline at end of file
diff --git a/tests/tests/content/lib/accountaccess/src/com.android.cts.content/AlwaysSyncableSyncService.java b/tests/tests/content/lib/accountaccess/src/com.android.cts.content/AlwaysSyncableSyncService.java
new file mode 100644
index 0000000..80c496a
--- /dev/null
+++ b/tests/tests/content/lib/accountaccess/src/com.android.cts.content/AlwaysSyncableSyncService.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2018 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.content;
+
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.os.IBinder;
+
+public class AlwaysSyncableSyncService extends Service {
+ private static final Object sLock = new Object();
+ private static SyncAdapter sInstance;
+
+ public static SyncAdapter getInstance(Context context) {
+ synchronized (sLock) {
+ if (sInstance == null) {
+ sInstance = new SyncAdapter(context.getApplicationContext(), false);
+ }
+ }
+
+ return sInstance;
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return getInstance(this).getSyncAdapterBinder();
+ }
+}
diff --git a/tests/tests/content/lib/accountaccess/src/com.android.cts.content/FlakyTestRule.java b/tests/tests/content/lib/accountaccess/src/com.android.cts.content/FlakyTestRule.java
index 2608b97..2d41ad6 100644
--- a/tests/tests/content/lib/accountaccess/src/com.android.cts.content/FlakyTestRule.java
+++ b/tests/tests/content/lib/accountaccess/src/com.android.cts.content/FlakyTestRule.java
@@ -15,6 +15,8 @@
package com.android.cts.content;
+import android.util.Log;
+
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
@@ -25,6 +27,8 @@
*/
// TODO: Move this puppy in a common place, so ppl can use it.
public class FlakyTestRule implements TestRule {
+ private static final String LOG_TAG = FlakyTestRule.class.getSimpleName();
+
private final int mAttemptCount;
public FlakyTestRule(int attemptCount) {
@@ -42,6 +46,8 @@
statement.evaluate();
return;
} catch (Throwable t) {
+ Log.e(LOG_TAG, "Test failed ", t);
+
throwable = t;
}
}
diff --git a/tests/tests/content/lib/accountaccess/src/com.android.cts.content/NotAlwaysSyncableSyncService.java b/tests/tests/content/lib/accountaccess/src/com.android.cts.content/NotAlwaysSyncableSyncService.java
new file mode 100644
index 0000000..58524cd
--- /dev/null
+++ b/tests/tests/content/lib/accountaccess/src/com.android.cts.content/NotAlwaysSyncableSyncService.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2018 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.content;
+
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.os.IBinder;
+
+public class NotAlwaysSyncableSyncService extends Service {
+ private static final Object sLock = new Object();
+ private static SyncAdapter sInstance;
+
+ public static SyncAdapter getInstance(Context context) {
+ synchronized (sLock) {
+ if (sInstance == null) {
+ sInstance = new SyncAdapter(context.getApplicationContext(), false);
+ }
+ }
+
+ return sInstance;
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return getInstance(this).getSyncAdapterBinder();
+ }
+}
diff --git a/tests/tests/content/lib/accountaccess/src/com.android.cts.content/SyncAdapter.java b/tests/tests/content/lib/accountaccess/src/com.android.cts.content/SyncAdapter.java
index 19fb8ee..a81d6cc 100644
--- a/tests/tests/content/lib/accountaccess/src/com.android.cts.content/SyncAdapter.java
+++ b/tests/tests/content/lib/accountaccess/src/com.android.cts.content/SyncAdapter.java
@@ -27,14 +27,15 @@
import android.os.Bundle;
public class SyncAdapter extends AbstractThreadedSyncAdapter {
- private static final Object sLock = new Object();
- private static AbstractThreadedSyncAdapter sDelegate;
+ private final Object mLock = new Object();
+ private AbstractThreadedSyncAdapter mDelegate;
- public static AbstractThreadedSyncAdapter setNewDelegate() {
+ public AbstractThreadedSyncAdapter setNewDelegate() {
AbstractThreadedSyncAdapter delegate = mock(AbstractThreadedSyncAdapter.class);
+ when(delegate.onUnsyncableAccount()).thenCallRealMethod();
- synchronized (sLock) {
- sDelegate = delegate;
+ synchronized (mLock) {
+ mDelegate = delegate;
}
return delegate;
@@ -45,8 +46,8 @@
}
private AbstractThreadedSyncAdapter getCopyOfDelegate() {
- synchronized (sLock) {
- return sDelegate;
+ synchronized (mLock) {
+ return mDelegate;
}
}
@@ -59,4 +60,15 @@
delegate.onPerformSync(account, extras, authority, provider, syncResult);
}
}
+
+ @Override
+ public boolean onUnsyncableAccount() {
+ AbstractThreadedSyncAdapter delegate = getCopyOfDelegate();
+
+ if (delegate == null) {
+ return true;
+ } else {
+ return delegate.onUnsyncableAccount();
+ }
+ }
}
diff --git a/tests/tests/content/lib/accountaccess/src/com.android.cts.content/SyncService.java b/tests/tests/content/lib/accountaccess/src/com.android.cts.content/SyncService.java
deleted file mode 100644
index e8da82c..0000000
--- a/tests/tests/content/lib/accountaccess/src/com.android.cts.content/SyncService.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2016 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.content;
-
-import android.app.Service;
-import android.content.Intent;
-import android.os.IBinder;
-
-public class SyncService extends Service {
- private SyncAdapter mInstance;
-
- @Override
- public void onCreate() {
- super.onCreate();
- mInstance = new SyncAdapter(this, false);
- }
-
- @Override
- public IBinder onBind(Intent intent) {
- return mInstance.getSyncAdapterBinder();
- }
-}
diff --git a/tests/tests/content/lib/accountaccess/src/com.android.cts.content/Utils.java b/tests/tests/content/lib/accountaccess/src/com.android.cts.content/Utils.java
new file mode 100644
index 0000000..b2ff8c9
--- /dev/null
+++ b/tests/tests/content/lib/accountaccess/src/com.android.cts.content/Utils.java
@@ -0,0 +1,132 @@
+package com.android.cts.content;
+
+import android.accounts.Account;
+import android.accounts.AccountManager;
+import android.accounts.AuthenticatorException;
+import android.accounts.OperationCanceledException;
+import android.app.Activity;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.SyncRequest;
+import android.content.pm.PackageManager;
+import android.content.res.Configuration;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.os.Bundle;
+import android.os.Process;
+import android.os.SystemClock;
+import android.support.annotation.NonNull;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.uiautomator.UiDevice;
+import android.util.Log;
+
+import com.android.compatibility.common.util.SystemUtil;
+
+import java.io.IOException;
+
+public class Utils {
+ private static final String LOG_TAG = Utils.class.getSimpleName();
+
+ public static final long SYNC_TIMEOUT_MILLIS = 20000; // 20 sec
+ public static final String TOKEN_TYPE_REMOVE_ACCOUNTS = "TOKEN_TYPE_REMOVE_ACCOUNTS";
+ public static final String SYNC_ACCOUNT_TYPE = "com.stub";
+ public static final String ALWAYS_SYNCABLE_AUTHORITY = "com.android.cts.stub.provider";
+ public static final String NOT_ALWAYS_SYNCABLE_AUTHORITY = "com.android.cts.stub.provider2";
+
+ public static boolean hasDataConnection() {
+ ConnectivityManager connectivityManager = getContext().getSystemService(
+ ConnectivityManager.class);
+ NetworkInfo activeNetwork = connectivityManager.getActiveNetworkInfo();
+ return activeNetwork != null && activeNetwork.isConnectedOrConnecting();
+ }
+
+ public static boolean hasNotificationSupport() {
+ return !getContext().getPackageManager()
+ .hasSystemFeature(PackageManager.FEATURE_LEANBACK);
+ }
+
+ public static Context getContext() {
+ return InstrumentationRegistry.getInstrumentation().getContext();
+ }
+
+ public static boolean isWatch() {
+ return (getContext().getResources().getConfiguration().uiMode
+ & Configuration.UI_MODE_TYPE_MASK) == Configuration.UI_MODE_TYPE_WATCH;
+ }
+
+ public static UiDevice getUiDevice() {
+ return UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
+ }
+
+ public static void waitForSyncManagerAccountChangeUpdate() {
+ // Wait for the sync manager to be notified for the new account.
+ // Unfortunately, there is no way to detect this event, sigh...
+ SystemClock.sleep(SYNC_TIMEOUT_MILLIS);
+ }
+
+ public static void allowSyncAdapterRunInBackgroundAndDataInBackground() throws IOException {
+ // Allow us to run in the background
+ SystemUtil.runShellCommand(InstrumentationRegistry.getInstrumentation(),
+ "cmd deviceidle whitelist +" + getContext().getPackageName());
+ // Allow us to use data in the background
+ SystemUtil.runShellCommand(InstrumentationRegistry.getInstrumentation(),
+ "cmd netpolicy add restrict-background-whitelist " + Process.myUid());
+ }
+
+ public static void disallowSyncAdapterRunInBackgroundAndDataInBackground() throws IOException {
+ // Allow us to run in the background
+ SystemUtil.runShellCommand(InstrumentationRegistry.getInstrumentation(),
+ "cmd deviceidle whitelist -" + getContext().getPackageName());
+ // Allow us to use data in the background
+ SystemUtil.runShellCommand(InstrumentationRegistry.getInstrumentation(),
+ "cmd netpolicy remove restrict-background-whitelist " + Process.myUid());
+ }
+
+ public static class ClosableAccount implements AutoCloseable {
+ public final Account account;
+
+ private ClosableAccount(@NonNull Account account) {
+ this.account = account;
+ }
+
+ @Override
+ public void close() throws Exception {
+ AccountManager accountManager = getContext().getSystemService(AccountManager.class);
+
+ accountManager.getAuthToken(account, TOKEN_TYPE_REMOVE_ACCOUNTS, null, false, null,
+ null);
+ }
+ }
+
+ public static ClosableAccount withAccount(@NonNull Activity activity)
+ throws AuthenticatorException, OperationCanceledException, IOException {
+ AccountManager accountManager = getContext().getSystemService(AccountManager.class);
+ Bundle result = accountManager.addAccount(SYNC_ACCOUNT_TYPE, null, null, null,
+ activity, null, null).getResult();
+ Account addedAccount = new Account(
+ result.getString(AccountManager.KEY_ACCOUNT_NAME),
+ result.getString(AccountManager.KEY_ACCOUNT_TYPE));
+ Log.i(LOG_TAG, "Added account " + addedAccount);
+
+ waitForSyncManagerAccountChangeUpdate();
+
+ return new ClosableAccount(addedAccount);
+ }
+
+ public static SyncRequest requestSync(String authority) {
+ Bundle extras = new Bundle();
+ extras.putBoolean(ContentResolver.SYNC_EXTRAS_DO_NOT_RETRY, true);
+ extras.putBoolean(ContentResolver.SYNC_EXTRAS_PRIORITY, true);
+ extras.getBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_SETTINGS, true);
+ SyncRequest request = new SyncRequest.Builder()
+ .setSyncAdapter(null, authority)
+ .syncOnce()
+ .setExtras(extras)
+ .setExpedited(true)
+ .setManual(true)
+ .build();
+ ContentResolver.requestSync(request);
+
+ return request;
+ }
+}
diff --git a/tests/tests/content/res/xml/accountaccesssyncadapter.xml b/tests/tests/content/res/xml/always_syncable_account_access_adapter.xml
similarity index 100%
rename from tests/tests/content/res/xml/accountaccesssyncadapter.xml
rename to tests/tests/content/res/xml/always_syncable_account_access_adapter.xml
diff --git a/tests/tests/content/res/xml/not_always_syncable_account_access_adapter.xml b/tests/tests/content/res/xml/not_always_syncable_account_access_adapter.xml
new file mode 100644
index 0000000..bc2e9fd
--- /dev/null
+++ b/tests/tests/content/res/xml/not_always_syncable_account_access_adapter.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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.
+-->
+
+<sync-adapter
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:contentAuthority="com.android.cts.stub.provider2"
+ android:accountType="com.stub"
+ android:userVisible="false"
+ android:supportsUploading="false"
+ android:allowParallelSyncs="false"
+ android:isAlwaysSyncable="false">
+</sync-adapter>
diff --git a/tests/tests/content/src/android/content/cts/AccountAccessSameCertTest.java b/tests/tests/content/src/android/content/cts/AccountAccessSameCertTest.java
index db27352..95af4ca 100644
--- a/tests/tests/content/src/android/content/cts/AccountAccessSameCertTest.java
+++ b/tests/tests/content/src/android/content/cts/AccountAccessSameCertTest.java
@@ -16,34 +16,26 @@
package android.content.cts;
-import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
+import static com.android.cts.content.Utils.ALWAYS_SYNCABLE_AUTHORITY;
+import static com.android.cts.content.Utils.SYNC_TIMEOUT_MILLIS;
+import static com.android.cts.content.Utils.allowSyncAdapterRunInBackgroundAndDataInBackground;
+import static com.android.cts.content.Utils.disallowSyncAdapterRunInBackgroundAndDataInBackground;
+import static com.android.cts.content.Utils.hasDataConnection;
+import static com.android.cts.content.Utils.requestSync;
+import static com.android.cts.content.Utils.withAccount;
import static org.junit.Assume.assumeTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.verify;
-import android.accounts.Account;
-import android.accounts.AccountManager;
-import android.app.Activity;
import android.content.AbstractThreadedSyncAdapter;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.SyncRequest;
-import android.content.pm.PackageManager;
-import android.net.ConnectivityManager;
-import android.net.NetworkInfo;
-import android.os.Bundle;
-import android.os.Process;
-import android.os.SystemClock;
-import android.support.test.InstrumentationRegistry;
+import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
-import com.android.compatibility.common.util.SystemUtil;
+import com.android.cts.content.AlwaysSyncableSyncService;
import com.android.cts.content.FlakyTestRule;
import com.android.cts.content.StubActivity;
-import com.android.cts.content.SyncAdapter;
import org.junit.After;
import org.junit.Before;
@@ -52,18 +44,17 @@
import org.junit.rules.TestRule;
import org.junit.runner.RunWith;
-import java.io.IOException;
-
/**
* Tests whether a sync adapter can access accounts.
*/
@RunWith(AndroidJUnit4.class)
public class AccountAccessSameCertTest {
- private static final long SYNC_TIMEOUT_MILLIS = 20000; // 20 sec
-
@Rule
public final TestRule mFlakyTestTRule = new FlakyTestRule(3);
+ @Rule
+ public final ActivityTestRule<StubActivity> activity = new ActivityTestRule(StubActivity.class);
+
@Before
public void setUp() throws Exception {
allowSyncAdapterRunInBackgroundAndDataInBackground();
@@ -77,83 +68,15 @@
@Test
public void testAccountAccess_sameCertAsAuthenticatorCanSeeAccount() throws Exception {
assumeTrue(hasDataConnection());
- assumeTrue(hasNotificationSupport());
- Intent intent = new Intent(getContext(), StubActivity.class);
- intent.addFlags(FLAG_ACTIVITY_NEW_TASK);
- Activity activity = InstrumentationRegistry.getInstrumentation().startActivitySync(intent);
+ try (AutoCloseable ignored = withAccount(activity.getActivity())) {
+ AbstractThreadedSyncAdapter adapter = AlwaysSyncableSyncService.getInstance(
+ activity.getActivity()).setNewDelegate();
- AccountManager accountManager = getContext().getSystemService(AccountManager.class);
- Bundle result = accountManager.addAccount("com.stub", null, null, null, activity,
- null, null).getResult();
-
- Account addedAccount = new Account(
- result.getString(AccountManager.KEY_ACCOUNT_NAME),
- result.getString(AccountManager.KEY_ACCOUNT_TYPE));
-
- waitForSyncManagerAccountChangeUpdate();
-
- try {
- AbstractThreadedSyncAdapter adapter = SyncAdapter.setNewDelegate();
-
- Bundle extras = new Bundle();
- extras.putBoolean(ContentResolver.SYNC_EXTRAS_DO_NOT_RETRY, true);
- extras.putBoolean(ContentResolver.SYNC_EXTRAS_PRIORITY, true);
- extras.getBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_SETTINGS, true);
- SyncRequest request = new SyncRequest.Builder()
- .setSyncAdapter(null, "com.android.cts.stub.provider")
- .syncOnce()
- .setExtras(extras)
- .setExpedited(true)
- .setManual(true)
- .build();
- ContentResolver.requestSync(request);
+ requestSync(ALWAYS_SYNCABLE_AUTHORITY);
verify(adapter, timeout(SYNC_TIMEOUT_MILLIS)).onPerformSync(any(), any(), any(), any(),
any());
- } finally {
- accountManager.removeAccount(addedAccount, activity, null, null);
- activity.finish();
}
}
-
- private Context getContext() {
- return InstrumentationRegistry.getInstrumentation().getContext();
- }
-
- private void waitForSyncManagerAccountChangeUpdate() {
- // Wait for the sync manager to be notified for the new account.
- // Unfortunately, there is no way to detect this event, sigh...
- SystemClock.sleep(SYNC_TIMEOUT_MILLIS);
- }
-
- private boolean hasDataConnection() {
- ConnectivityManager connectivityManager = getContext().getSystemService(
- ConnectivityManager.class);
- NetworkInfo activeNetwork = connectivityManager.getActiveNetworkInfo();
- return activeNetwork != null && activeNetwork.isConnectedOrConnecting();
- }
-
- private boolean hasNotificationSupport() {
- return !getContext().getPackageManager()
- .hasSystemFeature(PackageManager.FEATURE_LEANBACK);
- }
-
- private void allowSyncAdapterRunInBackgroundAndDataInBackground() throws IOException {
- // Allow us to run in the background
- SystemUtil.runShellCommand(InstrumentationRegistry.getInstrumentation(),
- "cmd deviceidle whitelist +" + getContext().getPackageName());
- // Allow us to use data in the background
- SystemUtil.runShellCommand(InstrumentationRegistry.getInstrumentation(),
- "cmd netpolicy add restrict-background-whitelist " + Process.myUid());
- }
-
- private void disallowSyncAdapterRunInBackgroundAndDataInBackground() throws IOException {
- // Allow us to run in the background
- SystemUtil.runShellCommand(InstrumentationRegistry.getInstrumentation(),
- "cmd deviceidle whitelist -" + getContext().getPackageName());
- // Allow us to use data in the background
- SystemUtil.runShellCommand(InstrumentationRegistry.getInstrumentation(),
- "cmd netpolicy remove restrict-background-whitelist " + Process.myUid());
- }
}
diff --git a/tests/tests/content/src/android/content/cts/DeferSyncTest.java b/tests/tests/content/src/android/content/cts/DeferSyncTest.java
new file mode 100644
index 0000000..457da10
--- /dev/null
+++ b/tests/tests/content/src/android/content/cts/DeferSyncTest.java
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.cts;
+
+import static com.android.cts.content.Utils.ALWAYS_SYNCABLE_AUTHORITY;
+import static com.android.cts.content.Utils.NOT_ALWAYS_SYNCABLE_AUTHORITY;
+import static com.android.cts.content.Utils.SYNC_TIMEOUT_MILLIS;
+import static com.android.cts.content.Utils.allowSyncAdapterRunInBackgroundAndDataInBackground;
+import static com.android.cts.content.Utils.disallowSyncAdapterRunInBackgroundAndDataInBackground;
+import static com.android.cts.content.Utils.hasDataConnection;
+import static com.android.cts.content.Utils.requestSync;
+import static com.android.cts.content.Utils.withAccount;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
+import static org.mockito.ArgumentCaptor.forClass;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.atLeast;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.timeout;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.AbstractThreadedSyncAdapter;
+import android.content.ContentResolver;
+import android.os.Bundle;
+import android.support.test.rule.ActivityTestRule;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.android.cts.content.AlwaysSyncableSyncService;
+import com.android.cts.content.FlakyTestRule;
+import com.android.cts.content.NotAlwaysSyncableSyncService;
+import com.android.cts.content.StubActivity;
+import com.android.cts.content.Utils;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TestRule;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+
+@RunWith(AndroidJUnit4.class)
+public class DeferSyncTest {
+ @Rule
+ public final TestRule flakyTestRule = new FlakyTestRule(3);
+
+ @Rule
+ public final ActivityTestRule<StubActivity> activity = new ActivityTestRule(StubActivity.class);
+
+ @Before
+ public void setUp() throws Exception {
+ allowSyncAdapterRunInBackgroundAndDataInBackground();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ disallowSyncAdapterRunInBackgroundAndDataInBackground();
+ }
+
+ @Test
+ public void noSyncsWhenDeferred() throws Exception {
+ assumeTrue(hasDataConnection());
+
+ AbstractThreadedSyncAdapter notAlwaysSyncableAdapter =
+ NotAlwaysSyncableSyncService.getInstance(activity.getActivity()).setNewDelegate();
+ AbstractThreadedSyncAdapter alwaysSyncableAdapter =
+ AlwaysSyncableSyncService.getInstance(activity.getActivity()).setNewDelegate();
+
+ when(alwaysSyncableAdapter.onUnsyncableAccount()).thenReturn(false);
+ when(notAlwaysSyncableAdapter.onUnsyncableAccount()).thenReturn(false);
+
+ try (Utils.ClosableAccount ignored = withAccount(activity.getActivity())) {
+ requestSync(NOT_ALWAYS_SYNCABLE_AUTHORITY);
+ requestSync(ALWAYS_SYNCABLE_AUTHORITY);
+
+ Thread.sleep(SYNC_TIMEOUT_MILLIS);
+
+ verify(notAlwaysSyncableAdapter, atLeast(1)).onUnsyncableAccount();
+ verify(notAlwaysSyncableAdapter, never()).onPerformSync(any(), any(), any(), any(),
+ any());
+
+ verify(alwaysSyncableAdapter, atLeast(1)).onUnsyncableAccount();
+ verify(alwaysSyncableAdapter, never()).onPerformSync(any(), any(), any(), any(), any());
+ }
+ }
+
+ @Test
+ public void deferSyncAndMakeSyncable() throws Exception {
+ assumeTrue(hasDataConnection());
+
+ AbstractThreadedSyncAdapter adapter = NotAlwaysSyncableSyncService.getInstance(
+ activity.getActivity()).setNewDelegate();
+ when(adapter.onUnsyncableAccount()).thenReturn(false);
+
+ try (Utils.ClosableAccount account = withAccount(activity.getActivity())) {
+ verify(adapter, timeout(SYNC_TIMEOUT_MILLIS)).onUnsyncableAccount();
+
+ // Enable the adapter by making the account/provider syncable
+ ContentResolver.setIsSyncable(account.account, NOT_ALWAYS_SYNCABLE_AUTHORITY, 1);
+ requestSync(NOT_ALWAYS_SYNCABLE_AUTHORITY);
+
+ ArgumentCaptor<Bundle> extrasCaptor = forClass(Bundle.class);
+ verify(adapter, timeout(SYNC_TIMEOUT_MILLIS)).onPerformSync(any(),
+ extrasCaptor.capture(), any(), any(), any());
+
+ // As the adapter is made syncable, we should not get an initialization sync
+ assertFalse(
+ extrasCaptor.getValue().containsKey(ContentResolver.SYNC_EXTRAS_INITIALIZE));
+ }
+ }
+
+ @Test
+ public void deferSyncAndReportIsReady() throws Exception {
+ assumeTrue(hasDataConnection());
+
+ AbstractThreadedSyncAdapter adapter = NotAlwaysSyncableSyncService.getInstance(
+ activity.getActivity()).setNewDelegate();
+ when(adapter.onUnsyncableAccount()).thenReturn(false);
+
+ try (Utils.ClosableAccount ignored = withAccount(activity.getActivity())) {
+ verify(adapter, timeout(SYNC_TIMEOUT_MILLIS)).onUnsyncableAccount();
+
+ // Enable the adapter by returning true from onNewAccount
+ when(adapter.onUnsyncableAccount()).thenReturn(true);
+ requestSync(NOT_ALWAYS_SYNCABLE_AUTHORITY);
+ verify(adapter, atLeast(1)).onUnsyncableAccount();
+
+ ArgumentCaptor<Bundle> extrasCaptor = forClass(Bundle.class);
+ verify(adapter, timeout(SYNC_TIMEOUT_MILLIS)).onPerformSync(any(),
+ extrasCaptor.capture(), any(), any(), any());
+
+ // As the adapter is not syncable yet, we should get an initialization sync
+ assertTrue(extrasCaptor.getValue().getBoolean(ContentResolver.SYNC_EXTRAS_INITIALIZE));
+ }
+ }
+
+ @Test
+ public void deferSyncAndReportIsReadyAlwaysSyncable() throws Exception {
+ assumeTrue(hasDataConnection());
+
+ AbstractThreadedSyncAdapter adapter = AlwaysSyncableSyncService.getInstance(
+ activity.getActivity()).setNewDelegate();
+ when(adapter.onUnsyncableAccount()).thenReturn(false);
+
+ try (Utils.ClosableAccount ignored = withAccount(activity.getActivity())) {
+ verify(adapter, timeout(SYNC_TIMEOUT_MILLIS)).onUnsyncableAccount();
+
+ // Enable the adapter by returning true from onNewAccount
+ when(adapter.onUnsyncableAccount()).thenReturn(true);
+ requestSync(ALWAYS_SYNCABLE_AUTHORITY);
+ verify(adapter, atLeast(1)).onUnsyncableAccount();
+
+ ArgumentCaptor<Bundle> extrasCaptor = forClass(Bundle.class);
+ verify(adapter, timeout(SYNC_TIMEOUT_MILLIS)).onPerformSync(any(),
+ extrasCaptor.capture(), any(), any(), any());
+
+ // The adapter is always syncable, hence there is no init sync
+ assertFalse(
+ extrasCaptor.getValue().containsKey(ContentResolver.SYNC_EXTRAS_INITIALIZE));
+ }
+ }
+
+ @Test
+ public void onNewAccountForEachAccount() throws Exception {
+ assumeTrue(hasDataConnection());
+
+ AbstractThreadedSyncAdapter adapter = NotAlwaysSyncableSyncService.getInstance(
+ activity.getActivity()).setNewDelegate();
+ when(adapter.onUnsyncableAccount()).thenReturn(true, false);
+
+ try (Utils.ClosableAccount account1 = withAccount(activity.getActivity())) {
+ try (Utils.ClosableAccount account2 = withAccount(activity.getActivity())) {
+ verify(adapter, timeout(SYNC_TIMEOUT_MILLIS).atLeast(2)).onUnsyncableAccount();
+
+ // Exactly account should have gotten the init-sync. No further syncs happen as
+ // onNewAccount returns false again.
+ ArgumentCaptor<Bundle> extrasCaptor = forClass(Bundle.class);
+ verify(adapter, timeout(SYNC_TIMEOUT_MILLIS)).onPerformSync(any(),
+ extrasCaptor.capture(), any(), any(), any());
+ assertTrue(
+ extrasCaptor.getValue().getBoolean(ContentResolver.SYNC_EXTRAS_INITIALIZE));
+ }
+ }
+ }
+
+}
diff --git a/tests/tests/content/src/android/content/cts/MockSyncAdapter.java b/tests/tests/content/src/android/content/cts/MockSyncAdapter.java
index 957859e..c8b0bec 100644
--- a/tests/tests/content/src/android/content/cts/MockSyncAdapter.java
+++ b/tests/tests/content/src/android/content/cts/MockSyncAdapter.java
@@ -19,6 +19,7 @@
import android.accounts.Account;
import android.content.ContentResolver;
import android.content.ISyncAdapter;
+import android.content.ISyncAdapterUnsyncableAccountCallback;
import android.content.ISyncContext;
import android.os.Bundle;
import android.os.RemoteException;
@@ -76,6 +77,12 @@
this.mLatch = mLatch;
}
+ @Override
+ public void onUnsyncableAccount(ISyncAdapterUnsyncableAccountCallback cb)
+ throws RemoteException {
+ cb.onUnsyncableAccountDone(true);
+ }
+
public void startSync(ISyncContext syncContext, String authority, Account account,
Bundle extras) throws RemoteException {
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/DrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/DrawableTest.java
index 13cc2e0..3c26f39 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/DrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/DrawableTest.java
@@ -213,6 +213,39 @@
}
}
+ private Boolean isClosed = new Boolean(false);
+
+ @Test
+ public void testCreateFromStream2() throws IOException {
+ FileInputStream inputStream = null;
+ File imageFile = null;
+ synchronized (isClosed) {
+ isClosed = false;
+ try {
+ imageFile = new File(mContext.getFilesDir(), "tempimage.jpg");
+ writeSampleImage(imageFile);
+
+ inputStream = new FileInputStream(imageFile) {
+ @Override
+ public void close() throws IOException {
+ super.close();
+ isClosed = true;
+ }
+ };
+ assertNotNull(Drawable.createFromStream(inputStream, "Sample"));
+ } finally {
+ if (null != inputStream) {
+ // verify that the stream was not closed
+ assertFalse(isClosed);
+ inputStream.close();
+ }
+ if (imageFile.exists()) {
+ assertTrue(imageFile.delete());
+ }
+ }
+ }
+ }
+
@Test
public void testCreateFromResourceStream1() throws IOException {
FileInputStream inputEmptyStream = null;
diff --git a/tests/tests/media/libmediandkjni/native-media-jni.cpp b/tests/tests/media/libmediandkjni/native-media-jni.cpp
index 9439ed1..9c4d6f2 100644
--- a/tests/tests/media/libmediandkjni/native-media-jni.cpp
+++ b/tests/tests/media/libmediandkjni/native-media-jni.cpp
@@ -35,6 +35,7 @@
#include "media/NdkMediaExtractor.h"
#include "media/NdkMediaCodec.h"
#include "media/NdkMediaCrypto.h"
+#include "media/NdkMediaDataSource.h"
#include "media/NdkMediaFormat.h"
#include "media/NdkMediaMuxer.h"
@@ -76,6 +77,49 @@
}
};
+struct FdDataSource {
+
+ FdDataSource(int fd, jlong offset, jlong size)
+ : mFd(fd),
+ mOffset(offset),
+ mSize(size) {
+ }
+
+ ssize_t readAt(off64_t offset, void *data, size_t size) {
+ ssize_t ssize = size;
+ if (!data || offset < 0 || offset >= mSize || offset + ssize < offset) {
+ return -1;
+ }
+ if (offset + ssize > mSize) {
+ ssize = mSize - offset;
+ }
+ if (lseek(mFd, mOffset + offset, SEEK_SET) < 0) {
+ return -1;
+ }
+ return read(mFd, data, ssize);
+ }
+
+ ssize_t getSize() {
+ return mSize;
+ }
+
+private:
+
+ int mFd;
+ off64_t mOffset;
+ int64_t mSize;
+
+};
+
+static ssize_t FdSourceReadAt(void *userdata, off64_t offset, void *data, size_t size) {
+ FdDataSource *src = (FdDataSource*) userdata;
+ return src->readAt(offset, data, size);
+}
+
+static ssize_t FdSourceGetSize(void *userdata) {
+ FdDataSource *src = (FdDataSource*) userdata;
+ return src->getSize();
+}
jobject testExtractor(AMediaExtractor *ex, JNIEnv *env) {
@@ -220,11 +264,22 @@
}
extern "C" jobject Java_android_media_cts_NativeDecoderTest_getDecodedDataNative(JNIEnv *env,
- jclass /*clazz*/, int fd, jlong offset, jlong size) {
+ jclass /*clazz*/, int fd, jlong offset, jlong size, jboolean wrapFd) {
ALOGV("getDecodedDataNative");
+ FdDataSource fdSrc(fd, offset, size);
AMediaExtractor *ex = AMediaExtractor_new();
- int err = AMediaExtractor_setDataSourceFd(ex, fd, offset, size);
+ AMediaDataSource *ndkSrc = AMediaDataSource_new();
+
+ int err;
+ if (wrapFd) {
+ AMediaDataSource_setUserdata(ndkSrc, &fdSrc);
+ AMediaDataSource_setReadAt(ndkSrc, FdSourceReadAt);
+ AMediaDataSource_setGetSize(ndkSrc, FdSourceGetSize);
+ err = AMediaExtractor_setDataSourceCustom(ex, ndkSrc);
+ } else {
+ err = AMediaExtractor_setDataSourceFd(ex, fd, offset, size);
+ }
if (err != 0) {
ALOGE("setDataSource error: %d", err);
return NULL;
@@ -367,6 +422,7 @@
delete[] format;
delete[] codec;
AMediaExtractor_delete(ex);
+ AMediaDataSource_delete(ndkSrc);
return ret;
}
diff --git a/tests/tests/media/src/android/media/cts/NativeDecoderTest.java b/tests/tests/media/src/android/media/cts/NativeDecoderTest.java
index 32cf661..f688e09 100644
--- a/tests/tests/media/src/android/media/cts/NativeDecoderTest.java
+++ b/tests/tests/media/src/android/media/cts/NativeDecoderTest.java
@@ -203,7 +203,18 @@
}
}
+ public void testDataSource() throws Exception {
+ int testsRun = testDecoder(R.raw.video_176x144_3gp_h263_300kbps_12fps_aac_mono_24kbps_11025hz, true);
+ if (testsRun == 0) {
+ MediaUtils.skipTest("no decoders found");
+ }
+ }
+
private int testDecoder(int res) throws Exception {
+ return testDecoder(res, /* wrapFd */ false);
+ }
+
+ private int testDecoder(int res, boolean wrapFd) throws Exception {
if (!MediaUtils.hasCodecsForResource(mContext, res)) {
return 0; // skip
}
@@ -213,7 +224,7 @@
int[] jdata = getDecodedData(
fd.getFileDescriptor(), fd.getStartOffset(), fd.getLength());
int[] ndata = getDecodedDataNative(
- fd.getParcelFileDescriptor().getFd(), fd.getStartOffset(), fd.getLength());
+ fd.getParcelFileDescriptor().getFd(), fd.getStartOffset(), fd.getLength(), wrapFd);
fd.close();
Log.i("@@@", Arrays.toString(jdata));
@@ -384,7 +395,7 @@
return ret;
}
- private static native int[] getDecodedDataNative(int fd, long offset, long size)
+ private static native int[] getDecodedDataNative(int fd, long offset, long size, boolean wrapFd)
throws IOException;
public void testVideoPlayback() throws Exception {