Merge "Doc change: Google Play services 4.0 reference docs." into klp-dev
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index bd52f49..6ddd3fe 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1153,7 +1153,7 @@
href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
targetSdkVersion}</a> is 4 or higher.-->
<permission android:name="android.permission.READ_EXTERNAL_STORAGE"
- android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
+ android:permissionGroup="android.permission-group.STORAGE"
android:label="@string/permlab_sdcardRead"
android:description="@string/permdesc_sdcardRead"
android:protectionLevel="normal" />
diff --git a/docs/html/guide/topics/manifest/uses-sdk-element.jd b/docs/html/guide/topics/manifest/uses-sdk-element.jd
index 07b08f6..9169658 100644
--- a/docs/html/guide/topics/manifest/uses-sdk-element.jd
+++ b/docs/html/guide/topics/manifest/uses-sdk-element.jd
@@ -227,6 +227,12 @@
<table>
<tr><th>Platform Version</th><th>API Level</th><th>VERSION_CODE</th><th>Notes</th></tr>
+ <tr><td><a href="{@docRoot}about/versions/android-4.4.html">Android 4.4</a></td>
+ <td><a href="{@docRoot}sdk/api_diff/19/changes.html" title="Diff Report">19</a></td>
+ <td>{@link android.os.Build.VERSION_CODES#KITKAT}</td>
+ <td><a href="{@docRoot}about/versions/kitkat.html">Platform
+Highlights</a></td></tr>
+
<tr><td><a href="{@docRoot}about/versions/android-4.3.html">Android 4.3</a></td>
<td><a href="{@docRoot}sdk/api_diff/18/changes.html" title="Diff Report">18</a></td>
<td>{@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2}</td>
diff --git a/docs/html/sdk/index.jd b/docs/html/sdk/index.jd
index eb2d6a7..71212ec 100644
--- a/docs/html/sdk/index.jd
+++ b/docs/html/sdk/index.jd
@@ -5,43 +5,43 @@
page.metaDescription=Download the official Android SDK to develop apps for Android-powered devices.
-sdk.linux32_bundle_download=adt-bundle-linux-x86-20130917.zip
-sdk.linux32_bundle_bytes=474924071
-sdk.linux32_bundle_checksum=912b2dac6e0a4fa4ae1417271bf42863
+sdk.linux32_bundle_download=adt-bundle-linux-x86-20131028.zip
+sdk.linux32_bundle_bytes=496856894
+sdk.linux32_bundle_checksum=dfc1b314a07b5260941360d3e7542493
-sdk.linux64_bundle_download=adt-bundle-linux-x86_64-20130917.zip
-sdk.linux64_bundle_bytes=475215747
-sdk.linux64_bundle_checksum=2f7523d4eba9a8302c3c4a3955785e18
+sdk.linux64_bundle_download=adt-bundle-linux-x86_64-20131028.zip
+sdk.linux64_bundle_bytes=497152039
+sdk.linux64_bundle_checksum=c5db52afa4d7d3b6b78793ccc98b036f
-sdk.mac64_bundle_download=adt-bundle-mac-x86_64-20130917.zip
-sdk.mac64_bundle_bytes=448581372
-sdk.mac64_bundle_checksum=4e2d599486ecc935d24eeef5eb641364
+sdk.mac64_bundle_download=adt-bundle-mac-x86_64-20131028.zip
+sdk.mac64_bundle_bytes=470367339
+sdk.mac64_bundle_checksum=446f013ab88ff873985369e5405fda70
-sdk.win32_bundle_download=adt-bundle-windows-x86-20130917.zip
-sdk.win32_bundle_bytes=481803289
-sdk.win32_bundle_checksum=5d6c79a47c8b47170cff3d231dcf7ad3
+sdk.win32_bundle_download=adt-bundle-windows-x86-20131028.zip
+sdk.win32_bundle_bytes=503579820
+sdk.win32_bundle_checksum=8cfb299b548c1017dbe66259e136d1e7
-sdk.win64_bundle_download=adt-bundle-windows-x86_64-20130917.zip
-sdk.win64_bundle_bytes=481934982
-sdk.win64_bundle_checksum=918f80aad61ec21509d86a2fbd87fd44
+sdk.win64_bundle_download=adt-bundle-windows-x86_64-20131028.zip
+sdk.win64_bundle_bytes=503715722
+sdk.win64_bundle_checksum=fc2c638d32293df8874dbcff3ab06e63
-sdk.linux_download=android-sdk_r22.2.1-linux.tgz
-sdk.linux_bytes=100918342
-sdk.linux_checksum=05911d3052a1cbf678561104d35a1bc0
+sdk.linux_download=android-sdk_r22.3-linux.tgz
+sdk.linux_bytes=100968558
+sdk.linux_checksum=6ae581a906d6420ad67176dff25a31cc
-sdk.mac_download=android-sdk_r22.2.1-macosx.zip
-sdk.mac_bytes=74859877
-sdk.mac_checksum=727a51affa2af733eca1aa307c73c3bd
+sdk.mac_download=android-sdk_r22.3-macosx.zip
+sdk.mac_bytes=74893875
+sdk.mac_checksum=ecde88ca1f05955826697848fcb4a9e7
-sdk.win_download=android-sdk_r22.2.1-windows.zip
-sdk.win_bytes=108797377
-sdk.win_checksum=bea5d28cfb6c073b32643dd3ed0bc1e0
+sdk.win_download=android-sdk_r22.3-windows.zip
+sdk.win_bytes=108847452
+sdk.win_checksum=9f0fe8c8884d6aee2b298fee203c62dc
-sdk.win_installer=installer_r22.2.1-windows.exe
-sdk.win_installer_bytes=88795776
-sdk.win_installer_checksum=07e6e47de6c4549bea6986453119b37c
+sdk.win_installer=installer_r22.3-windows.exe
+sdk.win_installer_bytes=88845794
+sdk.win_installer_checksum=ad50c4dd9e23cee65a1ed740ff3345fa
diff --git a/docs/html/sdk/installing/installing-adt.jd b/docs/html/sdk/installing/installing-adt.jd
index 66b1c43..88fd7df 100644
--- a/docs/html/sdk/installing/installing-adt.jd
+++ b/docs/html/sdk/installing/installing-adt.jd
@@ -1,8 +1,8 @@
page.title=Installing the Eclipse Plugin
-adt.zip.version=22.2.1
-adt.zip.download=ADT-22.2.1.zip
-adt.zip.bytes=14476845
-adt.zip.checksum=97176754a1e86adf2e5e05f44dc7229e
+adt.zip.version=22.3.0
+adt.zip.download=ADT-22.3.0.zip
+adt.zip.bytes=14493723
+adt.zip.checksum=0189080b23dfa0f866adafaaafcc34ab
@jd:body
diff --git a/docs/html/tools/revisions/platforms.jd b/docs/html/tools/revisions/platforms.jd
index 02216de..f219784 100644
--- a/docs/html/tools/revisions/platforms.jd
+++ b/docs/html/tools/revisions/platforms.jd
@@ -50,13 +50,54 @@
-<h2 id="4.3">Android 4.3</h2>
+<h2 id="4.4">Android 4.4</h2>
<div class="toggle-content opened">
<p><a href="#" onclick="return toggleContent(this)">
<img src="{@docRoot}assets/images/triangle-opened.png"
+class="toggle-content-img" alt="" />Revision 1</a> <em>(October 2013)</em>
+ </p>
+
+ <div class="toggle-content-toggleme">
+
+ <p>Initial release. The system version is 4.4.</p>
+ <dl>
+ <dt>Dependencies:</dt>
+ <dd>Android SDK Platform-tools r19 or higher is required.</dd>
+ <dd>Android SDK Tools 22.3 or higher is recommended.</dd>
+ </dl>
+
+ </div>
+</div>
+
+<h3 id="gsi-4.4">Google APIs System Image</h3>
+
+<div class="toggle-content opened">
+ <p><a href="#" onclick="return toggleContent(this)">
+ <img src="{@docRoot}assets/images/triangle-opened.png"
+class="toggle-content-img" alt="" />Revision 1</a> <em>(October 2013)</em>
+ </p>
+
+ <div class="toggle-content-toggleme">
+
+ <p>Initial release. This release includes
+ <a href="{@docRoot}google/play-services/index.html">Google Play services</a> version 4.0.30,
+ allowing you to test your application in an emulator using the latest Google Play services.</p>
+
+ </div>
+</div>
+
+
+
+<h2 id="4.3">Android 4.3</h2>
+
+
+<div class="toggle-content closed">
+
+ <p><a href="#" onclick="return toggleContent(this)">
+ <img src="{@docRoot}assets/images/triangle-closed.png"
class="toggle-content-img" alt="" />Revision 2</a> <em>(August 2013)</em>
</p>
@@ -91,11 +132,11 @@
</div>
</div>
-<h3 id="">Google APIs System Image</h3>
+<h3 id="gsi-4.3">Google APIs System Image</h3>
-<div class="toggle-content opened">
+<div class="toggle-content closed">
<p><a href="#" onclick="return toggleContent(this)">
- <img src="{@docRoot}assets/images/triangle-opened.png"
+ <img src="{@docRoot}assets/images/triangle-closed.png"
class="toggle-content-img" alt="" />Revision 3</a> <em>(September 2013)</em>
</p>
diff --git a/docs/html/tools/sdk/eclipse-adt.jd b/docs/html/tools/sdk/eclipse-adt.jd
index cfdf8cc..c584ae5 100644
--- a/docs/html/tools/sdk/eclipse-adt.jd
+++ b/docs/html/tools/sdk/eclipse-adt.jd
@@ -57,6 +57,43 @@
<div class="toggle-content opened">
<p><a href="#" onclick="return toggleContent(this)">
<img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-content-img"
+ alt=""/>ADT 22.3.0</a> <em>(October 2013)</em>
+ </p>
+
+ <div class="toggle-content-toggleme">
+<dl>
+ <dt>Dependencies:</dt>
+
+ <dd>
+ <ul>
+ <li>Java 1.6 or higher is required.</li>
+ <li>Eclipse Helios (Version 3.6.2) or higher is required.</li>
+ <li>This version of ADT is designed for use with
+ <a href="{@docRoot}tools/sdk/tools-notes.html">SDK Tools r22.3</a>.
+ If you haven't already installed SDK Tools r22.3 into your SDK, use the
+ Android SDK Manager to do so.</li>
+ </ul>
+ </dd>
+
+ <dt>General Notes:</dt>
+ <dd>
+ <ul>
+ <li>Added support for Android 4.4 (API level 19).</li>
+ <li>Fixed problem with parsing view hierarchies containing classes in the java.*
+ name space.</li>
+ <li>Fixed problem importing Android projects that have the same name as an existing
+ project.</li>
+ </ul>
+ </dd>
+
+</dl>
+</div>
+</div>
+
+
+<div class="toggle-content closed">
+ <p><a href="#" onclick="return toggleContent(this)">
+ <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-content-img"
alt=""/>ADT 22.2.1</a> <em>(September 2013)</em>
</p>
diff --git a/docs/html/tools/sdk/tools-notes.jd b/docs/html/tools/sdk/tools-notes.jd
index 25c409e..c28b946 100644
--- a/docs/html/tools/sdk/tools-notes.jd
+++ b/docs/html/tools/sdk/tools-notes.jd
@@ -30,6 +30,38 @@
<div class="toggle-content opened">
<p><a href="#" onclick="return toggleContent(this)">
<img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-content-img"
+ alt=""/>SDK Tools, Revision 22.3</a> <em>(October 2013)</em>
+ </p>
+
+ <div class="toggle-content-toggleme">
+
+ <dl>
+ <dt>Dependencies:</dt>
+ <dd>
+ <ul>
+ <li>Android SDK Platform-tools revision 18 or later.</li>
+ <li>If you are developing in Eclipse with ADT, note that this version of SDK Tools is
+ designed for use with ADT 22.3.0 and later. If you haven't already, update your
+ <a href="{@docRoot}tools/sdk/eclipse-adt.html">ADT Plugin</a> to 22.3.0.</li>
+ <li>If you are developing outside Eclipse, you must have
+ <a href="http://ant.apache.org/">Apache Ant</a> 1.8 or later.</li>
+ </ul>
+ </dd>
+
+ <dt>General Notes:</dt>
+ <dd>
+ <ul>
+ <li>Added support for Android 4.4 (API level 19).</li>
+ <li>Fixed a number of minor bugs in the SDK and build system.</li>
+ </ul>
+ </dd>
+ </dl>
+ </div>
+</div>
+
+<div class="toggle-content closed">
+ <p><a href="#" onclick="return toggleContent(this)">
+ <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-content-img"
alt=""/>SDK Tools, Revision 22.2.1</a> <em>(September 2013)</em>
</p>
diff --git a/docs/html/tools/support-library/index.jd b/docs/html/tools/support-library/index.jd
index 4ee8c12..dba4e74 100644
--- a/docs/html/tools/support-library/index.jd
+++ b/docs/html/tools/support-library/index.jd
@@ -62,6 +62,58 @@
<div class="toggle-content opened">
<p><a href="#" onclick="return toggleContent(this)">
<img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-content-img" alt=""
+/>Android Support Library, revision 19</a> <em>(October 2013)</em>
+ </p>
+ <div class="toggle-content-toggleme">
+ <dl>
+ <dt>Changes for v4 support library:</dt>
+ <dd>
+ <ul>
+ <li>Added support for external Storage APIs with the
+ {@link android.support.v4.content.ContextCompat#getObbDirs getObbDirs()},
+ {@link android.support.v4.content.ContextCompat#getExternalFilesDirs getExternalFilesDirs()},
+ {@link android.support.v4.content.ContextCompat#getExternalCacheDirs getExternalCacheDirs()},
+ and {@link android.support.v4.os.EnvironmentCompat#getStorageState getStorageState()}.
+ These helper methods always return a single file object on devices running Android
+ 4.3 (API level 18) and earlier. When running on Android 4.4 (API level 19) and higher,
+ these methods may return more than one file object.</li>
+ <li>Added {@link android.support.v4.print.PrintHelper} class that works with the
+ Print APIs to print images with a minimum of code.</li>
+ <li>Added drag-to-open user interface support for pop-up menus. For more information, see
+ {@link android.support.v4.widget.PopupMenuCompat} and
+ {@link android.support.v4.widget.ListPopupWindowCompat}.</li>
+ <li>Improved accessibility support with the addition of a
+ {@link android.support.v4.view.accessibility.AccessibilityNodeProviderCompat#findFocus
+ findFocus()} method in
+ {@link android.support.v4.view.accessibility.AccessibilityNodeProviderCompat} and the
+ {@link android.support.v4.view.accessibility.AccessibilityNodeInfoCompat#getLiveRegion
+ getLiveRegion()} method in
+ {@link android.support.v4.view.accessibility.AccessibilityNodeInfoCompat}.</li>
+ <li>Added helper class {@link android.support.v4.view.ScaleGestureDetectorCompat} for
+ accessing new scaling gesture methods.</li>
+ <li>Fixed problem with {@link android.support.v4.app.ActionBarDrawerToggle} in
+ right-to-left language displays.</li>
+ <li>Modified {@link android.support.v4.widget.AutoScrollHelper} option to consume
+ touch events or allow them to be passed through to other views.</li>
+ </ul>
+ </dd>
+
+ <dt>Changes for v7 mediarouter library:</dt>
+ <dd>
+ <ul>
+ <li>Added support for media playback queuing, setting HTTP header values and media
+ playback duration.</li>
+ <li>Added explicit start, get, and end session actions for explicitly managing media
+ playback sessions with media router.</li>
+ </ul>
+ </dd>
+ </dl>
+ </div>
+</div>
+
+<div class="toggle-content closed">
+ <p><a href="#" onclick="return toggleContent(this)">
+ <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-content-img" alt=""
/>Android Support Library, revision 18</a> <em>(July 2013)</em>
</p>
<div class="toggle-content-toggleme">
diff --git a/packages/WallpaperCropper/res/values/strings.xml b/packages/WallpaperCropper/res/values/strings.xml
index 2b8111d..091869a 100644
--- a/packages/WallpaperCropper/res/values/strings.xml
+++ b/packages/WallpaperCropper/res/values/strings.xml
@@ -17,4 +17,9 @@
<string name="crop_wallpaper">Crop wallpaper</string>
<!-- Button label on Wallpaper picker screen; user selects this button to set a specific wallpaper -->
<string name="wallpaper_instructions">Set wallpaper</string>
+ <!-- Error message when an image is selected as a wallpaper,
+ but the wallpaper cropper cannot load it. The user will
+ usually see this when using another app and trying to set
+ an image as the wallpaper -->
+ <string name="wallpaper_load_fail">Couldn\'t load image as wallpaper</string>
</resources>
diff --git a/packages/WallpaperCropper/src/com/android/photos/BitmapRegionTileSource.java b/packages/WallpaperCropper/src/com/android/photos/BitmapRegionTileSource.java
index b5774f4..e14f89a 100644
--- a/packages/WallpaperCropper/src/com/android/photos/BitmapRegionTileSource.java
+++ b/packages/WallpaperCropper/src/com/android/photos/BitmapRegionTileSource.java
@@ -31,6 +31,7 @@
import android.util.Log;
import com.android.gallery3d.common.BitmapUtils;
+import com.android.gallery3d.common.Utils;
import com.android.gallery3d.exif.ExifInterface;
import com.android.gallery3d.glrenderer.BasicTexture;
import com.android.gallery3d.glrenderer.BitmapTexture;
@@ -41,6 +42,85 @@
import java.io.IOException;
import java.io.InputStream;
+interface SimpleBitmapRegionDecoder {
+ int getWidth();
+ int getHeight();
+ Bitmap decodeRegion(Rect wantRegion, BitmapFactory.Options options);
+}
+
+class SimpleBitmapRegionDecoderWrapper implements SimpleBitmapRegionDecoder {
+ BitmapRegionDecoder mDecoder;
+ private SimpleBitmapRegionDecoderWrapper(BitmapRegionDecoder decoder) {
+ mDecoder = decoder;
+ }
+ public static SimpleBitmapRegionDecoderWrapper newInstance(String pathName, boolean isShareable) {
+ try {
+ BitmapRegionDecoder d = BitmapRegionDecoder.newInstance(pathName, isShareable);
+ if (d != null) {
+ return new SimpleBitmapRegionDecoderWrapper(d);
+ }
+ } catch (IOException e) {
+ Log.w("BitmapRegionTileSource", "getting decoder failed for path " + pathName, e);
+ return null;
+ }
+ return null;
+ }
+ public static SimpleBitmapRegionDecoderWrapper newInstance(InputStream is, boolean isShareable) {
+ try {
+ BitmapRegionDecoder d = BitmapRegionDecoder.newInstance(is, isShareable);
+ if (d != null) {
+ return new SimpleBitmapRegionDecoderWrapper(d);
+ }
+ } catch (IOException e) {
+ Log.w("BitmapRegionTileSource", "getting decoder failed", e);
+ return null;
+ }
+ return null;
+ }
+ public int getWidth() {
+ return mDecoder.getWidth();
+ }
+ public int getHeight() {
+ return mDecoder.getHeight();
+ }
+ public Bitmap decodeRegion(Rect wantRegion, BitmapFactory.Options options) {
+ return mDecoder.decodeRegion(wantRegion, options);
+ }
+}
+
+class DumbBitmapRegionDecoder implements SimpleBitmapRegionDecoder {
+ //byte[] streamCopy;
+ Bitmap mBuffer;
+ private DumbBitmapRegionDecoder(Bitmap b) {
+ mBuffer = b;
+ }
+ public static DumbBitmapRegionDecoder newInstance(String pathName) {
+ Bitmap b = BitmapFactory.decodeFile(pathName);
+ if (b != null) {
+ return new DumbBitmapRegionDecoder(b);
+ }
+ return null;
+ }
+ public static DumbBitmapRegionDecoder newInstance(InputStream is) {
+ Bitmap b = BitmapFactory.decodeStream(is);
+ if (b != null) {
+ return new DumbBitmapRegionDecoder(b);
+ }
+ return null;
+ }
+ public int getWidth() {
+ return mBuffer.getWidth();
+ }
+ public int getHeight() {
+ return mBuffer.getHeight();
+ }
+ public Bitmap decodeRegion(Rect wantRegion, BitmapFactory.Options options) {
+ System.out.println("DECODING WITH SAMPLE LEVEL OF " + options.inSampleSize);
+ return Bitmap.createBitmap(
+ mBuffer, wantRegion.left, wantRegion.top, wantRegion.width(), wantRegion.height());
+ }
+}
+
/**
* A {@link com.android.photos.views.TiledImageRenderer.TileSource} using
* {@link BitmapRegionDecoder} to wrap a local file
@@ -58,14 +138,16 @@
public static final int MAX_PREVIEW_SIZE = GL_SIZE_LIMIT / 2;
public static abstract class BitmapSource {
- private BitmapRegionDecoder mDecoder;
+ private SimpleBitmapRegionDecoder mDecoder;
private Bitmap mPreview;
private int mPreviewSize;
private int mRotation;
+ public enum State { NOT_LOADED, LOADED, ERROR_LOADING };
+ private State mState = State.NOT_LOADED;
public BitmapSource(int previewSize) {
mPreviewSize = previewSize;
}
- public void loadInBackground() {
+ public boolean loadInBackground() {
ExifInterface ei = new ExifInterface();
if (readExif(ei)) {
Integer ori = ei.getTagIntValue(ExifInterface.TAG_ORIENTATION);
@@ -74,22 +156,33 @@
}
}
mDecoder = loadBitmapRegionDecoder();
- int width = mDecoder.getWidth();
- int height = mDecoder.getHeight();
- if (mPreviewSize != 0) {
- int previewSize = Math.min(mPreviewSize, MAX_PREVIEW_SIZE);
- BitmapFactory.Options opts = new BitmapFactory.Options();
- opts.inPreferredConfig = Bitmap.Config.ARGB_8888;
- opts.inPreferQualityOverSpeed = true;
+ if (mDecoder == null) {
+ mState = State.ERROR_LOADING;
+ return false;
+ } else {
+ int width = mDecoder.getWidth();
+ int height = mDecoder.getHeight();
+ if (mPreviewSize != 0) {
+ int previewSize = Math.min(mPreviewSize, MAX_PREVIEW_SIZE);
+ BitmapFactory.Options opts = new BitmapFactory.Options();
+ opts.inPreferredConfig = Bitmap.Config.ARGB_8888;
+ opts.inPreferQualityOverSpeed = true;
- float scale = (float) previewSize / Math.max(width, height);
- opts.inSampleSize = BitmapUtils.computeSampleSizeLarger(scale);
- opts.inJustDecodeBounds = false;
- mPreview = loadPreviewBitmap(opts);
+ float scale = (float) previewSize / Math.max(width, height);
+ opts.inSampleSize = BitmapUtils.computeSampleSizeLarger(scale);
+ opts.inJustDecodeBounds = false;
+ mPreview = loadPreviewBitmap(opts);
+ }
+ mState = State.LOADED;
+ return true;
}
}
- public BitmapRegionDecoder getBitmapRegionDecoder() {
+ public State getLoadingState() {
+ return mState;
+ }
+
+ public SimpleBitmapRegionDecoder getBitmapRegionDecoder() {
return mDecoder;
}
@@ -106,7 +199,7 @@
}
public abstract boolean readExif(ExifInterface ei);
- public abstract BitmapRegionDecoder loadBitmapRegionDecoder();
+ public abstract SimpleBitmapRegionDecoder loadBitmapRegionDecoder();
public abstract Bitmap loadPreviewBitmap(BitmapFactory.Options options);
}
@@ -117,13 +210,13 @@
mPath = path;
}
@Override
- public BitmapRegionDecoder loadBitmapRegionDecoder() {
- try {
- return BitmapRegionDecoder.newInstance(mPath, true);
- } catch (IOException e) {
- Log.w("BitmapRegionTileSource", "getting decoder failed", e);
- return null;
+ public SimpleBitmapRegionDecoder loadBitmapRegionDecoder() {
+ SimpleBitmapRegionDecoder d;
+ d = SimpleBitmapRegionDecoderWrapper.newInstance(mPath, true);
+ if (d == null) {
+ d = DumbBitmapRegionDecoder.newInstance(mPath);
}
+ return d;
}
@Override
public Bitmap loadPreviewBitmap(BitmapFactory.Options options) {
@@ -154,9 +247,17 @@
return new BufferedInputStream(is);
}
@Override
- public BitmapRegionDecoder loadBitmapRegionDecoder() {
+ public SimpleBitmapRegionDecoder loadBitmapRegionDecoder() {
try {
- return BitmapRegionDecoder.newInstance(regenerateInputStream(), true);
+ InputStream is = regenerateInputStream();
+ SimpleBitmapRegionDecoder regionDecoder =
+ SimpleBitmapRegionDecoderWrapper.newInstance(is, false);
+ Utils.closeSilently(is);
+ if (regionDecoder == null) {
+ is = regenerateInputStream();
+ regionDecoder = DumbBitmapRegionDecoder.newInstance(is);
+ }
+ return regionDecoder;
} catch (FileNotFoundException e) {
Log.e("BitmapRegionTileSource", "Failed to load URI " + mUri, e);
return null;
@@ -168,7 +269,10 @@
@Override
public Bitmap loadPreviewBitmap(BitmapFactory.Options options) {
try {
- return BitmapFactory.decodeStream(regenerateInputStream(), null, options);
+ InputStream is = regenerateInputStream();
+ Bitmap b = BitmapFactory.decodeStream(is, null, options);
+ Utils.closeSilently(is);
+ return b;
} catch (FileNotFoundException e) {
Log.e("BitmapRegionTileSource", "Failed to load URI " + mUri, e);
return null;
@@ -177,13 +281,15 @@
@Override
public boolean readExif(ExifInterface ei) {
try {
- ei.readExif(regenerateInputStream());
+ InputStream is = regenerateInputStream();
+ ei.readExif(is);
+ Utils.closeSilently(is);
return true;
} catch (FileNotFoundException e) {
Log.e("BitmapRegionTileSource", "Failed to load URI " + mUri, e);
return false;
} catch (IOException e) {
- Log.e("BitmapRegionTileSource", "Failure while reading URI " + mUri, e);
+ Log.e("BitmapRegionTileSource", "Failed to load URI " + mUri, e);
return false;
}
}
@@ -202,13 +308,16 @@
return new BufferedInputStream(is);
}
@Override
- public BitmapRegionDecoder loadBitmapRegionDecoder() {
- try {
- return BitmapRegionDecoder.newInstance(regenerateInputStream(), true);
- } catch (IOException e) {
- Log.e("BitmapRegionTileSource", "Error reading resource", e);
- return null;
+ public SimpleBitmapRegionDecoder loadBitmapRegionDecoder() {
+ InputStream is = regenerateInputStream();
+ SimpleBitmapRegionDecoder regionDecoder =
+ SimpleBitmapRegionDecoderWrapper.newInstance(is, false);
+ Utils.closeSilently(is);
+ if (regionDecoder == null) {
+ is = regenerateInputStream();
+ regionDecoder = DumbBitmapRegionDecoder.newInstance(is);
}
+ return regionDecoder;
}
@Override
public Bitmap loadPreviewBitmap(BitmapFactory.Options options) {
@@ -217,7 +326,9 @@
@Override
public boolean readExif(ExifInterface ei) {
try {
- ei.readExif(regenerateInputStream());
+ InputStream is = regenerateInputStream();
+ ei.readExif(is);
+ Utils.closeSilently(is);
return true;
} catch (IOException e) {
Log.e("BitmapRegionTileSource", "Error reading resource", e);
@@ -226,7 +337,7 @@
}
}
- BitmapRegionDecoder mDecoder;
+ SimpleBitmapRegionDecoder mDecoder;
int mWidth;
int mHeight;
int mTileSize;
@@ -243,27 +354,29 @@
mTileSize = TiledImageRenderer.suggestedTileSize(context);
mRotation = source.getRotation();
mDecoder = source.getBitmapRegionDecoder();
- mWidth = mDecoder.getWidth();
- mHeight = mDecoder.getHeight();
- mOptions = new BitmapFactory.Options();
- mOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;
- mOptions.inPreferQualityOverSpeed = true;
- mOptions.inTempStorage = new byte[16 * 1024];
- int previewSize = source.getPreviewSize();
- if (previewSize != 0) {
- previewSize = Math.min(previewSize, MAX_PREVIEW_SIZE);
- // Although this is the same size as the Bitmap that is likely already
- // loaded, the lifecycle is different and interactions are on a different
- // thread. Thus to simplify, this source will decode its own bitmap.
- Bitmap preview = decodePreview(source, previewSize);
- if (preview.getWidth() <= GL_SIZE_LIMIT && preview.getHeight() <= GL_SIZE_LIMIT) {
- mPreview = new BitmapTexture(preview);
- } else {
- Log.w(TAG, String.format(
- "Failed to create preview of apropriate size! "
- + " in: %dx%d, out: %dx%d",
- mWidth, mHeight,
- preview.getWidth(), preview.getHeight()));
+ if (mDecoder != null) {
+ mWidth = mDecoder.getWidth();
+ mHeight = mDecoder.getHeight();
+ mOptions = new BitmapFactory.Options();
+ mOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;
+ mOptions.inPreferQualityOverSpeed = true;
+ mOptions.inTempStorage = new byte[16 * 1024];
+ int previewSize = source.getPreviewSize();
+ if (previewSize != 0) {
+ previewSize = Math.min(previewSize, MAX_PREVIEW_SIZE);
+ // Although this is the same size as the Bitmap that is likely already
+ // loaded, the lifecycle is different and interactions are on a different
+ // thread. Thus to simplify, this source will decode its own bitmap.
+ Bitmap preview = decodePreview(source, previewSize);
+ if (preview.getWidth() <= GL_SIZE_LIMIT && preview.getHeight() <= GL_SIZE_LIMIT) {
+ mPreview = new BitmapTexture(preview);
+ } else {
+ Log.w(TAG, String.format(
+ "Failed to create preview of apropriate size! "
+ + " in: %dx%d, out: %dx%d",
+ mWidth, mHeight,
+ preview.getWidth(), preview.getHeight()));
+ }
}
}
}
diff --git a/packages/WallpaperCropper/src/com/android/wallpapercropper/WallpaperCropActivity.java b/packages/WallpaperCropper/src/com/android/wallpapercropper/WallpaperCropActivity.java
index 220f567..d12140d 100644
--- a/packages/WallpaperCropper/src/com/android/wallpapercropper/WallpaperCropActivity.java
+++ b/packages/WallpaperCropper/src/com/android/wallpapercropper/WallpaperCropActivity.java
@@ -41,10 +41,12 @@
import android.view.Display;
import android.view.View;
import android.view.WindowManager;
+import android.widget.Toast;
import com.android.gallery3d.common.Utils;
import com.android.gallery3d.exif.ExifInterface;
import com.android.photos.BitmapRegionTileSource;
+import com.android.photos.BitmapRegionTileSource.BitmapSource;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
@@ -109,12 +111,24 @@
});
// Load image in background
- setCropViewTileSource(
- new BitmapRegionTileSource.UriBitmapSource(this, imageUri, 1024), true, false);
+ final BitmapRegionTileSource.UriBitmapSource bitmapSource =
+ new BitmapRegionTileSource.UriBitmapSource(this, imageUri, 1024);
+ Runnable onLoad = new Runnable() {
+ public void run() {
+ if (bitmapSource.getLoadingState() != BitmapSource.State.LOADED) {
+ Toast.makeText(WallpaperCropActivity.this,
+ getString(R.string.wallpaper_load_fail),
+ Toast.LENGTH_LONG).show();
+ finish();
+ }
+ }
+ };
+ setCropViewTileSource(bitmapSource, true, false, onLoad);
}
- public void setCropViewTileSource(final BitmapRegionTileSource.BitmapSource bitmapSource,
- final boolean touchEnabled, final boolean moveToLeft) {
+ public void setCropViewTileSource(
+ final BitmapRegionTileSource.BitmapSource bitmapSource, final boolean touchEnabled,
+ final boolean moveToLeft, final Runnable postExecute) {
final Context context = WallpaperCropActivity.this;
final View progressView = findViewById(R.id.loading);
final AsyncTask<Void, Void, Void> loadBitmapTask = new AsyncTask<Void, Void, Void>() {
@@ -127,13 +141,18 @@
protected void onPostExecute(Void arg) {
if (!isCancelled()) {
progressView.setVisibility(View.INVISIBLE);
- mCropView.setTileSource(
- new BitmapRegionTileSource(context, bitmapSource), null);
- mCropView.setTouchEnabled(touchEnabled);
- if (moveToLeft) {
- mCropView.moveToLeft();
+ if (bitmapSource.getLoadingState() == BitmapSource.State.LOADED) {
+ mCropView.setTileSource(
+ new BitmapRegionTileSource(context, bitmapSource), null);
+ mCropView.setTouchEnabled(touchEnabled);
+ if (moveToLeft) {
+ mCropView.moveToLeft();
+ }
}
}
+ if (postExecute != null) {
+ postExecute.run();
+ }
}
};
// We don't want to show the spinner every time we load an image, because that would be
@@ -235,10 +254,12 @@
InputStream is = context.getContentResolver().openInputStream(uri);
BufferedInputStream bis = new BufferedInputStream(is);
ei.readExif(bis);
+ bis.close();
} else {
InputStream is = res.openRawResource(resId);
BufferedInputStream bis = new BufferedInputStream(is);
ei.readExif(bis);
+ bis.close();
}
Integer ori = ei.getTagIntValue(ExifInterface.TAG_ORIENTATION);
if (ori != null) {
@@ -408,7 +429,6 @@
String mInFilePath;
byte[] mInImageBytes;
int mInResId = 0;
- InputStream mInStream;
RectF mCropBounds = null;
int mOutWidth, mOutHeight;
int mRotation;
@@ -481,37 +501,36 @@
}
// Helper to setup input stream
- private void regenerateInputStream() {
+ private InputStream regenerateInputStream() {
if (mInUri == null && mInResId == 0 && mInFilePath == null && mInImageBytes == null) {
Log.w(LOGTAG, "cannot read original file, no input URI, resource ID, or " +
"image byte array given");
} else {
- Utils.closeSilently(mInStream);
try {
if (mInUri != null) {
- mInStream = new BufferedInputStream(
+ return new BufferedInputStream(
mContext.getContentResolver().openInputStream(mInUri));
} else if (mInFilePath != null) {
- mInStream = mContext.openFileInput(mInFilePath);
+ return mContext.openFileInput(mInFilePath);
} else if (mInImageBytes != null) {
- mInStream = new BufferedInputStream(
- new ByteArrayInputStream(mInImageBytes));
+ return new BufferedInputStream(new ByteArrayInputStream(mInImageBytes));
} else {
- mInStream = new BufferedInputStream(
- mResources.openRawResource(mInResId));
+ return new BufferedInputStream(mResources.openRawResource(mInResId));
}
} catch (FileNotFoundException e) {
Log.w(LOGTAG, "cannot read file: " + mInUri.toString(), e);
}
}
+ return null;
}
public Point getImageBounds() {
- regenerateInputStream();
- if (mInStream != null) {
+ InputStream is = regenerateInputStream();
+ if (is != null) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
- BitmapFactory.decodeStream(mInStream, null, options);
+ BitmapFactory.decodeStream(is, null, options);
+ Utils.closeSilently(is);
if (options.outWidth != 0 && options.outHeight != 0) {
return new Point(options.outWidth, options.outHeight);
}
@@ -529,22 +548,26 @@
public boolean cropBitmap() {
boolean failure = false;
- regenerateInputStream();
WallpaperManager wallpaperManager = null;
if (mSetWallpaper) {
wallpaperManager = WallpaperManager.getInstance(mContext.getApplicationContext());
}
- if (mSetWallpaper && mNoCrop && mInStream != null) {
+
+
+ if (mSetWallpaper && mNoCrop) {
try {
- wallpaperManager.setStream(mInStream);
+ InputStream is = regenerateInputStream();
+ if (is != null) {
+ wallpaperManager.setStream(is);
+ Utils.closeSilently(is);
+ }
} catch (IOException e) {
Log.w(LOGTAG, "cannot write stream to wallpaper", e);
failure = true;
}
return !failure;
- }
- if (mInStream != null) {
+ } else {
// Find crop bounds (scaled to original image size)
Rect roundedTrueCrop = new Rect();
Matrix rotateMatrix = new Matrix();
@@ -557,6 +580,11 @@
mCropBounds = new RectF(roundedTrueCrop);
Point bounds = getImageBounds();
+ if (bounds == null) {
+ Log.w(LOGTAG, "cannot get bounds for image");
+ failure = true;
+ return false;
+ }
float[] rotatedBounds = new float[] { bounds.x, bounds.y };
rotateMatrix.mapPoints(rotatedBounds);
@@ -567,7 +595,6 @@
inverseRotateMatrix.mapRect(mCropBounds);
mCropBounds.offset(bounds.x/2, bounds.y/2);
- regenerateInputStream();
}
mCropBounds.roundOut(roundedTrueCrop);
@@ -585,7 +612,14 @@
// Attempt to open a region decoder
BitmapRegionDecoder decoder = null;
try {
- decoder = BitmapRegionDecoder.newInstance(mInStream, true);
+ InputStream is = regenerateInputStream();
+ if (is == null) {
+ Log.w(LOGTAG, "cannot get input stream for uri=" + mInUri.toString());
+ failure = true;
+ return false;
+ }
+ decoder = BitmapRegionDecoder.newInstance(is, false);
+ Utils.closeSilently(is);
} catch (IOException e) {
Log.w(LOGTAG, "cannot open region decoder for file: " + mInUri.toString(), e);
}
@@ -603,14 +637,15 @@
if (crop == null) {
// BitmapRegionDecoder has failed, try to crop in-memory
- regenerateInputStream();
+ InputStream is = regenerateInputStream();
Bitmap fullSize = null;
- if (mInStream != null) {
+ if (is != null) {
BitmapFactory.Options options = new BitmapFactory.Options();
if (scaleDownSampleSize > 1) {
options.inSampleSize = scaleDownSampleSize;
}
- fullSize = BitmapFactory.decodeStream(mInStream, null, options);
+ fullSize = BitmapFactory.decodeStream(is, null, options);
+ Utils.closeSilently(is);
}
if (fullSize != null) {
mCropBounds.left /= scaleDownSampleSize;
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index dcaf3d6..faca949 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -3466,6 +3466,8 @@
if (mStatusBarController.setBarShowingLw(true)) {
changes |= FINISH_LAYOUT_REDO_LAYOUT;
}
+ // Maintain fullscreen layout until incoming animation is complete.
+ topIsFullscreen = mTopIsFullscreen && mStatusBar.isAnimatingLw();
} else if (mTopFullscreenOpaqueWindowState != null) {
if (localLOGV) {
Slog.d(TAG, "frame: " + mTopFullscreenOpaqueWindowState.getFrameLw()
@@ -3499,7 +3501,13 @@
}
}
- mTopIsFullscreen = topIsFullscreen;
+ if (mTopIsFullscreen != topIsFullscreen) {
+ if (!topIsFullscreen) {
+ // Force another layout when status bar becomes fully shown.
+ changes |= FINISH_LAYOUT_REDO_LAYOUT;
+ }
+ mTopIsFullscreen = topIsFullscreen;
+ }
// Hide the key guard if a visible window explicitly specifies that it wants to be
// displayed when the screen is locked.
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index 2e5dedf..44ff3bc 100644
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -3408,6 +3408,9 @@
int numActivities = 0;
int numRunning = 0;
final ArrayList<ActivityRecord> activities = task.mActivities;
+ if (activities.isEmpty()) {
+ continue;
+ }
for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
r = activities.get(activityNdx);
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index a781d5f..3d6b3c9 100755
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -9965,6 +9965,10 @@
// writer
int callingUid = Binder.getCallingUid();
enforceCrossUserPermission(callingUid, userId, true, "add preferred activity");
+ if (filter.countActions() == 0) {
+ Slog.w(TAG, "Cannot set a preferred activity with no filter actions");
+ return;
+ }
synchronized (mPackages) {
if (mContext.checkCallingOrSelfPermission(
android.Manifest.permission.SET_PREFERRED_APPLICATIONS)
@@ -10024,7 +10028,9 @@
String category = filter.getCategory(0);
while (it.hasNext()) {
PreferredActivity pa = it.next();
- if (pa.getAction(0).equals(action) && pa.getCategory(0).equals(category)) {
+ if ((pa.countActions() == 0) || (pa.countCategories() == 0)
+ || (pa.getAction(0).equals(action)
+ && pa.getCategory(0).equals(category))) {
if (removed == null) {
removed = new ArrayList<PreferredActivity>();
}
diff --git a/services/java/com/android/server/wm/WindowStateAnimator.java b/services/java/com/android/server/wm/WindowStateAnimator.java
index af00d83..c405170 100644
--- a/services/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/java/com/android/server/wm/WindowStateAnimator.java
@@ -360,6 +360,10 @@
+ mWin.mToken + ": first real window done animating");
mService.mFinishedStarting.add(mWin.mAppToken);
mService.mH.sendEmptyMessage(H.FINISHED_STARTING);
+ } else if (mAttrType == LayoutParams.TYPE_STATUS_BAR && mWin.mPolicyVisibility) {
+ // Upon completion of a not-visible to visible status bar animation a relayout is
+ // required.
+ mWin.mDisplayContent.layoutNeeded = true;
}
finishExit();