Merge "Calculating jank from the timestamps."
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index 79db2b0..ed2ecd4 100644
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -568,6 +568,11 @@
     <string name="camera_fov_choose_preview_size_for_camera">Choose preview size for camera %1$s</string>
     <string name="camera_fov_displayed_fov_label">Displayed FOV : </string>
     <string name="camera_fov_reported_fov_label">Reported  FOV : </string>
+    <string name="camera_fov_reported_fov_problem">Reported FOV problem</string>
+    <string name="camera_fov_reported_fov_problem_message">The reported FOV before takePicture() is
+        different from when onPictureTaken() is called.\nAs picture size has not been changed, the
+        reported FOV should be identical at both times.\n\nFOV before/after: %1$f / %2$f</string>
+
     <string name="camera_fov_panorama_wallpaper_title">Photo Sphere Live Wallpaper</string>
     <string name="camera_fov_panorama_wallpaper_description">This live wallapper displays photo
         spheres.</string>
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/camera/fov/PhotoCaptureActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/camera/fov/PhotoCaptureActivity.java
index 913ff4f..05013ed 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/camera/fov/PhotoCaptureActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/camera/fov/PhotoCaptureActivity.java
@@ -18,12 +18,14 @@
 
 import android.app.Activity;
 import android.app.AlertDialog;
+import android.app.Dialog;
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.Intent;
 import android.graphics.Color;
 import android.hardware.Camera;
 import android.hardware.Camera.PictureCallback;
+import android.hardware.Camera.ShutterCallback;
 import android.os.Bundle;
 import android.os.PowerManager;
 import android.os.PowerManager.WakeLock;
@@ -58,6 +60,7 @@
     private static final int FOV_REQUEST_CODE = 1006;
     private static final String PICTURE_FILENAME = "photo.jpg";
     private static float mReportedFovDegrees = 0;
+    private float mReportedFovPrePictureTaken = -1;
 
     private SurfaceView mPreview;
     private SurfaceHolder mSurfaceHolder;
@@ -72,9 +75,12 @@
     private boolean mPreviewActive = false;
     private int mResolutionSpinnerIndex = -1;
     private WakeLock mWakeLock;
+    private long shutterStartTime;
 
     private ArrayList<Integer> mPreviewSizeCamerasToProcess = new ArrayList<Integer>();
 
