am 14b961f6: Reconcile with jb-release
* commit '14b961f6ef4ab2177765c3e64676f0735d934158':
diff --git a/Android.mk b/Android.mk
index ea71b39..b0ebf89 100644
--- a/Android.mk
+++ b/Android.mk
@@ -18,7 +18,7 @@
LOCAL_OVERRIDES_PACKAGES := Gallery Gallery3D GalleryNew3D
-#LOCAL_SDK_VERSION := current
+LOCAL_SDK_VERSION := current
LOCAL_JNI_SHARED_LIBRARIES := libjni_mosaic libjni_eglfence
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 2a69ce1..c7a693b 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -7,7 +7,7 @@
<original-package android:name="com.android.gallery3d" />
- <uses-sdk android:minSdkVersion="14" />
+ <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="16" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
@@ -322,6 +322,7 @@
<data android:scheme="package"/>
</intent-filter>
</receiver>
+ <service android:name="com.android.gallery3d.app.PackagesMonitor$AsyncService"/>
<receiver android:name="com.android.camera.CameraButtonIntentReceiver">
<intent-filter>
<action android:name="android.intent.action.CAMERA_BUTTON"/>
diff --git a/gallerycommon/Android.mk b/gallerycommon/Android.mk
index a942de2..fb81dd9 100644
--- a/gallerycommon/Android.mk
+++ b/gallerycommon/Android.mk
@@ -22,6 +22,6 @@
LOCAL_MODULE := com.android.gallery3d.common2
LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_SDK_VERSION := 8
+LOCAL_SDK_VERSION := current
include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/gallerycommon/src/com/android/gallery3d/common/ApiHelper.java b/gallerycommon/src/com/android/gallery3d/common/ApiHelper.java
new file mode 100644
index 0000000..85b0925
--- /dev/null
+++ b/gallerycommon/src/com/android/gallery3d/common/ApiHelper.java
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ * 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.gallery3d.common;
+
+import android.os.Build;
+import android.provider.MediaStore.MediaColumns;
+import android.view.View;
+
+public class ApiHelper {
+ public static interface VERSION_CODES {
+ // These value are copied from Build.VERSION_CODES
+ public static final int GINGERBREAD_MR1 = 10;
+ public static final int HONEYCOMB = 11;
+ public static final int HONEYCOMB_MR1 = 12;
+ public static final int HONEYCOMB_MR2 = 13;
+ public static final int ICE_CREAM_SANDWICH = 14;
+ public static final int ICE_CREAM_SANDWICH_MR1 = 15;
+ public static final int JELLY_BEAN = 16;
+ }
+
+ public static final boolean HAS_VIEW_SYSTEM_UI_FLAG_LAYOUT_STABLE =
+ hasField(View.class, "SYSTEM_UI_FLAG_LAYOUT_STABLE");
+
+ public static final boolean HAS_VIEW_SYSTEM_UI_FLAG_HIDE_NAVIGATION =
+ hasField(View.class, "SYSTEM_UI_FLAG_HIDE_NAVIGATION");
+
+ public static final boolean HAS_MEDIA_COLUMNS_WIDTH_AND_HEIGHT =
+ hasField(MediaColumns.class, "WIDTH");
+
+ public static final boolean HAS_REUSING_BITMAP_IN_BITMAP_REGION_DECODER =
+ Build.VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN;
+
+ private static boolean hasField(Class<?> klass, String fieldName) {
+ try {
+ klass.getDeclaredField(fieldName);
+ return true;
+ } catch (NoSuchFieldException e) {
+ return false;
+ }
+ }
+}
diff --git a/gallerycommon/src/com/android/gallery3d/common/LongSparseArray.java b/gallerycommon/src/com/android/gallery3d/common/LongSparseArray.java
new file mode 100644
index 0000000..b3298e6
--- /dev/null
+++ b/gallerycommon/src/com/android/gallery3d/common/LongSparseArray.java
@@ -0,0 +1,368 @@
+/*
+ * Copyright (C) 2009 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.gallery3d.common;
+
+
+// Copied from android.util.LongSparseArray for unbundling
+
+/**
+ * SparseArray mapping longs to Objects. Unlike a normal array of Objects,
+ * there can be gaps in the indices. It is intended to be more efficient
+ * than using a HashMap to map Longs to Objects.
+ */
+public class LongSparseArray<E> implements Cloneable {
+ private static final Object DELETED = new Object();
+ private boolean mGarbage = false;
+
+ private long[] mKeys;
+ private Object[] mValues;
+ private int mSize;
+
+ /**
+ * Creates a new LongSparseArray containing no mappings.
+ */
+ public LongSparseArray() {
+ this(10);
+ }
+
+ /**
+ * Creates a new LongSparseArray containing no mappings that will not
+ * require any additional memory allocation to store the specified
+ * number of mappings.
+ */
+ public LongSparseArray(int initialCapacity) {
+ initialCapacity = idealLongArraySize(initialCapacity);
+
+ mKeys = new long[initialCapacity];
+ mValues = new Object[initialCapacity];
+ mSize = 0;
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public LongSparseArray<E> clone() {
+ LongSparseArray<E> clone = null;
+ try {
+ clone = (LongSparseArray<E>) super.clone();
+ clone.mKeys = mKeys.clone();
+ clone.mValues = mValues.clone();
+ } catch (CloneNotSupportedException cnse) {
+ /* ignore */
+ }
+ return clone;
+ }
+
+ /**
+ * Gets the Object mapped from the specified key, or <code>null</code>
+ * if no such mapping has been made.
+ */
+ public E get(long key) {
+ return get(key, null);
+ }
+
+ /**
+ * Gets the Object mapped from the specified key, or the specified Object
+ * if no such mapping has been made.
+ */
+ @SuppressWarnings("unchecked")
+ public E get(long key, E valueIfKeyNotFound) {
+ int i = binarySearch(mKeys, 0, mSize, key);
+
+ if (i < 0 || mValues[i] == DELETED) {
+ return valueIfKeyNotFound;
+ } else {
+ return (E) mValues[i];
+ }
+ }
+
+ /**
+ * Removes the mapping from the specified key, if there was any.
+ */
+ public void delete(long key) {
+ int i = binarySearch(mKeys, 0, mSize, key);
+
+ if (i >= 0) {
+ if (mValues[i] != DELETED) {
+ mValues[i] = DELETED;
+ mGarbage = true;
+ }
+ }
+ }
+
+ /**
+ * Alias for {@link #delete(long)}.
+ */
+ public void remove(long key) {
+ delete(key);
+ }
+
+ /**
+ * Removes the mapping at the specified index.
+ */
+ public void removeAt(int index) {
+ if (mValues[index] != DELETED) {
+ mValues[index] = DELETED;
+ mGarbage = true;
+ }
+ }
+
+ private void gc() {
+ // Log.e("SparseArray", "gc start with " + mSize);
+
+ int n = mSize;
+ int o = 0;
+ long[] keys = mKeys;
+ Object[] values = mValues;
+
+ for (int i = 0; i < n; i++) {
+ Object val = values[i];
+
+ if (val != DELETED) {
+ if (i != o) {
+ keys[o] = keys[i];
+ values[o] = val;
+ values[i] = null;
+ }
+
+ o++;
+ }
+ }
+
+ mGarbage = false;
+ mSize = o;
+
+ // Log.e("SparseArray", "gc end with " + mSize);
+ }
+
+ /**
+ * Adds a mapping from the specified key to the specified value,
+ * replacing the previous mapping from the specified key if there
+ * was one.
+ */
+ public void put(long key, E value) {
+ int i = binarySearch(mKeys, 0, mSize, key);
+
+ if (i >= 0) {
+ mValues[i] = value;
+ } else {
+ i = ~i;
+
+ if (i < mSize && mValues[i] == DELETED) {
+ mKeys[i] = key;
+ mValues[i] = value;
+ return;
+ }
+
+ if (mGarbage && mSize >= mKeys.length) {
+ gc();
+
+ // Search again because indices may have changed.
+ i = ~binarySearch(mKeys, 0, mSize, key);
+ }
+
+ if (mSize >= mKeys.length) {
+ int n = idealLongArraySize(mSize + 1);
+
+ long[] nkeys = new long[n];
+ Object[] nvalues = new Object[n];
+
+ // Log.e("SparseArray", "grow " + mKeys.length + " to " + n);
+ System.arraycopy(mKeys, 0, nkeys, 0, mKeys.length);
+ System.arraycopy(mValues, 0, nvalues, 0, mValues.length);
+
+ mKeys = nkeys;
+ mValues = nvalues;
+ }
+
+ if (mSize - i != 0) {
+ // Log.e("SparseArray", "move " + (mSize - i));
+ System.arraycopy(mKeys, i, mKeys, i + 1, mSize - i);
+ System.arraycopy(mValues, i, mValues, i + 1, mSize - i);
+ }
+
+ mKeys[i] = key;
+ mValues[i] = value;
+ mSize++;
+ }
+ }
+
+ /**
+ * Returns the number of key-value mappings that this LongSparseArray
+ * currently stores.
+ */
+ public int size() {
+ if (mGarbage) {
+ gc();
+ }
+
+ return mSize;
+ }
+
+ /**
+ * Given an index in the range <code>0...size()-1</code>, returns
+ * the key from the <code>index</code>th key-value mapping that this
+ * LongSparseArray stores.
+ */
+ public long keyAt(int index) {
+ if (mGarbage) {
+ gc();
+ }
+
+ return mKeys[index];
+ }
+
+ /**
+ * Given an index in the range <code>0...size()-1</code>, returns
+ * the value from the <code>index</code>th key-value mapping that this
+ * LongSparseArray stores.
+ */
+ @SuppressWarnings("unchecked")
+ public E valueAt(int index) {
+ if (mGarbage) {
+ gc();
+ }
+
+ return (E) mValues[index];
+ }
+
+ /**
+ * Given an index in the range <code>0...size()-1</code>, sets a new
+ * value for the <code>index</code>th key-value mapping that this
+ * LongSparseArray stores.
+ */
+ public void setValueAt(int index, E value) {
+ if (mGarbage) {
+ gc();
+ }
+
+ mValues[index] = value;
+ }
+
+ /**
+ * Returns the index for which {@link #keyAt} would return the
+ * specified key, or a negative number if the specified
+ * key is not mapped.
+ */
+ public int indexOfKey(long key) {
+ if (mGarbage) {
+ gc();
+ }
+
+ return binarySearch(mKeys, 0, mSize, key);
+ }
+
+ /**
+ * Returns an index for which {@link #valueAt} would return the
+ * specified key, or a negative number if no keys map to the
+ * specified value.
+ * Beware that this is a linear search, unlike lookups by key,
+ * and that multiple keys can map to the same value and this will
+ * find only one of them.
+ */
+ public int indexOfValue(E value) {
+ if (mGarbage) {
+ gc();
+ }
+
+ for (int i = 0; i < mSize; i++)
+ if (mValues[i] == value)
+ return i;
+
+ return -1;
+ }
+
+ /**
+ * Removes all key-value mappings from this LongSparseArray.
+ */
+ public void clear() {
+ int n = mSize;
+ Object[] values = mValues;
+
+ for (int i = 0; i < n; i++) {
+ values[i] = null;
+ }
+
+ mSize = 0;
+ mGarbage = false;
+ }
+
+ /**
+ * Puts a key/value pair into the array, optimizing for the case where
+ * the key is greater than all existing keys in the array.
+ */
+ public void append(long key, E value) {
+ if (mSize != 0 && key <= mKeys[mSize - 1]) {
+ put(key, value);
+ return;
+ }
+
+ if (mGarbage && mSize >= mKeys.length) {
+ gc();
+ }
+
+ int pos = mSize;
+ if (pos >= mKeys.length) {
+ int n = idealLongArraySize(pos + 1);
+
+ long[] nkeys = new long[n];
+ Object[] nvalues = new Object[n];
+
+ // Log.e("SparseArray", "grow " + mKeys.length + " to " + n);
+ System.arraycopy(mKeys, 0, nkeys, 0, mKeys.length);
+ System.arraycopy(mValues, 0, nvalues, 0, mValues.length);
+
+ mKeys = nkeys;
+ mValues = nvalues;
+ }
+
+ mKeys[pos] = key;
+ mValues[pos] = value;
+ mSize = pos + 1;
+ }
+
+ private static int binarySearch(long[] a, int start, int len, long key) {
+ int high = start + len, low = start - 1, guess;
+
+ while (high - low > 1) {
+ guess = (high + low) / 2;
+
+ if (a[guess] < key)
+ low = guess;
+ else
+ high = guess;
+ }
+
+ if (high == start + len)
+ return ~(start + len);
+ else if (a[high] == key)
+ return high;
+ else
+ return ~high;
+ }
+
+ private static int idealByteArraySize(int need) {
+ for (int i = 4; i < 32; i++)
+ if (need <= (1 << i) - 12)
+ return (1 << i) - 12;
+
+ return need;
+ }
+
+ public static int idealLongArraySize(int need) {
+ return idealByteArraySize(need * 8) / 8;
+ }
+}
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 899c1e6..0000c61 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -445,4 +445,10 @@
<!-- Web address for gallery help. DO NOT TRANSLATE -->
<string name="help_url_gallery_main" translatable="false"></string>
+
+ <!-- The tilte of a dialog showing there is no external storage. [CHAR LIMIT=20] -->
+ <string name="no_external_storage_title">No Storage</string>
+
+ <!-- The message of a dialog showing there is no external storage. [CHAR LIMIT=none] -->
+ <string name="no_external_storage">No external storage available</string>
</resources>
diff --git a/src/com/android/gallery3d/app/AbstractGalleryActivity.java b/src/com/android/gallery3d/app/AbstractGalleryActivity.java
index 144485d..0987ac3 100644
--- a/src/com/android/gallery3d/app/AbstractGalleryActivity.java
+++ b/src/com/android/gallery3d/app/AbstractGalleryActivity.java
@@ -143,8 +143,8 @@
};
mAlertDialog = new AlertDialog.Builder(this)
.setIconAttribute(android.R.attr.alertDialogIcon)
- .setTitle("No Storage")
- .setMessage("No external storage available.")
+ .setTitle(R.string.no_external_storage_title)
+ .setMessage(R.string.no_external_storage)
.setNegativeButton(android.R.string.cancel, onClick)
.setOnCancelListener(onCancel)
.show();
diff --git a/src/com/android/gallery3d/app/CropImage.java b/src/com/android/gallery3d/app/CropImage.java
index 4f450d8..f264697 100644
--- a/src/com/android/gallery3d/app/CropImage.java
+++ b/src/com/android/gallery3d/app/CropImage.java
@@ -16,6 +16,7 @@
package com.android.gallery3d.app;
+import android.annotation.TargetApi;
import android.app.ActionBar;
import android.app.ProgressDialog;
import android.app.WallpaperManager;
@@ -45,6 +46,7 @@
import android.widget.Toast;
import com.android.gallery3d.R;
+import com.android.gallery3d.common.ApiHelper;
import com.android.gallery3d.common.BitmapUtils;
import com.android.gallery3d.common.Utils;
import com.android.gallery3d.data.DataManager;
@@ -96,10 +98,6 @@
private static final int DEFAULT_COMPRESS_QUALITY = 90;
private static final String TIME_STAMP_NAME = "'IMG'_yyyyMMdd_HHmmss";
- // Change these to Images.Media.WIDTH/HEIGHT after they are unhidden.
- private static final String WIDTH = "width";
- private static final String HEIGHT = "height";
-
public static final String KEY_RETURN_DATA = "return-data";
public static final String KEY_CROPPED_RECT = "cropped-rect";
public static final String KEY_ASPECT_X = "aspectX";
@@ -371,6 +369,15 @@
}
}
+ @TargetApi(ApiHelper.VERSION_CODES.JELLY_BEAN)
+ private static void setImageSize(ContentValues values, int width, int height) {
+ // The two fields are available since ICS but got published in JB
+ if (ApiHelper.HAS_MEDIA_COLUMNS_WIDTH_AND_HEIGHT) {
+ values.put(Images.Media.WIDTH, width);
+ values.put(Images.Media.HEIGHT, height);
+ }
+ }
+
private Uri savePicasaImage(JobContext jc, Bitmap cropped) {
if (!DOWNLOAD_BUCKET.isDirectory() && !DOWNLOAD_BUCKET.mkdirs()) {
throw new RuntimeException("cannot create download folder");
@@ -395,8 +402,7 @@
values.put(Images.Media.ORIENTATION, 0);
values.put(Images.Media.DATA, output.getAbsolutePath());
values.put(Images.Media.SIZE, output.length());
- values.put(WIDTH, cropped.getWidth());
- values.put(HEIGHT, cropped.getHeight());
+ setImageSize(values, cropped.getWidth(), cropped.getHeight());
double latitude = PicasaSource.getLatitude(mMediaItem);
double longitude = PicasaSource.getLongitude(mMediaItem);
@@ -434,8 +440,8 @@
values.put(Images.Media.ORIENTATION, 0);
values.put(Images.Media.DATA, output.getAbsolutePath());
values.put(Images.Media.SIZE, output.length());
- values.put(WIDTH, cropped.getWidth());
- values.put(HEIGHT, cropped.getHeight());
+
+ setImageSize(values, cropped.getWidth(), cropped.getHeight());
if (GalleryUtils.isValidLocation(localImage.latitude, localImage.longitude)) {
values.put(Images.Media.LATITUDE, localImage.latitude);
@@ -467,8 +473,8 @@
values.put(Images.Media.ORIENTATION, 0);
values.put(Images.Media.DATA, output.getAbsolutePath());
values.put(Images.Media.SIZE, output.length());
- values.put(WIDTH, cropped.getWidth());
- values.put(HEIGHT, cropped.getHeight());
+
+ setImageSize(values, cropped.getWidth(), cropped.getHeight());
return getContentResolver().insert(
Images.Media.EXTERNAL_CONTENT_URI, values);
diff --git a/src/com/android/gallery3d/app/MovieActivity.java b/src/com/android/gallery3d/app/MovieActivity.java
index 78fe1ee..5f4db1d 100644
--- a/src/com/android/gallery3d/app/MovieActivity.java
+++ b/src/com/android/gallery3d/app/MovieActivity.java
@@ -16,6 +16,7 @@
package com.android.gallery3d.app;
+import android.annotation.TargetApi;
import android.app.ActionBar;
import android.app.Activity;
import android.content.AsyncQueryHandler;
@@ -27,6 +28,7 @@
import android.graphics.drawable.BitmapDrawable;
import android.media.AudioManager;
import android.net.Uri;
+import android.os.Build;
import android.os.Bundle;
import android.provider.MediaStore;
import android.provider.OpenableColumns;
@@ -39,6 +41,7 @@
import android.widget.ShareActionProvider;
import com.android.gallery3d.R;
+import com.android.gallery3d.common.ApiHelper;
import com.android.gallery3d.common.Utils;
/**
@@ -59,6 +62,15 @@
private Uri mUri;
private boolean mTreatUpAsBack;
+ @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
+ private void setSystemUiVisibility(View rootView) {
+ if (ApiHelper.HAS_VIEW_SYSTEM_UI_FLAG_LAYOUT_STABLE) {
+ rootView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE
+ | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
+ | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
+ }
+ }
+
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -68,9 +80,9 @@
setContentView(R.layout.movie_view);
View rootView = findViewById(R.id.movie_view_root);
- rootView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE
- | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
- | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
+
+ setSystemUiVisibility(rootView);
+
Intent intent = getIntent();
initializeActionBar(intent);
mFinishOnCompletion = intent.getBooleanExtra(
diff --git a/src/com/android/gallery3d/app/MoviePlayer.java b/src/com/android/gallery3d/app/MoviePlayer.java
index 11b40bd..98d7a64 100644
--- a/src/com/android/gallery3d/app/MoviePlayer.java
+++ b/src/com/android/gallery3d/app/MoviePlayer.java
@@ -16,6 +16,7 @@
package com.android.gallery3d.app;
+import android.annotation.TargetApi;
import android.app.AlertDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -37,6 +38,7 @@
import android.widget.VideoView;
import com.android.gallery3d.R;
+import com.android.gallery3d.common.ApiHelper;
import com.android.gallery3d.common.BlobCache;
import com.android.gallery3d.util.CacheManager;
import com.android.gallery3d.util.GalleryUtils;
@@ -98,9 +100,10 @@
};
private final Runnable mRemoveBackground = new Runnable() {
+ @SuppressWarnings("deprecation")
@Override
public void run() {
- mRootView.setBackground(null);
+ mRootView.setBackgroundDrawable(null);
}
};
@@ -148,6 +151,37 @@
}
}, BLACK_TIMEOUT);
+ setOnSystemUiVisibilityChangeListener();
+ // Hide system UI by default
+ showSystemUi(false);
+
+ mAudioBecomingNoisyReceiver = new AudioBecomingNoisyReceiver();
+ mAudioBecomingNoisyReceiver.register();
+
+ Intent i = new Intent(SERVICECMD);
+ i.putExtra(CMDNAME, CMDPAUSE);
+ movieActivity.sendBroadcast(i);
+
+ if (savedInstance != null) { // this is a resumed activity
+ mVideoPosition = savedInstance.getInt(KEY_VIDEO_POSITION, 0);
+ mResumeableTime = savedInstance.getLong(KEY_RESUMEABLE_TIME, Long.MAX_VALUE);
+ mVideoView.start();
+ mVideoView.suspend();
+ mHasPaused = true;
+ } else {
+ final Integer bookmark = mBookmarker.getBookmark(mUri);
+ if (bookmark != null) {
+ showResumeDialog(movieActivity, bookmark);
+ } else {
+ startVideo();
+ }
+ }
+ }
+
+ @TargetApi(ApiHelper.VERSION_CODES.JELLY_BEAN)
+ private void setOnSystemUiVisibilityChangeListener() {
+ if (!ApiHelper.HAS_VIEW_SYSTEM_UI_FLAG_HIDE_NAVIGATION) return;
+
// When the user touches the screen or uses some hard key, the framework
// will change system ui visibility from invisible to visible. We show
// the media control and enable system UI (e.g. ActionBar) to be visible at this point
@@ -176,37 +210,15 @@
}
}
});
-
- // Hide system UI by default
- showSystemUi(false);
-
- mAudioBecomingNoisyReceiver = new AudioBecomingNoisyReceiver();
- mAudioBecomingNoisyReceiver.register();
-
- Intent i = new Intent(SERVICECMD);
- i.putExtra(CMDNAME, CMDPAUSE);
- movieActivity.sendBroadcast(i);
-
- if (savedInstance != null) { // this is a resumed activity
- mVideoPosition = savedInstance.getInt(KEY_VIDEO_POSITION, 0);
- mResumeableTime = savedInstance.getLong(KEY_RESUMEABLE_TIME, Long.MAX_VALUE);
- mVideoView.start();
- mVideoView.suspend();
- mHasPaused = true;
- } else {
- final Integer bookmark = mBookmarker.getBookmark(mUri);
- if (bookmark != null) {
- showResumeDialog(movieActivity, bookmark);
- } else {
- startVideo();
- }
- }
}
+ @TargetApi(ApiHelper.VERSION_CODES.JELLY_BEAN)
private void showSystemUi(boolean visible) {
+ if (!ApiHelper.HAS_VIEW_SYSTEM_UI_FLAG_LAYOUT_STABLE) return;
+
int flag = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
- | View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
+ | View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
if (!visible) {
flag |= View.SYSTEM_UI_FLAG_LOW_PROFILE | View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
@@ -496,7 +508,7 @@
DataInputStream dis = new DataInputStream(
new ByteArrayInputStream(data));
- String uriString = dis.readUTF(dis);
+ String uriString = DataInputStream.readUTF(dis);
int bookmark = dis.readInt();
int duration = dis.readInt();
diff --git a/src/com/android/gallery3d/app/PackagesMonitor.java b/src/com/android/gallery3d/app/PackagesMonitor.java
index e4bb8ee..d8aa8c9 100644
--- a/src/com/android/gallery3d/app/PackagesMonitor.java
+++ b/src/com/android/gallery3d/app/PackagesMonitor.java
@@ -16,6 +16,7 @@
package com.android.gallery3d.app;
+import android.app.IntentService;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -34,23 +35,23 @@
@Override
public void onReceive(final Context context, final Intent intent) {
- final PendingResult result = goAsync();
- new Thread("GalleryPackagesMonitorAsync") {
- @Override
- public void run() {
- try {
- onReceiveAsync(context, intent);
- } catch (Throwable t) {
- Log.e("PackagesMonitor", "onReceiveAsync", t);
- } finally {
- result.finish();
- }
- }
- }.start();
+ intent.setClass(context, AsyncService.class);
+ context.startService(intent);
+ }
+
+ public static class AsyncService extends IntentService {
+ public AsyncService() {
+ super("GalleryPackagesMonitorAsync");
+ }
+
+ @Override
+ protected void onHandleIntent(Intent intent) {
+ onReceiveAsync(this, intent);
+ }
}
// Runs in a background thread.
- private void onReceiveAsync(Context context, Intent intent) {
+ private static void onReceiveAsync(Context context, Intent intent) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
int version = prefs.getInt(KEY_PACKAGES_VERSION, 1);
diff --git a/src/com/android/gallery3d/app/Wallpaper.java b/src/com/android/gallery3d/app/Wallpaper.java
index c08c1d7..1ece66c 100644
--- a/src/com/android/gallery3d/app/Wallpaper.java
+++ b/src/com/android/gallery3d/app/Wallpaper.java
@@ -16,11 +16,16 @@
package com.android.gallery3d.app;
+import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Point;
import android.net.Uri;
+import android.os.Build;
import android.os.Bundle;
+import android.view.Display;
+
+import com.android.gallery3d.common.ApiHelper;
/**
* Wallpaper picker for the gallery application. This just redirects to the
@@ -57,6 +62,18 @@
}
}
+ @SuppressWarnings("deprecation")
+ @TargetApi(ApiHelper.VERSION_CODES.HONEYCOMB_MR2)
+ private Point getDefaultDisplaySize(Point size) {
+ Display d = getWindowManager().getDefaultDisplay();
+ if (Build.VERSION.SDK_INT >= ApiHelper.VERSION_CODES.HONEYCOMB_MR2) {
+ d.getSize(size);
+ } else {
+ size.set(d.getWidth(), d.getHeight());
+ }
+ return size;
+ }
+
@SuppressWarnings("fallthrough")
@Override
protected void onResume() {
@@ -78,8 +95,7 @@
case STATE_PHOTO_PICKED: {
int width = getWallpaperDesiredMinimumWidth();
int height = getWallpaperDesiredMinimumHeight();
- Point size = new Point();
- getWindowManager().getDefaultDisplay().getSize(size);
+ Point size = getDefaultDisplaySize(new Point());
float spotlightX = (float) size.x / width;
float spotlightY = (float) size.y / height;
Intent request = new Intent(CropImage.ACTION_CROP)
diff --git a/src/com/android/gallery3d/data/LocalImage.java b/src/com/android/gallery3d/data/LocalImage.java
index c3095a0..316e324 100644
--- a/src/com/android/gallery3d/data/LocalImage.java
+++ b/src/com/android/gallery3d/data/LocalImage.java
@@ -16,6 +16,7 @@
package com.android.gallery3d.data;
+import android.annotation.TargetApi;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.database.Cursor;
@@ -26,9 +27,11 @@
import android.net.Uri;
import android.provider.MediaStore.Images;
import android.provider.MediaStore.Images.ImageColumns;
+import android.provider.MediaStore.MediaColumns;
import android.util.Log;
import com.android.gallery3d.app.GalleryApp;
+import com.android.gallery3d.common.ApiHelper;
import com.android.gallery3d.common.BitmapUtils;
import com.android.gallery3d.util.GalleryUtils;
import com.android.gallery3d.util.ThreadPool.Job;
@@ -74,10 +77,22 @@
ImageColumns.ORIENTATION, // 9
ImageColumns.BUCKET_ID, // 10
ImageColumns.SIZE, // 11
- ImageColumns.WIDTH, // 12
- ImageColumns.HEIGHT // 13
+ "0", // 12
+ "0" // 13
};
+ static {
+ updateWidthAndHeightProjection();
+ }
+
+ @TargetApi(ApiHelper.VERSION_CODES.JELLY_BEAN)
+ private static void updateWidthAndHeightProjection() {
+ if (ApiHelper.HAS_MEDIA_COLUMNS_WIDTH_AND_HEIGHT) {
+ PROJECTION[INDEX_WIDTH] = MediaColumns.WIDTH;
+ PROJECTION[INDEX_HEIGHT] = MediaColumns.HEIGHT;
+ }
+ }
+
private final GalleryApp mApplication;
public int rotation;
diff --git a/src/com/android/gallery3d/gadget/PhotoAppWidgetProvider.java b/src/com/android/gallery3d/gadget/PhotoAppWidgetProvider.java
index 2b36f6b..9813902 100644
--- a/src/com/android/gallery3d/gadget/PhotoAppWidgetProvider.java
+++ b/src/com/android/gallery3d/gadget/PhotoAppWidgetProvider.java
@@ -70,6 +70,7 @@
super.onUpdate(context, appWidgetManager, appWidgetIds);
}
+ @SuppressWarnings("deprecation")
private static RemoteViews buildStackWidget(Context context, int widgetId, Entry entry) {
RemoteViews views = new RemoteViews(
context.getPackageName(), R.layout.appwidget_main);
@@ -80,7 +81,10 @@
intent.putExtra(WidgetService.EXTRA_ALBUM_PATH, entry.albumPath);
intent.setData(Uri.parse("widget://gallery/" + widgetId));
- views.setRemoteAdapter(R.id.appwidget_stack_view, intent);
+ // We use the deprecated API for backward compatibility
+ // The new API is available in ICE_CREAM_SANDWICH (15)
+ views.setRemoteAdapter(widgetId, R.id.appwidget_stack_view, intent);
+
views.setEmptyView(R.id.appwidget_stack_view, R.id.appwidget_empty_view);
Intent clickIntent = new Intent(context, WidgetClickHandler.class);
diff --git a/src/com/android/gallery3d/ui/GLRootView.java b/src/com/android/gallery3d/ui/GLRootView.java
index 99ed8cb..478cb4f 100644
--- a/src/com/android/gallery3d/ui/GLRootView.java
+++ b/src/com/android/gallery3d/ui/GLRootView.java
@@ -16,6 +16,7 @@
package com.android.gallery3d.ui;
+import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Matrix;
import android.graphics.PixelFormat;
@@ -29,6 +30,7 @@
import com.android.gallery3d.R;
import com.android.gallery3d.anim.CanvasAnimation;
+import com.android.gallery3d.common.ApiHelper;
import com.android.gallery3d.common.Utils;
import com.android.gallery3d.util.GalleryUtils;
import com.android.gallery3d.util.Profile;
@@ -536,12 +538,15 @@
}
@Override
+ @TargetApi(ApiHelper.VERSION_CODES.JELLY_BEAN)
public void setLightsOutMode(boolean enabled) {
- int flags = enabled
- ? SYSTEM_UI_FLAG_LOW_PROFILE
- | SYSTEM_UI_FLAG_FULLSCREEN
- | SYSTEM_UI_FLAG_LAYOUT_STABLE
- : 0;
+ int flags = 0;
+ if (enabled) {
+ flags = SYSTEM_UI_FLAG_LOW_PROFILE;
+ if (ApiHelper.HAS_VIEW_SYSTEM_UI_FLAG_LAYOUT_STABLE) {
+ flags |= (SYSTEM_UI_FLAG_FULLSCREEN | SYSTEM_UI_FLAG_LAYOUT_STABLE);
+ }
+ }
setSystemUiVisibility(flags);
}
diff --git a/src/com/android/gallery3d/ui/PositionController.java b/src/com/android/gallery3d/ui/PositionController.java
index d556caf..6d33470 100644
--- a/src/com/android/gallery3d/ui/PositionController.java
+++ b/src/com/android/gallery3d/ui/PositionController.java
@@ -110,11 +110,11 @@
private Listener mListener;
private volatile Rect mOpenAnimationRect;
- // Use a large enough value, so we won't see the gray shadown in the beginning.
+ // Use a large enough value, so we won't see the gray shadow in the beginning.
private int mViewW = 1200;
private int mViewH = 1200;
- // A scaling guesture is in progress.
+ // A scaling gesture is in progress.
private boolean mInScale;
// The focus point of the scaling gesture, relative to the center of the
// picture in bitmap pixels.
@@ -178,7 +178,7 @@
private RangeArray<Gap> mTempGaps =
new RangeArray<Gap>(-BOX_MAX, BOX_MAX - 1);
- // The output of the PositionController. Available throught getPosition().
+ // The output of the PositionController. Available through getPosition().
private RangeArray<Rect> mRects = new RangeArray<Rect>(-BOX_MAX, BOX_MAX);
// The direction of a new picture should appear. New pictures pop from top
@@ -211,7 +211,7 @@
mListener = listener;
mPageScroller = new FlingScroller();
mFilmScroller = new OverScroller(context,
- null /* default interpolator */, false /* no flywheel */);
+ null /* default interpolator */, 0, 0, false /* no flywheel */);
// Initialize the areas.
initPlatform();
@@ -519,7 +519,7 @@
Platform p = mPlatform;
// We want to keep the focus point (on the bitmap) the same as when we
- // begin the scale guesture, that is,
+ // begin the scale gesture, that is,
//
// (focusX' - currentX') / scale' = (focusX - currentX) / scale
//
@@ -1005,7 +1005,7 @@
// N N N N N N N -- all new boxes
// -3 -2 -1 0 1 2 3 -- nothing changed
// -2 -1 0 1 2 3 N -- focus goes to the next box
- // N -3 -2 -1 0 1 2 -- focuse goes to the previous box
+ // N -3 -2 -1 0 1 2 -- focus goes to the previous box
// -3 -2 -1 1 2 3 N -- the focused box was deleted.
//
// hasPrev/hasNext indicates if there are previous/next boxes for the
@@ -1019,7 +1019,7 @@
RangeIntArray from = new RangeIntArray(fromIndex, -BOX_MAX, BOX_MAX);
- // 1. Get the absolute X coordiates for the boxes.
+ // 1. Get the absolute X coordinates for the boxes.
layoutAndSetPosition();
for (int i = -BOX_MAX; i <= BOX_MAX; i++) {
Box b = mBoxes.get(i);
@@ -1366,7 +1366,7 @@
public int mAnimationKind;
public int mAnimationDuration;
- // This should be overidden in subclass to change the animation values
+ // This should be overridden in subclass to change the animation values
// give the progress value in [0, 1].
protected abstract boolean interpolate(float progress);
public abstract boolean startSnapback();
diff --git a/src/com/android/gallery3d/ui/TileImageView.java b/src/com/android/gallery3d/ui/TileImageView.java
index 0c6086d..fc61efd 100644
--- a/src/com/android/gallery3d/ui/TileImageView.java
+++ b/src/com/android/gallery3d/ui/TileImageView.java
@@ -21,9 +21,10 @@
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.FloatMath;
-import android.util.LongSparseArray;
import com.android.gallery3d.app.GalleryContext;
+import com.android.gallery3d.common.ApiHelper;
+import com.android.gallery3d.common.LongSparseArray;
import com.android.gallery3d.common.Utils;
import com.android.gallery3d.data.BitmapPool;
import com.android.gallery3d.data.DecodeUtils;
@@ -48,7 +49,9 @@
private static final int UPLOAD_LIMIT = 1;
private static final BitmapPool sTilePool =
- new BitmapPool(BITMAP_SIZE, BITMAP_SIZE, 128);
+ ApiHelper.HAS_REUSING_BITMAP_IN_BITMAP_REGION_DECODER
+ ? new BitmapPool(BITMAP_SIZE, BITMAP_SIZE, 128)
+ : null;
/*
* This is the tile state in the CPU side.
@@ -378,7 +381,7 @@
}
}
setScreenNail(null);
- sTilePool.clear();
+ if (sTilePool != null) sTilePool.clear();
}
public void prepareTextures() {
@@ -487,7 +490,7 @@
if (tile.mTileState == STATE_RECYCLING) {
tile.mTileState = STATE_RECYCLED;
if (tile.mDecodedTile != null) {
- sTilePool.recycle(tile.mDecodedTile);
+ if (sTilePool != null) sTilePool.recycle(tile.mDecodedTile);
tile.mDecodedTile = null;
}
mRecycledQueue.push(tile);
@@ -515,7 +518,7 @@
}
tile.mTileState = STATE_RECYCLED;
if (tile.mDecodedTile != null) {
- sTilePool.recycle(tile.mDecodedTile);
+ if (sTilePool != null) sTilePool.recycle(tile.mDecodedTile);
tile.mDecodedTile = null;
}
mRecycledQueue.push(tile);
@@ -653,7 +656,7 @@
@Override
protected void onFreeBitmap(Bitmap bitmap) {
- sTilePool.recycle(bitmap);
+ if (sTilePool != null) sTilePool.recycle(bitmap);
}
boolean decode() {
diff --git a/src/com/android/gallery3d/ui/TileImageViewAdapter.java b/src/com/android/gallery3d/ui/TileImageViewAdapter.java
index 0b4ac03..4865e5c 100644
--- a/src/com/android/gallery3d/ui/TileImageViewAdapter.java
+++ b/src/com/android/gallery3d/ui/TileImageViewAdapter.java
@@ -20,8 +20,10 @@
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.BitmapRegionDecoder;
+import android.graphics.Canvas;
import android.graphics.Rect;
+import com.android.gallery3d.common.ApiHelper;
import com.android.gallery3d.common.Utils;
import com.android.gallery3d.data.BitmapPool;
@@ -108,6 +110,11 @@
@Override
public Bitmap getTile(int level, int x, int y, int tileSize,
int borderSize, BitmapPool pool) {
+
+ if (!ApiHelper.HAS_REUSING_BITMAP_IN_BITMAP_REGION_DECODER) {
+ return getTileWithoutReusingBitmap(level, x, y, tileSize, borderSize);
+ }
+
int b = borderSize << level;
int t = tileSize << level;
@@ -158,6 +165,49 @@
return bitmap;
}
+ private Bitmap getTileWithoutReusingBitmap(
+ int level, int x, int y, int tileSize, int borderSize) {
+ int b = borderSize << level;
+ int t = tileSize << level;
+ Rect wantRegion = new Rect(x - b, y - b, x + t + b, y + t + b);
+
+ BitmapRegionDecoder regionDecoder;
+ Rect overlapRegion;
+
+ synchronized (this) {
+ regionDecoder = mRegionDecoder;
+ if (regionDecoder == null) return null;
+ overlapRegion = new Rect(0, 0, mImageWidth, mImageHeight);
+ Utils.assertTrue(overlapRegion.intersect(wantRegion));
+ }
+
+ BitmapFactory.Options options = new BitmapFactory.Options();
+ options.inPreferredConfig = Config.ARGB_8888;
+ options.inPreferQualityOverSpeed = true;
+ options.inSampleSize = (1 << level);
+ Bitmap bitmap = null;
+
+ // In CropImage, we may call the decodeRegion() concurrently.
+ synchronized (regionDecoder) {
+ bitmap = regionDecoder.decodeRegion(overlapRegion, options);
+ }
+
+ if (bitmap == null) {
+ Log.w(TAG, "fail in decoding region");
+ }
+
+ if (wantRegion.equals(overlapRegion)) return bitmap;
+
+ int s = tileSize + 2 * borderSize;
+ Bitmap result = Bitmap.createBitmap(s, s, Config.ARGB_8888);
+ Canvas canvas = new Canvas(result);
+ canvas.drawBitmap(bitmap,
+ (overlapRegion.left - wantRegion.left) >> level,
+ (overlapRegion.top - wantRegion.top) >> level, null);
+ return result;
+ }
+
+
@Override
public ScreenNail getScreenNail() {
return mScreenNail;
diff --git a/src/com/android/gallery3d/util/GalleryUtils.java b/src/com/android/gallery3d/util/GalleryUtils.java
index 1d70914..1291ee9 100644
--- a/src/com/android/gallery3d/util/GalleryUtils.java
+++ b/src/com/android/gallery3d/util/GalleryUtils.java
@@ -16,7 +16,6 @@
package com.android.gallery3d.util;
-import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.Context;
@@ -24,7 +23,6 @@
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
-import android.content.res.Resources;
import android.net.Uri;
import android.os.ConditionVariable;
import android.os.Environment;