Merge "Initial interface for the burst module." into ub-camera-haleakala
diff --git a/project.properties b/project.properties
index 2f095e1..6e18427 100644
--- a/project.properties
+++ b/project.properties
@@ -11,4 +11,4 @@
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
# Project target.
-target=android-L
+target=android-21
diff --git a/res/layout-land/aspect_ratio_dialog_content.xml b/res/layout-land/aspect_ratio_dialog_content.xml
index c183f1d..7aca76f 100644
--- a/res/layout-land/aspect_ratio_dialog_content.xml
+++ b/res/layout-land/aspect_ratio_dialog_content.xml
@@ -38,8 +38,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/photo_size_selection_title"
- android:textSize="22sp"
- android:textColor="@color/dialog_text_color"
+ style="@style/fullscreen_dialog_title"
android:layout_margin="28dp" />
<TextView
android:layout_width="match_parent"
diff --git a/res/layout-land/location_dialog_content.xml b/res/layout-land/location_dialog_content.xml
index 2577f69..e3dab88 100644
--- a/res/layout-land/location_dialog_content.xml
+++ b/res/layout-land/location_dialog_content.xml
@@ -30,8 +30,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/remember_location_title"
- android:textSize="22sp"
- android:textColor="@color/dialog_text_color"
+ style="@style/fullscreen_dialog_title"
android:layout_marginLeft="28dp"
android:layout_marginRight="28dp"
android:layout_marginBottom="28dp" />
diff --git a/res/layout-port/aspect_ratio_dialog_content.xml b/res/layout-port/aspect_ratio_dialog_content.xml
index 087909e..4086889 100644
--- a/res/layout-port/aspect_ratio_dialog_content.xml
+++ b/res/layout-port/aspect_ratio_dialog_content.xml
@@ -27,8 +27,7 @@
android:layout_margin="28dp"
android:gravity="center"
android:text="@string/photo_size_selection_title"
- android:textSize="22sp"
- android:textColor="@color/dialog_text_color" />
+ style="@style/fullscreen_dialog_title" />
<include
layout="@layout/aspect_ratio_selector"
android:layout_width="match_parent"
diff --git a/res/layout-port/location_dialog_content.xml b/res/layout-port/location_dialog_content.xml
index 0e1e453..fee5d64 100644
--- a/res/layout-port/location_dialog_content.xml
+++ b/res/layout-port/location_dialog_content.xml
@@ -22,8 +22,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/remember_location_title"
- android:textSize="22sp"
- android:textColor="@color/dialog_text_color"
+ style="@style/fullscreen_dialog_title"
android:layout_margin="28dp" />
<ImageView
android:layout_width="wrap_content"
diff --git a/res/values/styles.xml b/res/values/styles.xml
index ad38594..7c0f7ca 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -216,13 +216,18 @@
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">match_parent</item>
</style>
+ <style name="fullscreen_dialog_title">
+ <item name="android:textSize">24sp</item>
+ <item name="android:fontFamily">sans-serif-regular</item>
+ <item name="android:textColor">@color/dialog_text_color</item>
+ </style>
<style name="BlueButton">
<item name="android:layout_width">144dp</item>
<item name="android:layout_height">48dp</item>
<item name="android:background">@drawable/button_cling</item>
- <item name="android:fontFamily">sans-serif-regular</item>
- <item name="android:textColor">@color/blue_button_text_color</item>
<item name="android:textSize">14sp</item>
+ <item name="android:fontFamily">sans-serif-medium</item>
+ <item name="android:textColor">@color/blue_button_text_color</item>
<item name="android:padding">12dp</item>
</style>
</resources>
diff --git a/src/com/android/camera/CaptureModule.java b/src/com/android/camera/CaptureModule.java
index 9b20ee9..a6b7ec6 100644
--- a/src/com/android/camera/CaptureModule.java
+++ b/src/com/android/camera/CaptureModule.java
@@ -19,7 +19,6 @@
import android.app.Activity;
import android.content.Context;
import android.content.res.Configuration;
-import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.graphics.RectF;
import android.graphics.SurfaceTexture;
@@ -460,8 +459,9 @@
@Override
public void onRemoteShutterPress() {
+ Log.d(TAG, "onRemoteShutterPress");
// TODO: Check whether shutter is enabled.
- onShutterButtonClick();
+ takePictureNow();
}
@Override
@@ -546,6 +546,7 @@
@Override
public void pause() {
mPaused = true;
+ getServices().getRemoteShutterListener().onModuleExit();
cancelCountDown();
closeCamera();
resetTextureBufferSize();
@@ -848,8 +849,8 @@
}
@Override
- public void onThumbnailResult(Bitmap bitmap) {
- // TODO
+ public void onThumbnailResult(byte[] jpegData) {
+ getServices().getRemoteShutterListener().onPictureTaken(jpegData);
}
@Override
diff --git a/src/com/android/camera/PhotoModule.java b/src/com/android/camera/PhotoModule.java
index f5d697a..b4b5ee7 100644
--- a/src/com/android/camera/PhotoModule.java
+++ b/src/com/android/camera/PhotoModule.java
@@ -1953,10 +1953,15 @@
}
mFocusManager.setAeAwbLock(false); // Unlock AE and AWB.
}
- setCameraParameters(UPDATE_PARAM_ALL);
+ // Nexus 4 must have picture size set to > 640x480 before other
+ // parameters are set in setCameraParameters, b/18227551. This call to
+ // updateParametersPictureSize should occur before setCameraParameters
+ // to address the issue.
updateParametersPictureSize();
+ setCameraParameters(UPDATE_PARAM_ALL);
+
mCameraDevice.setPreviewTexture(mActivity.getCameraAppUI().getSurfaceTexture());
Log.i(TAG, "startPreview");
diff --git a/src/com/android/camera/data/CameraDataAdapter.java b/src/com/android/camera/data/CameraDataAdapter.java
index 07100ef..7fd2d09 100644
--- a/src/com/android/camera/data/CameraDataAdapter.java
+++ b/src/com/android/camera/data/CameraDataAdapter.java
@@ -180,7 +180,7 @@
int pos = findDataByContentUri(uri);
if (pos != -1) {
// a duplicate one, just do a substitute.
- Log.v(TAG, "found duplicate data");
+ Log.v(TAG, "found duplicate data: " + uri);
updateData(pos, newData);
return false;
} else {
@@ -339,6 +339,7 @@
@Override
protected List<LocalData> doInBackground(ContentResolver... contentResolvers) {
if (mMinPhotoId != LocalMediaData.QUERY_ALL_MEDIA_ID) {
+ Log.v(TAG, "updating media metadata with photos newer than id: " + mMinPhotoId);
final ContentResolver cr = contentResolvers[0];
return LocalMediaData.PhotoData.query(cr, LocalMediaData.PhotoData.CONTENT_URI,
mMinPhotoId);
@@ -348,11 +349,19 @@
@Override
protected void onPostExecute(List<LocalData> newPhotoData) {
+ if (newPhotoData == null) {
+ Log.w(TAG, "null data returned from new photos query");
+ return;
+ }
+ Log.v(TAG, "new photos query return num items: " + newPhotoData.size());
if (!newPhotoData.isEmpty()) {
LocalData newestPhoto = newPhotoData.get(0);
// We may overlap with another load task or a query task, in which case we want
// to be sure we never decrement the oldest seen id.
- mLastPhotoId = Math.max(mLastPhotoId, newestPhoto.getContentId());
+ long newLastPhotoId = newestPhoto.getContentId();
+ Log.v(TAG, "updating last photo id (old:new) " +
+ mLastPhotoId + ":" + newLastPhotoId);
+ mLastPhotoId = Math.max(mLastPhotoId, newLastPhotoId);
}
// We may add data that is already present, but if we do, it will be deduped in addData.
// addData does not dedupe session items, so we ignore them here
@@ -406,12 +415,27 @@
long lastPhotoId = LocalMediaData.QUERY_ALL_MEDIA_ID;
if (!photoData.isEmpty()) {
+ // This relies on {@link LocalMediaData.QUERY_ORDER} returning
+ // items sorted descending by ID, as such we can just pull the
+ // ID from the first item in the result to establish the last
+ // (max) photo ID.
lastPhotoId = photoData.get(0).getContentId();
}
- l.addAll(photoData);
- l.addAll(videoData);
+ if (photoData != null) {
+ Log.v(TAG, "retrieved photo metadata, number of items: " + photoData.size());
+ l.addAll(photoData);
+ }
+ if (videoData != null) {
+ Log.v(TAG, "retrieved video metadata, number of items: " + videoData.size());
+ l.addAll(videoData);
+ }
+ Log.v(TAG, "sorting video/photo metadata");
+ // Photos should be sorted within photo/video by ID, which in most
+ // cases should correlate well to the date taken/modified. This sort
+ // operation makes all photos/videos sorted by date in one list.
l.sort(new LocalData.NewestFirstComparator());
+ Log.v(TAG, "sorted video/photo metadata");
// Load enough metadata so it's already loaded when we open the filmstrip.
for (int i = 0; i < MAX_METADATA && i < l.size(); i++) {
diff --git a/src/com/android/camera/data/LocalMediaData.java b/src/com/android/camera/data/LocalMediaData.java
index 950695f..9956108 100644
--- a/src/com/android/camera/data/LocalMediaData.java
+++ b/src/com/android/camera/data/LocalMediaData.java
@@ -328,8 +328,10 @@
static final Uri CONTENT_URI = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
- private static final String QUERY_ORDER = MediaStore.Images.ImageColumns.DATE_TAKEN + " DESC, "
- + MediaStore.Images.ImageColumns._ID + " DESC";
+ // Sort all data by ID. This must be aligned with
+ // {@link CameraDataAdapter.QueryTask} which relies on the highest ID
+ // being first in any data returned.
+ private static final String QUERY_ORDER = MediaStore.Images.ImageColumns._ID + " DESC";
/**
* These values should be kept in sync with column IDs (COL_*) above.
*/
diff --git a/src/com/android/camera/one/OneCamera.java b/src/com/android/camera/one/OneCamera.java
index fcf0631..743be37 100644
--- a/src/com/android/camera/one/OneCamera.java
+++ b/src/com/android/camera/one/OneCamera.java
@@ -17,7 +17,6 @@
package com.android.camera.one;
import android.content.Context;
-import android.graphics.Bitmap;
import android.location.Location;
import android.net.Uri;
import android.view.Surface;
@@ -159,7 +158,7 @@
* Called when a thumbnail image is provided before the final image is
* finished.
*/
- public void onThumbnailResult(Bitmap bitmap);
+ public void onThumbnailResult(byte[] jpegData);
/**
* Called when the final picture is done taking
diff --git a/src/com/android/camera/settings/SettingsUtil.java b/src/com/android/camera/settings/SettingsUtil.java
index d0f9b09..acf8921 100644
--- a/src/com/android/camera/settings/SettingsUtil.java
+++ b/src/com/android/camera/settings/SettingsUtil.java
@@ -24,6 +24,7 @@
import android.util.SparseArray;
import com.android.camera.debug.Log;
+import com.android.camera.util.ApiHelper;
import com.android.camera.util.Callback;
import com.android.camera2.R;
import com.android.ex.camera2.portability.CameraDeviceInfo;
@@ -353,7 +354,8 @@
*/
private static int getNextSupportedVideoQualityIndex(int cameraId, int start) {
for (int i = start + 1; i < sVideoQualities.length; ++i) {
- if (CamcorderProfile.hasProfile(cameraId, sVideoQualities[i])) {
+ if (isVideoQualitySupported(sVideoQualities[i])
+ && CamcorderProfile.hasProfile(cameraId, sVideoQualities[i])) {
// We found a new supported quality.
return i;
}
@@ -371,6 +373,19 @@
}
/**
+ * @return Whether the given {@link CamcorderProfile} is supported on the
+ * current device/OS version.
+ */
+ private static boolean isVideoQualitySupported(int videoQuality) {
+ // 4k is only supported on L or higher but some devices falsely report
+ // to have support for it on K, see b/18172081.
+ if (!ApiHelper.isLOrHigher() && videoQuality == CamcorderProfile.QUALITY_2160P) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
* Returns the index of the size within the given list that is closest to
* the given target pixel count.
*/
diff --git a/src/com/android/camera/ui/PreviewOverlay.java b/src/com/android/camera/ui/PreviewOverlay.java
index 3ccc758..6ff8549 100644
--- a/src/com/android/camera/ui/PreviewOverlay.java
+++ b/src/com/android/camera/ui/PreviewOverlay.java
@@ -259,9 +259,8 @@
}
public void layout(int l, int t, int r, int b) {
- // TODO: Needs to be centered in preview TextureView
- mCenterX = (r - l) / 2;
- mCenterY = (b - t) / 2;
+ mCenterX = (r + l) / 2;
+ mCenterY = (b + t) / 2;
// UI will extend from 20% to 80% of maximum inset circle.
float insetCircleDiameter = Math.min(getWidth(), getHeight());
mOuterRadius = insetCircleDiameter * 0.5f * ZOOM_UI_SIZE;
diff --git a/src/com/android/camera/util/ApiHelper.java b/src/com/android/camera/util/ApiHelper.java
index 8e25464..7f6f59c 100644
--- a/src/com/android/camera/util/ApiHelper.java
+++ b/src/com/android/camera/util/ApiHelper.java
@@ -60,6 +60,10 @@
&& "hammerhead".equalsIgnoreCase(Build.DEVICE);
public static final boolean IS_NEXUS_6 = "motorola".equalsIgnoreCase(Build.MANUFACTURER)
&& "shamu".equalsIgnoreCase(Build.DEVICE);
+ public static final boolean IS_NEXUS_9 = "htc".equalsIgnoreCase(Build.MANUFACTURER)
+ && ("flounder".equalsIgnoreCase(Build.DEVICE)
+ || "flounder_lte".equalsIgnoreCase(Build.DEVICE));
+ public static final boolean IS_HTC = "htc".equalsIgnoreCase(Build.MANUFACTURER);
public static final boolean HAS_CAMERA_2_API = isLOrHigher();
diff --git a/src/com/android/camera/util/CameraUtil.java b/src/com/android/camera/util/CameraUtil.java
index 658e73b..d6237a9 100644
--- a/src/com/android/camera/util/CameraUtil.java
+++ b/src/com/android/camera/util/CameraUtil.java
@@ -40,7 +40,6 @@
import android.os.ParcelFileDescriptor;
import android.telephony.TelephonyManager;
import android.util.DisplayMetrics;
-import android.util.FloatMath;
import android.util.TypedValue;
import android.view.Display;
import android.view.OrientationEventListener;
@@ -514,7 +513,15 @@
public static int getOptimalPreviewSizeIndex(Context context,
List<Size> sizes, double targetRatio) {
// Use a very small tolerance because we want an exact match.
- final double ASPECT_TOLERANCE = 0.01;
+ final double ASPECT_TOLERANCE;
+ // HTC 4:3 ratios is over .01 from true 4:3, targeted fix for those
+ // devices here, see b/18241645
+ if (ApiHelper.IS_HTC && targetRatio > 1.3433 && targetRatio < 1.35) {
+ Log.w(TAG, "4:3 ratio out of normal tolerance, increasing tolerance to 0.02");
+ ASPECT_TOLERANCE = 0.02;
+ } else {
+ ASPECT_TOLERANCE = 0.01;
+ }
if (sizes == null) {
return -1;
}
@@ -553,7 +560,7 @@
// Cannot find the one match the aspect ratio. This should not happen.
// Ignore the requirement.
if (optimalSizeIndex == -1) {
- Log.w(TAG, "No preview size match the aspect ratio");
+ Log.w(TAG, "No preview size match the aspect ratio. available sizes: " + sizes);
minDiff = Double.MAX_VALUE;
for (int i = 0; i < sizes.size(); i++) {
Size size = sizes.get(i);
@@ -926,7 +933,7 @@
float sigma = len;
float sum = 0;
for (int i = 0; i <= mid; i++) {
- float ex = FloatMath.exp(-(i - mid) * (i - mid) / (mid * mid))
+ float ex = (float) Math.exp(-(i - mid) * (i - mid) / (mid * mid))
/ (2 * sigma * sigma);
int symmetricIndex = len - 1 - i;
mask[i] = ex;
diff --git a/src/com/android/camera/widget/FilmstripView.java b/src/com/android/camera/widget/FilmstripView.java
index 4760fb7..95888fe 100644
--- a/src/com/android/camera/widget/FilmstripView.java
+++ b/src/com/android/camera/widget/FilmstripView.java
@@ -1256,18 +1256,22 @@
// It's in full-screen mode.
fadeAndScaleRightViewItem(itemID);
} else {
- if (curr.getVisibility() == INVISIBLE) {
- curr.setVisibility(VISIBLE);
- }
+ boolean setToVisible = (curr.getVisibility() == INVISIBLE);
+
if (itemID == mCurrentItem + 1) {
curr.setAlpha(1f - scaleFraction);
} else {
if (scaleFraction == 0f) {
curr.setAlpha(1f);
} else {
- curr.setVisibility(INVISIBLE);
+ setToVisible = false;
}
}
+
+ if (setToVisible) {
+ curr.setVisibility(VISIBLE);
+ }
+
curr.setTranslationX(
(mViewItem[mCurrentItem].getLeftPosition() - curr.getLeftPosition()) *
scaleFraction);