+    private Dialog mActiveDialog;
+
     /**
      * Selected preview size per camera. If null, preview size should be
      * automatically detected.
@@ -139,7 +145,15 @@
         previewView.setOnClickListener(new OnClickListener() {
             @Override
             public void onClick(View v) {
-                mCamera.takePicture(null, null, PhotoCaptureActivity.this);
+                shutterStartTime = System.currentTimeMillis();
+
+                mCamera.takePicture(new ShutterCallback() {
+                    @Override
+                    public void onShutter() {
+                        long dT = System.currentTimeMillis() - shutterStartTime;
+                        Log.d("CTS", "Shutter Lag: " + dT);
+                    }
+                }, null, PhotoCaptureActivity.this);
             }
         });
 
@@ -151,11 +165,17 @@
                 if (mSupportedResolutions != null) {
                     SelectableResolution resolution = mSupportedResolutions.get(position);
 
-                    switchToCamera(resolution.cameraId);
+                    switchToCamera(resolution.cameraId, false);
+
                     Camera.Parameters params = mCamera.getParameters();
                     params.setPictureSize(resolution.width, resolution.height);
                     mCamera.setParameters(params);
+
+                    // It should be guaranteed that the FOV is correctly updated after setParameters().
+                    mReportedFovPrePictureTaken = mCamera.getParameters().getHorizontalViewAngle();
+
                     mResolutionSpinnerIndex = position;
+                    initializeCamera();
                 }
             }
 
@@ -227,6 +247,32 @@
         File pictureFile = getPictureFile(this);
         Camera.Parameters params = mCamera.getParameters();
         mReportedFovDegrees = params.getHorizontalViewAngle();
+
+        // Show error if FOV does not match the value reported before takePicture().
+        if (mReportedFovPrePictureTaken != mReportedFovDegrees) {
+            mSupportedResolutions.get(mResolutionSpinnerIndex).tested = true;
+            mSupportedResolutions.get(mResolutionSpinnerIndex).passed = false;
+
+            AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this);
+            dialogBuilder.setTitle(R.string.camera_fov_reported_fov_problem);
+            dialogBuilder.setNeutralButton(
+                    android.R.string.ok, new DialogInterface.OnClickListener() {
+                @Override
+                public void onClick(DialogInterface dialog, int which) {
+                    if (mActiveDialog != null) {
+                        mActiveDialog.dismiss();
+                        mActiveDialog = null;
+                        initializeCamera();
+                    }
+                }
+            });
+
+            String message  = getResources().getString(R.string.camera_fov_reported_fov_problem_message);
+            dialogBuilder.setMessage(String.format(message, mReportedFovPrePictureTaken, mReportedFovDegrees));
+            mActiveDialog = dialogBuilder.show();
+            return;
+        }
+
         try {
             FileOutputStream fos = new FileOutputStream(pictureFile);
             fos.write(data);
@@ -329,7 +375,7 @@
                     public void onCancel(DialogInterface arg0) {
                         // User cancelled preview size selection.
                         mPreviewSizes = null;
-                        switchToCamera(mCameraId);
+                        switchToCamera(mCameraId, true);
                     }
                 }).
                 setSingleChoiceItems(choices, 0, new DialogInterface.OnClickListener() {
@@ -342,7 +388,7 @@
 
                         if (mPreviewSizeCamerasToProcess.isEmpty()) {
                             // We're done, re-initialize camera.
-                            switchToCamera(mCameraId);
+                            switchToCamera(mCameraId, true);
                         } else {
                             // Process other cameras.
                             showNextDialogToChoosePreviewSize();
@@ -385,14 +431,17 @@
         }
     }
 
-    private void switchToCamera(int cameraId) {
+    private void switchToCamera(int cameraId, boolean initializeCamera) {
         if (mCamera != null) {
             mCamera.stopPreview();
             mCamera.release();
         }
         mCameraId = cameraId;
         mCamera = Camera.open(cameraId);
-        initializeCamera();
+
+        if (initializeCamera){
+          initializeCamera();
+        }
     }
 
     /**
diff --git a/tests/tests/media/src/android/media/cts/Vp8EncoderTest.java b/tests/tests/media/src/android/media/cts/Vp8EncoderTest.java
index 308fb98c..c2f0c32 100644
--- a/tests/tests/media/src/android/media/cts/Vp8EncoderTest.java
+++ b/tests/tests/media/src/android/media/cts/Vp8EncoderTest.java
@@ -40,8 +40,8 @@
 
     private static final String TAG = "VP8EncoderTest";
     private static final String VP8_MIME = "video/x-vnd.on2.vp8";
-    private static final String VPX_DECODER_NAME = "OMX.google.vpx.decoder";
-    private static final String VPX_ENCODER_NAME = "OMX.google.vpx.encoder";
+    private static final String VPX_DECODER_NAME = "OMX.google.vp8.decoder";
+    private static final String VPX_ENCODER_NAME = "OMX.google.vp8.encoder";
     private static final String BASIC_IVF = "video_176x144_vp8_basic.ivf";
     private static final long DEFAULT_TIMEOUT_US = 5000;
 
diff --git a/tests/tests/webkit/src/android/webkit/cts/GeolocationTest.java b/tests/tests/webkit/src/android/webkit/cts/GeolocationTest.java
index 21f1224..85a616f 100644
--- a/tests/tests/webkit/src/android/webkit/cts/GeolocationTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/GeolocationTest.java
@@ -468,7 +468,7 @@
         final TestSimpleGeolocationRequestWebChromeClient chromeClientRejectOnce =
                 new TestSimpleGeolocationRequestWebChromeClient(mOnUiThread, false, false);
         mOnUiThread.setWebChromeClient(chromeClientRejectOnce);
-        // Load url once, and the callback should accept the domain for all future loads
+        // Load url once, and the callback should reject it once
         mOnUiThread.loadUrlAndWaitForCompletion(URL_1);
         Callable<Boolean> receivedRequest = new Callable<Boolean>() {
             @Override
@@ -483,11 +483,12 @@
                 return mJavascriptStatusReceiver.mDenied;
             }
         };
-        PollingCheck.check("JS didn't get position", POLLING_TIMEOUT, locationDenied);
+        PollingCheck.check("JS got position", POLLING_TIMEOUT, locationDenied);
         // Same result should happen on next run
+        chromeClientRejectOnce.mReceivedRequest = false;
         mOnUiThread.loadUrlAndWaitForCompletion(URL_1);
         PollingCheck.check("Geolocation prompt not called", POLLING_TIMEOUT, receivedRequest);
-        PollingCheck.check("JS didn't get position", POLLING_TIMEOUT, locationDenied);
+        PollingCheck.check("JS got position", POLLING_TIMEOUT, locationDenied);
 
         // Try to reject forever
         final TestSimpleGeolocationRequestWebChromeClient chromeClientRejectAlways =