Merge "CtsVerifier: Modify camera intents test to test for exif and location of image" am: 4ad716fdca am: 56e7e5341c am: c7b54cb36e
Change-Id: I9c15c6fb37f762dbe6e70c1739a78755f2fb1b9b
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/camera/intents/CameraIntentsActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/camera/intents/CameraIntentsActivity.java
index 2757237..b7a80de 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/camera/intents/CameraIntentsActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/camera/intents/CameraIntentsActivity.java
@@ -26,6 +26,7 @@
import android.content.pm.PackageManager;
import android.content.pm.PermissionInfo;
import android.hardware.Camera;
+import android.media.ExifInterface;
import android.media.MediaMetadataRetriever;
import android.net.Uri;
import android.os.AsyncTask;
@@ -51,6 +52,8 @@
import static android.media.MediaMetadataRetriever.METADATA_KEY_LOCATION;
import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
import java.util.TreeSet;
import java.util.Date;
import java.text.SimpleDateFormat;
@@ -103,7 +106,8 @@
private ImageButton mFailButton;
private Button mStartTestButton;
private Button mSettingsButton;
- private File mVideoTargetDir = null;
+ private File mDebugFolder = null;
+ private File mImageTarget = null;
private File mVideoTarget = null;
private int mState = STATE_OFF;
// MediaStore.Images.Media.EXTERNAL_CONTENT_URI or
@@ -420,49 +424,90 @@
mActivityResult = true;
synchronized(mLock) {
if (mState != STATE_FAILED) {
- /**
- * For images, we don't need to do more checks, since location in image exif is
- * checked by cts test: MediaStoreUiTest .
- */
- if (stageIndex == STAGE_INTENT_PICTURE) {
- mActionSuccess = true;
- // Set UriSuccess to true to avoid long wait in WaitForTriggerTask
- mUriSuccess = true;
- updateSuccessState();
- return;
+ switch (stageIndex) {
+ case STAGE_INTENT_PICTURE:
+ handleIntentPictureResult();
+ break;
+ case STAGE_INTENT_VIDEO:
+ handleIntentVideoResult();
+ break;
+ default:
+ return;
}
- if (stageIndex != STAGE_INTENT_VIDEO) {
- return;
- }
-
- if (mVideoTarget == null) {
- Log.d(TAG, "Video target was not set");
- return;
- }
- /**
- * Check that there is no location data in video.
- */
- MediaMetadataRetriever mediaRetriever = new MediaMetadataRetriever();
- mediaRetriever.setDataSource(mVideoTarget.toString());
- if (mediaRetriever.extractMetadata(METADATA_KEY_HAS_VIDEO) == null ||
- mediaRetriever.extractMetadata(METADATA_KEY_LOCATION) != null) {
- mState = STATE_FAILED;
- } else {
- mVideoTarget.delete();
- }
- Log.d(TAG, "METADATA_KEY_HAS_VIDEO: " +
- mediaRetriever.extractMetadata(METADATA_KEY_HAS_VIDEO) +
- " METADATA_KEY_LOCATION: " +
- mediaRetriever.extractMetadata(METADATA_KEY_LOCATION));
- mediaRetriever.release();
- /* successful, unless we get the URI trigger back
- at some point later on */
- mActionSuccess = true;
}
}
}
}
+ private void handleIntentPictureResult() {
+ if (mImageTarget == null) {
+ Log.d(TAG, "Image target was not set");
+ return;
+ }
+ try {
+ if (!mImageTarget.exists() || mImageTarget.length() <= 65536) {
+ Log.d(TAG, "Image target does not exist or it is too small");
+ mState = STATE_FAILED;
+ return;
+ }
+
+ try {
+ final ExifInterface exif = new ExifInterface(new FileInputStream(mImageTarget));
+ if (!checkExifAttribute(exif, ExifInterface.TAG_MAKE)
+ || !checkExifAttribute(exif, ExifInterface.TAG_MODEL)
+ || !checkExifAttribute(exif, ExifInterface.TAG_DATETIME)) {
+ Log.d(TAG, "The required tag does not appear in the exif");
+ mState = STATE_FAILED;
+ return;
+ }
+
+ float[] latLong = new float[2];
+ if (exif.getLatLong(latLong)) {
+ Log.d(TAG, "Should not contain location information");
+ mState = STATE_FAILED;
+ return;
+ }
+ mActionSuccess = true;
+ } catch (IOException ex) {
+ Log.e(TAG, "Failed to verify Exif", ex);
+ mState = STATE_FAILED;
+ return;
+ }
+ } finally {
+ mImageTarget.delete();
+ }
+ }
+
+ private void handleIntentVideoResult() {
+ if (mVideoTarget == null) {
+ Log.d(TAG, "Video target was not set");
+ return;
+ }
+ /**
+ * Check that there is no location data in video.
+ */
+ MediaMetadataRetriever mediaRetriever = new MediaMetadataRetriever();
+ mediaRetriever.setDataSource(mVideoTarget.toString());
+ if (mediaRetriever.extractMetadata(METADATA_KEY_HAS_VIDEO) == null ||
+ mediaRetriever.extractMetadata(METADATA_KEY_LOCATION) != null) {
+ mState = STATE_FAILED;
+ } else {
+ mVideoTarget.delete();
+ }
+ Log.d(TAG, "METADATA_KEY_HAS_VIDEO: " +
+ mediaRetriever.extractMetadata(METADATA_KEY_HAS_VIDEO) +
+ " METADATA_KEY_LOCATION: " +
+ mediaRetriever.extractMetadata(METADATA_KEY_LOCATION));
+ mediaRetriever.release();
+ /* successful, unless we get the URI trigger back at some point later on. */
+ mActionSuccess = true;
+ }
+
+ private boolean checkExifAttribute(ExifInterface exif, String tag) {
+ final String res = exif.getAttribute(tag);
+ return res != null && res.length() > 0;
+ }
+
@Override
public String getTestDetails() {
return mReportBuilder.toString();
@@ -549,7 +594,7 @@
* Video intents do not need to wait on a ContentProvider broadcast since we're starting
* the intent activity with EXTRA_OUTPUT set
*/
- if (stageIndex != STAGE_INTENT_VIDEO) {
+ if (stageIndex != STAGE_INTENT_VIDEO && stageIndex != STAGE_INTENT_PICTURE) {
JobInfo job = makeJobInfo(TEST_JOB_TYPES[stageIndex]);
jobScheduler.schedule(job);
new WaitForTriggerTask().execute();
@@ -575,21 +620,33 @@
if (intentStr != null) {
cameraIntent = new Intent(intentStr);
- if (stageIndex == STAGE_INTENT_VIDEO) {
- String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
- mVideoTargetDir = new File(this.getFilesDir(), "debug");
- mVideoTarget = new File(mVideoTargetDir, timeStamp + "video.mp4");
- mVideoTargetDir.mkdirs();
- if (!mVideoTargetDir.exists()) {
- Toast.makeText(this, R.string.ci_directory_creation_error,
- Toast.LENGTH_SHORT).show();
- Log.v(TAG, "Could not create directory");
- return;
- }
- cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, FileProvider.getUriForFile(this,
- "com.android.cts.verifier.managedprovisioning.fileprovider",
- mVideoTarget));
+ mDebugFolder = new File(this.getFilesDir(), "debug");
+ mDebugFolder.mkdirs();
+ if (!mDebugFolder.exists()) {
+ Toast.makeText(this, R.string.ci_directory_creation_error,
+ Toast.LENGTH_SHORT).show();
+ Log.v(TAG, "Could not create directory");
+ return;
}
+
+ File targetFile;
+ String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
+ switch (stageIndex) {
+ case STAGE_INTENT_PICTURE:
+ mImageTarget = new File(mDebugFolder, timeStamp + "capture.jpg");
+ targetFile = mImageTarget;
+ break;
+ case STAGE_INTENT_VIDEO:
+ mVideoTarget = new File(mDebugFolder, timeStamp + "video.mp4");
+ targetFile = mVideoTarget;
+ break;
+ default:
+ Log.wtf(TAG, "Unexpected stage index to send intent with extras");
+ return;
+ }
+ cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, FileProvider.getUriForFile(this,
+ "com.android.cts.verifier.managedprovisioning.fileprovider",
+ targetFile));
startActivityForResult(cameraIntent, 1337 + getStageIndex());
}