import com.android.camera.one.v2.core.RequestTemplate;
import com.android.camera.one.v2.core.ResponseListener;
import com.android.camera.one.v2.core.ResponseListeners;
+import com.android.camera.one.v2.errorhandling.FramerateJankDetector;
import com.android.camera.one.v2.errorhandling.RepeatFailureHandlerComponent;
import com.android.camera.one.v2.imagesaver.ImageSaver;
import com.android.camera.one.v2.initialization.CameraStarter;
rootBuilder.addResponseListener(failureDetector);
}
+ if (ApiHelper.IS_NEXUS_6) {
+ rootBuilder.addResponseListener(
+ new FramerateJankDetector(Loggers.tagFactory()));
+ }
+
final Observable<Integer> availableImageCount = sharedImageReaderFactory
.provideAvailableImageCount();
final Observable<Boolean> frameServerAvailability = frameServerComponent
--- /dev/null
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.camera.one.v2.errorhandling;
+
+import android.annotation.TargetApi;
+import android.hardware.camera2.CaptureResult;
+import android.hardware.camera2.TotalCaptureResult;
+import android.os.Build.VERSION_CODES;
+
+import com.android.camera.debug.Log.Tag;
+import com.android.camera.debug.Logger;
+import com.android.camera.one.v2.core.ResponseListener;
+
+import javax.annotation.ParametersAreNonnullByDefault;
+
+/**
+ * Detect jank in the preview by detecting large percentage increases in the time
+ * delta between the sensor timestamps retrieved from the camera.
+ */
+@ParametersAreNonnullByDefault
+@TargetApi(VERSION_CODES.L)
+public final class FramerateJankDetector extends ResponseListener {
+ private static final double PERCENT_CHANGE_LOG_THRESHOLD = 1.20;
+
+ private final Logger mLog;
+
+ private long mLastFrameTimestamp = -1;
+ private double mLastDeltaMillis = 0.0;
+
+ /**
+ * @param logFactory Used for logging.
+ */
+ public FramerateJankDetector(Logger.Factory logFactory) {
+ mLog = logFactory.create(new Tag("FrameJank"));
+ }
+
+ @Override
+ public void onCompleted(TotalCaptureResult result) {
+ long timestamp = result.get(CaptureResult.SENSOR_TIMESTAMP);
+ if (mLastFrameTimestamp >= 0) {
+ double deltaMillis = (timestamp - mLastFrameTimestamp) / 1000000.0;
+
+ if (mLastDeltaMillis > 0) {
+ double percentChange = (deltaMillis - mLastDeltaMillis) / mLastDeltaMillis;
+ if (percentChange >= PERCENT_CHANGE_LOG_THRESHOLD) {
+ mLog.v("JANK. Time between frames (" + deltaMillis + "ms) increased by " +
+ (percentChange * 100) + "% over the last frame delta (" +
+ mLastDeltaMillis + "ms)");
+ }
+ }
+ mLastDeltaMillis = deltaMillis;
+ }
+
+ mLastFrameTimestamp = timestamp;
+ }
+}