Merge change 22008 into eclair
* changes:
When bringing up the media controller view, focus the play/pause button.
diff --git a/api/current.xml b/api/current.xml
index ec76edb..c5f5919 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -7489,6 +7489,28 @@
visibility="public"
>
</field>
+<field name="supportsUploading"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843410"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="supportsUploading"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843410"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="syncable"
type="int"
transient="false"
@@ -8567,6 +8589,50 @@
visibility="public"
>
</field>
+<field name="wallpaperActivityCloseEnterAnimation"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843412"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="wallpaperActivityCloseExitAnimation"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843413"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="wallpaperActivityOpenEnterAnimation"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843410"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="wallpaperActivityOpenExitAnimation"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843411"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="webViewStyle"
type="int"
transient="false"
@@ -12087,6 +12153,17 @@
visibility="public"
>
</field>
+<field name="Animation_InputMethod"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973910"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="Animation_Toast"
type="int"
transient="false"
@@ -24946,6 +25023,235 @@
</field>
</class>
</package>
+<package name="android.bluetooth"
+>
+<class name="BluetoothAdapter"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="getRemoteDevice"
+ return="android.bluetooth.BluetoothDevice"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="address" type="java.lang.String">
+</parameter>
+</method>
+<method name="listenUsingRfcommOn"
+ return="android.bluetooth.BluetoothServerSocket"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="channel" type="int">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+</class>
+<class name="BluetoothDevice"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="android.os.Parcelable">
+</implements>
+<method name="createRfcommSocket"
+ return="android.bluetooth.BluetoothSocket"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="channel" type="int">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="describeContents"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getAddress"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="writeToParcel"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="out" type="android.os.Parcel">
+</parameter>
+<parameter name="flags" type="int">
+</parameter>
+</method>
+</class>
+<class name="BluetoothServerSocket"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="java.io.Closeable">
+</implements>
+<method name="accept"
+ return="android.bluetooth.BluetoothSocket"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="accept"
+ return="android.bluetooth.BluetoothSocket"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="timeout" type="int">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="close"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+</class>
+<class name="BluetoothSocket"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="java.io.Closeable">
+</implements>
+<method name="close"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="connect"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="getInputStream"
+ return="java.io.InputStream"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="getOutputStream"
+ return="java.io.OutputStream"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="getRemoteDevice"
+ return="android.bluetooth.BluetoothDevice"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+</package>
<package name="android.content"
>
<class name="AbstractCursorEntityIterator"
@@ -29304,6 +29610,17 @@
visibility="public"
>
</field>
+<field name="BLUETOOTH_SERVICE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""bluetooth""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="CLIPBOARD_SERVICE"
type="java.lang.String"
transient="false"
@@ -35829,6 +36146,8 @@
</parameter>
<parameter name="userVisible" type="boolean">
</parameter>
+<parameter name="supportsUploading" type="boolean">
+</parameter>
</constructor>
<constructor name="SyncAdapterType"
type="android.content.SyncAdapterType"
@@ -35851,6 +36170,17 @@
visibility="public"
>
</method>
+<method name="isUserVisible"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="newKey"
return="android.content.SyncAdapterType"
abstract="false"
@@ -35866,6 +36196,17 @@
<parameter name="accountType" type="java.lang.String">
</parameter>
</method>
+<method name="supportsUploading"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="writeToParcel"
return="void"
abstract="false"
@@ -35911,7 +36252,7 @@
visibility="public"
>
</field>
-<field name="userVisible"
+<field name="isKey"
type="boolean"
transient="false"
volatile="false"
@@ -144974,6 +145315,8 @@
>
<parameter name="dirty" type="android.graphics.Rect">
</parameter>
+<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
+</exception>
<exception name="Surface.OutOfResourcesException" type="android.view.Surface.OutOfResourcesException">
</exception>
</method>
diff --git a/cmds/stagefright/JPEGSource.cpp b/cmds/stagefright/JPEGSource.cpp
index 338a3d5..a7994ed 100644
--- a/cmds/stagefright/JPEGSource.cpp
+++ b/cmds/stagefright/JPEGSource.cpp
@@ -60,6 +60,7 @@
mHeight(0),
mOffset(0) {
CHECK_EQ(parseJPEG(), OK);
+ CHECK(mSource->getSize(&mSize) == OK);
}
JPEGSource::~JPEGSource() {
@@ -73,10 +74,6 @@
return UNKNOWN_ERROR;
}
- if (mSource->getSize(&mSize) != OK) {
- return UNKNOWN_ERROR;
- }
-
mGroup = new MediaBufferGroup;
mGroup->add_buffer(new MediaBuffer(mSize));
@@ -105,6 +102,7 @@
meta->setCString(kKeyMIMEType, "image/jpeg");
meta->setInt32(kKeyWidth, mWidth);
meta->setInt32(kKeyHeight, mHeight);
+ meta->setInt32(kKeyCompressedSize, mSize);
return meta;
}
diff --git a/cmds/stagefright/stagefright.cpp b/cmds/stagefright/stagefright.cpp
index 56f6338..185e6ac 100644
--- a/cmds/stagefright/stagefright.cpp
+++ b/cmds/stagefright/stagefright.cpp
@@ -70,6 +70,7 @@
long numIterationsLeft = gNumRepetitions;
MediaSource::ReadOptions options;
+
while (numIterationsLeft-- > 0) {
MediaBuffer *buffer;
diff --git a/core/java/android/appwidget/AppWidgetHostView.java b/core/java/android/appwidget/AppWidgetHostView.java
index cced338..a4c141e 100644
--- a/core/java/android/appwidget/AppWidgetHostView.java
+++ b/core/java/android/appwidget/AppWidgetHostView.java
@@ -322,6 +322,7 @@
if (mInfo != null) {
Context theirContext = mContext.createPackageContext(
mInfo.provider.getPackageName(), Context.CONTEXT_RESTRICTED);
+ mRemoteContext = theirContext;
LayoutInflater inflater = (LayoutInflater)
theirContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater = inflater.cloneInContext(theirContext);
@@ -336,8 +337,8 @@
exception = e;
}
- if (exception != null && LOGD) {
- Log.w(TAG, "Error inflating AppWidget " + mInfo, exception);
+ if (exception != null) {
+ Log.w(TAG, "Error inflating AppWidget " + mInfo + ": " + exception.toString());
}
if (defaultView == null) {
diff --git a/core/java/android/bluetooth/BluetoothA2dp.java b/core/java/android/bluetooth/BluetoothA2dp.java
index 6e48b66..b531a50 100644
--- a/core/java/android/bluetooth/BluetoothA2dp.java
+++ b/core/java/android/bluetooth/BluetoothA2dp.java
@@ -213,31 +213,6 @@
}
}
- /**
- * Check class bits for possible A2DP Sink support.
- * This is a simple heuristic that tries to guess if a device with the
- * given class bits might be a A2DP Sink. It is not accurate for all
- * devices. It tries to err on the side of false positives.
- * @return True if this device might be a A2DP sink
- */
- public static boolean doesClassMatchSink(int btClass) {
- if (BluetoothClass.Service.hasService(btClass, BluetoothClass.Service.RENDER)) {
- return true;
- }
- // By the A2DP spec, sinks must indicate the RENDER service.
- // However we found some that do not (Chordette). So lets also
- // match on some other class bits.
- switch (BluetoothClass.Device.getDevice(btClass)) {
- case BluetoothClass.Device.AUDIO_VIDEO_HIFI_AUDIO:
- case BluetoothClass.Device.AUDIO_VIDEO_HEADPHONES:
- case BluetoothClass.Device.AUDIO_VIDEO_LOUDSPEAKER:
- case BluetoothClass.Device.AUDIO_VIDEO_CAR_AUDIO:
- return true;
- default:
- return false;
- }
- }
-
/** Helper for converting a state to a string.
* For debug use only - strings are not internationalized.
* @hide
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index d207540..6bd2a5a 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -27,34 +27,54 @@
/**
* Represents the local Bluetooth adapter.
*
- * @hide
+ * <p>Use {@link android.content.Context#getSystemService} with {@link
+ * android.content.Context#BLUETOOTH_SERVICE} to get the default local
+ * Bluetooth adapter. On most Android devices there is only one local
+ * Bluetotoh adapter.
+ *
+ * <p>Use the {@link BluetoothDevice} class for operations on remote Bluetooth
+ * devices.
+ *
+ * <p>TODO: unhide more of this class
*/
public final class BluetoothAdapter {
private static final String TAG = "BluetoothAdapter";
+ /** @hide */
public static final int BLUETOOTH_STATE_OFF = 0;
+ /** @hide */
public static final int BLUETOOTH_STATE_TURNING_ON = 1;
+ /** @hide */
public static final int BLUETOOTH_STATE_ON = 2;
+ /** @hide */
public static final int BLUETOOTH_STATE_TURNING_OFF = 3;
/** Inquiry scan and page scan are both off.
- * Device is neither discoverable nor connectable */
+ * Device is neither discoverable nor connectable
+ * @hide */
public static final int SCAN_MODE_NONE = 0;
/** Page scan is on, inquiry scan is off.
- * Device is connectable, but not discoverable */
+ * Device is connectable, but not discoverable
+ * @hide*/
public static final int SCAN_MODE_CONNECTABLE = 1;
/** Page scan and inquiry scan are on.
- * Device is connectable and discoverable */
+ * Device is connectable and discoverable
+ * @hide*/
public static final int SCAN_MODE_CONNECTABLE_DISCOVERABLE = 3;
+ /** @hide */
public static final int RESULT_FAILURE = -1;
+ /** @hide */
public static final int RESULT_SUCCESS = 0;
- /* The user will be prompted to enter a pin */
+ /** The user will be prompted to enter a pin
+ * @hide */
public static final int PAIRING_VARIANT_PIN = 0;
- /* The user will be prompted to enter a passkey */
+ /** The user will be prompted to enter a passkey
+ * @hide */
public static final int PAIRING_VARIANT_PASSKEY = 1;
- /* The user will be prompted to confirm the passkey displayed on the screen */
+ /** The user will be prompted to confirm the passkey displayed on the screen
+ * @hide */
public static final int PAIRING_VARIANT_CONFIRMATION = 2;
private final IBluetooth mService;
@@ -71,9 +91,14 @@
}
/**
- * Get the remote BluetoothDevice associated with the given MAC address.
- * Bluetooth MAC address must be upper case, such as "00:11:22:33:AA:BB".
+ * Get a {@link BluetoothDevice} object for the given Bluetooth hardware
+ * address.
+ * <p>Valid Bluetooth hardware addresses must be upper case, in a format
+ * such as "00:11:22:33:AA:BB".
+ * <p>A {@link BluetoothDevice} will always be returned for a valid
+ * hardware address, even if this adapter has never seen that device.
* @param address valid Bluetooth MAC address
+ * @throws IllegalArgumentException if address is invalid
*/
public BluetoothDevice getRemoteDevice(String address) {
return new BluetoothDevice(address);
@@ -83,6 +108,7 @@
* Is Bluetooth currently turned on.
*
* @return true if Bluetooth enabled, false otherwise.
+ * @hide
*/
public boolean isEnabled() {
try {
@@ -95,6 +121,7 @@
* Get the current state of Bluetooth.
*
* @return One of BLUETOOTH_STATE_ or BluetoothError.ERROR.
+ * @hide
*/
public int getBluetoothState() {
try {
@@ -112,6 +139,7 @@
* @return false if we cannot enable the Bluetooth device. True does not
* imply the device was enabled, it only implies that so far there were no
* problems.
+ * @hide
*/
public boolean enable() {
try {
@@ -125,6 +153,7 @@
* This turns off the underlying hardware.
*
* @return true if successful, false otherwise.
+ * @hide
*/
public boolean disable() {
try {
@@ -133,6 +162,7 @@
return false;
}
+ /** @hide */
public String getAddress() {
try {
return mService.getAddress();
@@ -147,6 +177,7 @@
* possible to retrieve the Bluetooth name when Bluetooth is enabled.
*
* @return the Bluetooth name, or null if there was a problem.
+ * @hide
*/
public String getName() {
try {
@@ -163,6 +194,7 @@
*
* @param name the name to set
* @return true, if the name was successfully set. False otherwise.
+ * @hide
*/
public boolean setName(String name) {
try {
@@ -175,6 +207,7 @@
* Get the current scan mode.
* Used to determine if the local device is connectable and/or discoverable
* @return Scan mode, one of SCAN_MODE_* or an error code
+ * @hide
*/
public int getScanMode() {
try {
@@ -187,6 +220,7 @@
* Set the current scan mode.
* Used to make the local device connectable and/or discoverable
* @param scanMode One of SCAN_MODE_*
+ * @hide
*/
public void setScanMode(int scanMode) {
try {
@@ -194,6 +228,7 @@
} catch (RemoteException e) {Log.e(TAG, "", e);}
}
+ /** @hide */
public int getDiscoverableTimeout() {
try {
return mService.getDiscoverableTimeout();
@@ -201,12 +236,14 @@
return -1;
}
+ /** @hide */
public void setDiscoverableTimeout(int timeout) {
try {
mService.setDiscoverableTimeout(timeout);
} catch (RemoteException e) {Log.e(TAG, "", e);}
}
+ /** @hide */
public boolean startDiscovery() {
try {
return mService.startDiscovery();
@@ -214,12 +251,14 @@
return false;
}
+ /** @hide */
public void cancelDiscovery() {
try {
mService.cancelDiscovery();
} catch (RemoteException e) {Log.e(TAG, "", e);}
}
+ /** @hide */
public boolean isDiscovering() {
try {
return mService.isDiscovering();
@@ -248,6 +287,7 @@
* returned.
*
* @return unmodifiable set of bonded devices, or null on error
+ * @hide
*/
public Set<BluetoothDevice> getBondedDevices() {
try {
@@ -257,17 +297,20 @@
}
/**
- * Construct a listening, secure RFCOMM server socket.
- * The remote device connecting to this socket will be authenticated and
+ * Create a listening, secure RFCOMM Bluetooth socket.
+ * <p>A remote device connecting to this socket will be authenticated and
* communication on this socket will be encrypted.
- * Call #accept to retrieve connections to this socket.
- * @return An RFCOMM BluetoothServerSocket
- * @throws IOException On error, for example Bluetooth not available, or
- * insufficient permissions.
+ * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming
+ * connections to listening {@link BluetoothServerSocket}.
+ * <p>Valid RFCOMM channels are in range 1 to 30.
+ * @param channel RFCOMM channel to listen on
+ * @return a listening RFCOMM BluetoothServerSocket
+ * @throws IOException on error, for example Bluetooth not available, or
+ * insufficient permissions, or channel in use.
*/
- public BluetoothServerSocket listenUsingRfcommOn(int port) throws IOException {
+ public BluetoothServerSocket listenUsingRfcommOn(int channel) throws IOException {
BluetoothServerSocket socket = new BluetoothServerSocket(
- BluetoothSocket.TYPE_RFCOMM, true, true, port);
+ BluetoothSocket.TYPE_RFCOMM, true, true, channel);
try {
socket.mSocket.bindListenNative();
} catch (IOException e) {
@@ -285,6 +328,7 @@
* @return An RFCOMM BluetoothServerSocket
* @throws IOException On error, for example Bluetooth not available, or
* insufficient permissions.
+ * @hide
*/
public BluetoothServerSocket listenUsingInsecureRfcommOn(int port) throws IOException {
BluetoothServerSocket socket = new BluetoothServerSocket(
@@ -306,6 +350,7 @@
* @return A SCO BluetoothServerSocket
* @throws IOException On error, for example Bluetooth not available, or
* insufficient permissions.
+ * @hide
*/
public static BluetoothServerSocket listenUsingScoOn() throws IOException {
BluetoothServerSocket socket = new BluetoothServerSocket(
diff --git a/core/java/android/bluetooth/BluetoothClass.java b/core/java/android/bluetooth/BluetoothClass.java
index 88ce18b..0061f10 100644
--- a/core/java/android/bluetooth/BluetoothClass.java
+++ b/core/java/android/bluetooth/BluetoothClass.java
@@ -46,6 +46,10 @@
/** Indicates the Bluetooth API could not retrieve the class */
public static final int ERROR = 0xFF000000;
+ public static final int PROFILE_HEADSET = 0;
+ public static final int PROFILE_A2DP = 1;
+ public static final int PROFILE_OPP = 2;
+
/** Every Bluetooth device has zero or more service classes */
public static class Service {
public static final int BITMASK = 0xFFE000;
@@ -187,5 +191,74 @@
return (btClass & Device.BITMASK);
}
}
+
+ /**
+ * Check class bits for possible bluetooth profile support.
+ * This is a simple heuristic that tries to guess if a device with the
+ * given class bits might support specified profile. It is not accurate for all
+ * devices. It tries to err on the side of false positives.
+ * @param btClass The class
+ * @param profile The profile to be checked
+ * @return True if this device might support specified profile.
+ */
+ public static boolean doesClassMatch(int btClass, int profile) {
+ if (profile == PROFILE_A2DP) {
+ if (BluetoothClass.Service.hasService(btClass, BluetoothClass.Service.RENDER)) {
+ return true;
+ }
+ // By the A2DP spec, sinks must indicate the RENDER service.
+ // However we found some that do not (Chordette). So lets also
+ // match on some other class bits.
+ switch (BluetoothClass.Device.getDevice(btClass)) {
+ case BluetoothClass.Device.AUDIO_VIDEO_HIFI_AUDIO:
+ case BluetoothClass.Device.AUDIO_VIDEO_HEADPHONES:
+ case BluetoothClass.Device.AUDIO_VIDEO_LOUDSPEAKER:
+ case BluetoothClass.Device.AUDIO_VIDEO_CAR_AUDIO:
+ return true;
+ default:
+ return false;
+ }
+ } else if (profile == PROFILE_HEADSET) {
+ // The render service class is required by the spec for HFP, so is a
+ // pretty good signal
+ if (BluetoothClass.Service.hasService(btClass, BluetoothClass.Service.RENDER)) {
+ return true;
+ }
+ // Just in case they forgot the render service class
+ switch (BluetoothClass.Device.getDevice(btClass)) {
+ case BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE:
+ case BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET:
+ case BluetoothClass.Device.AUDIO_VIDEO_CAR_AUDIO:
+ return true;
+ default:
+ return false;
+ }
+ } else if (profile == PROFILE_OPP) {
+ if (BluetoothClass.Service.hasService(btClass, BluetoothClass.Service.OBJECT_TRANSFER)) {
+ return true;
+ }
+
+ switch (BluetoothClass.Device.getDevice(btClass)) {
+ case BluetoothClass.Device.COMPUTER_UNCATEGORIZED:
+ case BluetoothClass.Device.COMPUTER_DESKTOP:
+ case BluetoothClass.Device.COMPUTER_SERVER:
+ case BluetoothClass.Device.COMPUTER_LAPTOP:
+ case BluetoothClass.Device.COMPUTER_HANDHELD_PC_PDA:
+ case BluetoothClass.Device.COMPUTER_PALM_SIZE_PC_PDA:
+ case BluetoothClass.Device.COMPUTER_WEARABLE:
+ case BluetoothClass.Device.PHONE_UNCATEGORIZED:
+ case BluetoothClass.Device.PHONE_CELLULAR:
+ case BluetoothClass.Device.PHONE_CORDLESS:
+ case BluetoothClass.Device.PHONE_SMART:
+ case BluetoothClass.Device.PHONE_MODEM_OR_GATEWAY:
+ case BluetoothClass.Device.PHONE_ISDN:
+ return true;
+ default:
+ return false;
+ }
+ } else {
+ return false;
+ }
+ }
}
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index 27b2849..0a71961 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -30,41 +30,72 @@
/**
* Represents a remote Bluetooth device.
*
- * TODO: unhide
- * @hide
+ * <p>Use {@link BluetoothAdapter#getRemoteDevice} to create a {@link
+ * BluetoothDevice}.
+ *
+ * <p>This class is really just a thin wrapper for a Bluetooth hardware
+ * address. Objects of this class are immutable. Operations on this class
+ * are performed on the remote Bluetooth hardware address, using the
+ * {@link BluetoothAdapter} that was used to create this {@link
+ * BluetoothDevice}.
+ *
+ * TODO: unhide more of this class
*/
public final class BluetoothDevice implements Parcelable {
private static final String TAG = "BluetoothDevice";
/** We do not have a link key for the remote device, and are therefore not
- * bonded */
+ * bonded
+ * @hide*/
public static final int BOND_NOT_BONDED = 0;
- /** We have a link key for the remote device, and are probably bonded. */
+ /** We have a link key for the remote device, and are probably bonded.
+ * @hide */
public static final int BOND_BONDED = 1;
- /** We are currently attempting bonding */
+ /** We are currently attempting bonding
+ * @hide */
public static final int BOND_BONDING = 2;
+ /** Ask device picker to show all kinds of BT devices.
+ * @hide */
+ public static final int DEVICE_PICKER_FILTER_TYPE_ALL = 0;
+ /** Ask device picker to show BT devices that support AUDIO profiles.
+ * @hide */
+ public static final int DEVICE_PICKER_FILTER_TYPE_AUDIO = 1;
+ /** Ask device picker to show BT devices that support Object Transfer.
+ * @hide */
+ public static final int DEVICE_PICKER_FILTER_TYPE_TRANSFER = 2;
+
//TODO: Unify these result codes in BluetoothResult or BluetoothError
/** A bond attempt failed because pins did not match, or remote device did
- * not respond to pin request in time */
+ * not respond to pin request in time
+ * @hide */
public static final int UNBOND_REASON_AUTH_FAILED = 1;
/** A bond attempt failed because the other side explicilty rejected
- * bonding */
+ * bonding
+ * @hide */
public static final int UNBOND_REASON_AUTH_REJECTED = 2;
- /** A bond attempt failed because we canceled the bonding process */
+ /** A bond attempt failed because we canceled the bonding process
+ * @hide */
public static final int UNBOND_REASON_AUTH_CANCELED = 3;
- /** A bond attempt failed because we could not contact the remote device */
+ /** A bond attempt failed because we could not contact the remote device
+ * @hide */
public static final int UNBOND_REASON_REMOTE_DEVICE_DOWN = 4;
- /** A bond attempt failed because a discovery is in progress */
+ /** A bond attempt failed because a discovery is in progress
+ * @hide */
public static final int UNBOND_REASON_DISCOVERY_IN_PROGRESS = 5;
- /** An existing bond was explicitly revoked */
+ /** An existing bond was explicitly revoked
+ * @hide */
public static final int UNBOND_REASON_REMOVED = 6;
- /* The user will be prompted to enter a pin */
+ //TODO: Remove duplicates between here and BluetoothAdapter
+ /** The user will be prompted to enter a pin
+ * @hide */
public static final int PAIRING_VARIANT_PIN = 0;
- /* The user will be prompted to enter a passkey */
+ /** The user will be prompted to enter a passkey
+ * @hide */
public static final int PAIRING_VARIANT_PASSKEY = 1;
- /* The user will be prompted to confirm the passkey displayed on the screen */
+ /** The user will be prompted to confirm the passkey displayed on the screen
+ * @hide */
public static final int PAIRING_VARIANT_CONFIRMATION = 2;
private static final int ADDRESS_LENGTH = 17;
@@ -113,15 +144,25 @@
return mAddress.hashCode();
}
+ /**
+ * Returns a string representation of this BluetoothDevice.
+ * <p>Currently this is the Bluetooth hardware address, for example
+ * "00:11:22:AA:BB:CC". However, you should always use {@link #getAddress}
+ * if you explicitly require the Bluetooth hardware address in case the
+ * {@link #toString} representation changes in the future.
+ * @return string representation of this BluetoothDevice
+ */
@Override
public String toString() {
return mAddress;
}
+ /** @hide */
public int describeContents() {
return 0;
}
+ /** @hide */
public static final Parcelable.Creator<BluetoothDevice> CREATOR =
new Parcelable.Creator<BluetoothDevice>() {
public BluetoothDevice createFromParcel(Parcel in) {
@@ -132,21 +173,29 @@
}
};
+ /** @hide */
public void writeToParcel(Parcel out, int flags) {
out.writeString(mAddress);
}
+ /**
+ * Returns the hardware address of this BluetoothDevice.
+ * <p> For example, "00:11:22:AA:BB:CC".
+ * @return Bluetooth hardware address as string
+ */
public String getAddress() {
return mAddress;
}
/**
- * Get the friendly Bluetooth name of this remote device.
+ * Get the friendly Bluetooth name of the remote device.
*
- * This name is visible to remote Bluetooth devices. Currently it is only
- * possible to retrieve the Bluetooth name when Bluetooth is enabled.
+ * <p>The local adapter will automatically retrieve remote names when
+ * performing a device scan, and will cache them. This method just returns
+ * the name for this device from the cache.
*
* @return the Bluetooth name, or null if there was a problem.
+ * @hide
*/
public String getName() {
try {
@@ -164,6 +213,7 @@
* @param address the remote device Bluetooth address.
* @return false If there was an immediate problem creating the bonding,
* true otherwise.
+ * @hide
*/
public boolean createBond() {
try {
@@ -174,6 +224,7 @@
/**
* Cancel an in-progress bonding request started with createBond.
+ * @hide
*/
public boolean cancelBondProcess() {
try {
@@ -188,6 +239,7 @@
*
* @return true if the device was disconnected, false otherwise and on
* error.
+ * @hide
*/
public boolean removeBond() {
try {
@@ -205,6 +257,7 @@
*
* @param address Bluetooth hardware address of the remote device to check.
* @return Result code
+ * @hide
*/
public int getBondState() {
try {
@@ -213,6 +266,7 @@
return BluetoothError.ERROR_IPC;
}
+ /** @hide */
public int getBluetoothClass() {
try {
return sService.getRemoteClass(mAddress);
@@ -220,6 +274,7 @@
return BluetoothError.ERROR_IPC;
}
+ /** @hide */
public String[] getUuids() {
try {
return sService.getRemoteUuids(mAddress);
@@ -227,6 +282,7 @@
return null;
}
+ /** @hide */
public int getServiceChannel(String uuid) {
try {
return sService.getRemoteServiceChannel(mAddress, uuid);
@@ -234,6 +290,7 @@
return BluetoothError.ERROR_IPC;
}
+ /** @hide */
public boolean setPin(byte[] pin) {
try {
return sService.setPin(mAddress, pin);
@@ -241,6 +298,7 @@
return false;
}
+ /** @hide */
public boolean setPasskey(int passkey) {
try {
return sService.setPasskey(mAddress, passkey);
@@ -248,6 +306,7 @@
return false;
}
+ /** @hide */
public boolean setPairingConfirmation(boolean confirm) {
try {
return sService.setPairingConfirmation(mAddress, confirm);
@@ -255,6 +314,7 @@
return false;
}
+ /** @hide */
public boolean cancelPairingUserInput() {
try {
return sService.cancelPairingUserInput(mAddress);
@@ -263,17 +323,20 @@
}
/**
- * Construct a secure RFCOMM socket ready to start an outgoing connection.
- * Call #connect on the returned #BluetoothSocket to begin the connection.
- * The remote device will be authenticated and communication on this socket
- * will be encrypted.
- * @param port remote port
- * @return an RFCOMM BluetoothSocket
+ * Create an RFCOMM {@link BluetoothSocket} ready to start a secure
+ * outgoing connection to this remote device.
+ * <p>The remote device will be authenticated and communication on this
+ * socket will be encrypted.
+ * <p>Use {@link BluetoothSocket#connect} to intiate the outgoing
+ * connection.
+ * <p>Valid RFCOMM channels are in range 1 to 30.
+ * @param channel RFCOMM channel to connect to
+ * @return a RFCOMM BluetoothServerSocket ready for an outgoing connection
* @throws IOException on error, for example Bluetooth not available, or
- * insufficient permissions.
+ * insufficient permissions
*/
- public BluetoothSocket createRfcommSocket(int port) throws IOException {
- return new BluetoothSocket(BluetoothSocket.TYPE_RFCOMM, -1, true, true, this, port);
+ public BluetoothSocket createRfcommSocket(int channel) throws IOException {
+ return new BluetoothSocket(BluetoothSocket.TYPE_RFCOMM, -1, true, true, this, channel);
}
/**
@@ -286,6 +349,7 @@
* @return An RFCOMM BluetoothSocket
* @throws IOException On error, for example Bluetooth not available, or
* insufficient permissions.
+ * @hide
*/
public BluetoothSocket createInsecureRfcommSocket(int port) throws IOException {
return new BluetoothSocket(BluetoothSocket.TYPE_RFCOMM, -1, false, false, this, port);
@@ -297,6 +361,7 @@
* @return a SCO BluetoothSocket
* @throws IOException on error, for example Bluetooth not available, or
* insufficient permissions.
+ * @hide
*/
public BluetoothSocket createScoSocket() throws IOException {
return new BluetoothSocket(BluetoothSocket.TYPE_SCO, -1, true, true, this, -1);
@@ -309,6 +374,7 @@
* @param pin pin as java String
* @return the pin code as a UTF8 byte array, or null if it is an invalid
* Bluetooth pin.
+ * @hide
*/
public static byte[] convertPinToBytes(String pin) {
if (pin == null) {
@@ -327,7 +393,8 @@
return pinBytes;
}
- /** Sanity check a bluetooth address, such as "00:43:A8:23:10:F0" */
+ /** Sanity check a bluetooth address, such as "00:43:A8:23:10:F0"
+ * @hide */
public static boolean checkBluetoothAddress(String address) {
if (address == null || address.length() != ADDRESS_LENGTH) {
return false;
diff --git a/core/java/android/bluetooth/BluetoothHeadset.java b/core/java/android/bluetooth/BluetoothHeadset.java
index 0e3d2bb..d31b6ae 100644
--- a/core/java/android/bluetooth/BluetoothHeadset.java
+++ b/core/java/android/bluetooth/BluetoothHeadset.java
@@ -356,30 +356,6 @@
return -1;
}
- /**
- * Check class bits for possible HSP or HFP support.
- * This is a simple heuristic that tries to guess if a device with the
- * given class bits might support HSP or HFP. It is not accurate for all
- * devices. It tries to err on the side of false positives.
- * @return True if this device might support HSP or HFP.
- */
- public static boolean doesClassMatch(int btClass) {
- // The render service class is required by the spec for HFP, so is a
- // pretty good signal
- if (BluetoothClass.Service.hasService(btClass, BluetoothClass.Service.RENDER)) {
- return true;
- }
- // Just in case they forgot the render service class
- switch (BluetoothClass.Device.getDevice(btClass)) {
- case BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE:
- case BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET:
- case BluetoothClass.Device.AUDIO_VIDEO_CAR_AUDIO:
- return true;
- default:
- return false;
- }
- }
-
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
if (DBG) Log.d(TAG, "Proxy object connected");
diff --git a/core/java/android/bluetooth/BluetoothIntent.java b/core/java/android/bluetooth/BluetoothIntent.java
index 2a0de61..c39bc3d 100644
--- a/core/java/android/bluetooth/BluetoothIntent.java
+++ b/core/java/android/bluetooth/BluetoothIntent.java
@@ -62,6 +62,35 @@
public static final String PASSKEY =
"android.bluetooth.intent.PASSKEY";
+ public static final String DEVICE_PICKER_NEED_AUTH =
+ "android.bluetooth.intent.DEVICE_PICKER_NEED_AUTH";
+ public static final String DEVICE_PICKER_FILTER_TYPE =
+ "android.bluetooth.intent.DEVICE_PICKER_FILTER_TYPE";
+ public static final String DEVICE_PICKER_LAUNCH_PACKAGE =
+ "android.bluetooth.intent.DEVICE_PICKER_LAUNCH_PACKAGE";
+ public static final String DEVICE_PICKER_LAUNCH_CLASS =
+ "android.bluetooth.intent.DEVICE_PICKER_LAUNCH_CLASS";
+
+ /**
+ * Broadcast when one BT device is selected from BT device picker screen.
+ * Selected BT device address is contained in extra string "BluetoothIntent.ADDRESS".
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String DEVICE_PICKER_DEVICE_SELECTED =
+ "android.bluetooth.intent.action.DEVICE_SELECTED";
+
+ /**
+ * Broadcast when someone want to select one BT device from devices list.
+ * This intent contains below extra data:
+ * - BluetoothIntent.DEVICE_PICKER_NEED_AUTH (boolean): if need authentication
+ * - BluetoothIntent.DEVICE_PICKER_FILTER_TYPE (int): what kinds of device should be listed
+ * - BluetoothIntent.DEVICE_PICKER_LAUNCH_PACKAGE (string): where(which package) this intent come from
+ * - BluetoothIntent.DEVICE_PICKER_LAUNCH_CLASS (string): where(which class) this intent come from
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String DEVICE_PICKER_DEVICE_PICKER =
+ "android.bluetooth.intent.action.DEVICE_PICKER";
+
/** Broadcast when the local Bluetooth device state changes, for example
* when Bluetooth is enabled. Will contain int extra's BLUETOOTH_STATE and
* BLUETOOTH_PREVIOUS_STATE. */
diff --git a/core/java/android/bluetooth/BluetoothServerSocket.java b/core/java/android/bluetooth/BluetoothServerSocket.java
index 8be300b..e653c23 100644
--- a/core/java/android/bluetooth/BluetoothServerSocket.java
+++ b/core/java/android/bluetooth/BluetoothServerSocket.java
@@ -20,17 +20,31 @@
import java.io.IOException;
/**
- * Server (listening) Bluetooth Socket.
+ * A listening Bluetooth socket.
*
- * Currently only supports RFCOMM sockets.
+ * <p>The interface for Bluetooth Sockets is similar to that of TCP sockets:
+ * {@link java.net.Socket} and {@link java.net.ServerSocket}. On the server
+ * side, use a {@link BluetoothServerSocket} to create a listening server
+ * socket. It will return a new, connected {@link BluetoothSocket} on an
+ * accepted connection. On the client side, use the same
+ * {@link BluetoothSocket} object to both intiate the outgoing connection,
+ * and to manage the connected socket.
*
- * RFCOMM is a connection orientated, streaming transport over Bluetooth. It is
- * also known as the Serial Port Profile (SPP).
+ * <p>The most common type of Bluetooth Socket is RFCOMM. RFCOMM is a
+ * connection orientated, streaming transport over Bluetooth. It is also known
+ * as the Serial Port Profile (SPP).
*
- * TODO: Consider exposing L2CAP sockets.
- * TODO: Clean up javadoc grammer and formatting.
- * TODO: Remove @hide
- * @hide
+ * <p>Use {@link BluetoothDevice#createRfcommSocket} to create a new {@link
+ * BluetoothSocket} ready for an outgoing connection to a remote
+ * {@link BluetoothDevice}.
+ *
+ * <p>Use {@link BluetoothAdapter#listenUsingRfcommOn} to create a listening
+ * {@link BluetoothServerSocket} ready for incoming connections to the local
+ * {@link BluetoothAdapter}.
+ *
+ * <p>{@link BluetoothSocket} and {@link BluetoothServerSocket} are thread
+ * safe. In particular, {@link #close} will always immediately abort ongoing
+ * operations and close the socket.
*/
public final class BluetoothServerSocket implements Closeable {
/*package*/ final BluetoothSocket mSocket;
@@ -51,11 +65,13 @@
/**
* Block until a connection is established.
- * Returns a connected #BluetoothSocket. This server socket can be reused
- * for subsequent incoming connections by calling #accept repeatedly.
- * #close can be used to abort this call from another thread.
- * @return A connected #BluetoothSocket
- * @throws IOException On error, for example this call was aborted
+ * <p>Returns a connected {@link BluetoothSocket} on successful connection.
+ * <p>Once this call returns, it can be called again to accept subsequent
+ * incoming connections.
+ * <p>{@link #close} can be used to abort this call from another thread.
+ * @return a connected {@link BluetoothSocket}
+ * @throws IOException on error, for example this call was aborted, or
+ * timeout
*/
public BluetoothSocket accept() throws IOException {
return accept(-1);
@@ -63,11 +79,12 @@
/**
* Block until a connection is established, with timeout.
- * Returns a connected #BluetoothSocket. This server socket can be reused
- * for subsequent incoming connections by calling #accept repeatedly.
- * #close can be used to abort this call from another thread.
- * @return A connected #BluetoothSocket
- * @throws IOException On error, for example this call was aborted, or
+ * <p>Returns a connected {@link BluetoothSocket} on successful connection.
+ * <p>Once this call returns, it can be called again to accept subsequent
+ * incoming connections.
+ * <p>{@link #close} can be used to abort this call from another thread.
+ * @return a connected {@link BluetoothSocket}
+ * @throws IOException on error, for example this call was aborted, or
* timeout
*/
public BluetoothSocket accept(int timeout) throws IOException {
@@ -75,8 +92,8 @@
}
/**
- * Closes this socket.
- * This will cause other blocking calls on this socket to immediately
+ * Immediately close this socket, and release all associated resources.
+ * <p>Causes blocked calls on this socket in other threads to immediately
* throw an IOException.
*/
public void close() throws IOException {
diff --git a/core/java/android/bluetooth/BluetoothSocket.java b/core/java/android/bluetooth/BluetoothSocket.java
index dda2cef..eae0f37 100644
--- a/core/java/android/bluetooth/BluetoothSocket.java
+++ b/core/java/android/bluetooth/BluetoothSocket.java
@@ -22,20 +22,34 @@
import java.io.OutputStream;
/**
- * Represents a connected or connecting Bluetooth Socket.
+ * A connected or connecting Bluetooth socket.
*
- * Currently only supports RFCOMM sockets.
+ * <p>The interface for Bluetooth Sockets is similar to that of TCP sockets:
+ * {@link java.net.Socket} and {@link java.net.ServerSocket}. On the server
+ * side, use a {@link BluetoothServerSocket} to create a listening server
+ * socket. It will return a new, connected {@link BluetoothSocket} on an
+ * accepted connection. On the client side, use the same
+ * {@link BluetoothSocket} object to both intiate the outgoing connection,
+ * and to manage the connected socket.
*
- * RFCOMM is a connection orientated, streaming transport over Bluetooth. It is
- * also known as the Serial Port Profile (SPP).
+ * <p>The most common type of Bluetooth Socket is RFCOMM. RFCOMM is a
+ * connection orientated, streaming transport over Bluetooth. It is also known
+ * as the Serial Port Profile (SPP).
*
- * TODO: Consider exposing L2CAP sockets.
- * TODO: Clean up javadoc grammer and formatting.
- * TODO: Remove @hide
- * @hide
+ * <p>Use {@link BluetoothDevice#createRfcommSocket} to create a new {@link
+ * BluetoothSocket} ready for an outgoing connection to a remote
+ * {@link BluetoothDevice}.
+ *
+ * <p>Use {@link BluetoothAdapter#listenUsingRfcommOn} to create a listening
+ * {@link BluetoothServerSocket} ready for incoming connections to the local
+ * {@link BluetoothAdapter}.
+ *
+ * <p>{@link BluetoothSocket} and {@link BluetoothServerSocket} are thread
+ * safe. In particular, {@link #close} will always immediately abort ongoing
+ * operations and close the socket.
*/
public final class BluetoothSocket implements Closeable {
- /** Keep TYPE_RFCOMM etc in sync with BluetoothSocket.cpp */
+ /** Keep TYPE_ fields in sync with BluetoothSocket.cpp */
/*package*/ static final int TYPE_RFCOMM = 1;
/*package*/ static final int TYPE_SCO = 2;
/*package*/ static final int TYPE_L2CAP = 3;
@@ -99,6 +113,7 @@
this(type, fd, auth, encrypt, new BluetoothDevice(address), port);
}
+ /** @hide */
@Override
protected void finalize() throws Throwable {
try {
@@ -110,19 +125,19 @@
/**
* Attempt to connect to a remote device.
- * This method will block until a connection is made or the connection
+ * <p>This method will block until a connection is made or the connection
* fails. If this method returns without an exception then this socket
- * is now connected. #close can be used to abort this call from another
- * thread.
- * @throws IOException On error, for example connection failure
+ * is now connected.
+ * <p>{@link #close} can be used to abort this call from another thread.
+ * @throws IOException on error, for example connection failure
*/
public void connect() throws IOException {
connectNative();
}
/**
- * Closes this socket.
- * This will cause other blocking calls on this socket to immediately
+ * Immediately close this socket, and release all associated resources.
+ * <p>Causes blocked calls on this socket in other threads to immediately
* throw an IOException.
*/
public void close() throws IOException {
@@ -130,9 +145,8 @@
}
/**
- * Return the remote device we are connecting, or connected, to.
- * @return remote device, or null if this socket has not yet attempted
- * or established a connection.
+ * Get the remote device this socket is connecting, or connected, to.
+ * @return remote device
*/
public BluetoothDevice getRemoteDevice() {
return mDevice;
@@ -140,7 +154,7 @@
/**
* Get the input stream associated with this socket.
- * The input stream will be returned even if the socket is not yet
+ * <p>The input stream will be returned even if the socket is not yet
* connected, but operations on that stream will throw IOException until
* the associated socket is connected.
* @return InputStream
@@ -151,7 +165,7 @@
/**
* Get the output stream associated with this socket.
- * The output stream will be returned even if the socket is not yet
+ * <p>The output stream will be returned even if the socket is not yet
* connected, but operations on that stream will throw IOException until
* the associated socket is connected.
* @return OutputStream
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 8ab67c5..d86ab79 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -1148,7 +1148,6 @@
*
* @see #getSystemService
* @see android.bluetooth.BluetoothAdapter
- * @hide
*/
public static final String BLUETOOTH_SERVICE = "bluetooth";
/**
diff --git a/core/java/android/content/SyncAdapterType.java b/core/java/android/content/SyncAdapterType.java
index 93b61ec..25cbdb1 100644
--- a/core/java/android/content/SyncAdapterType.java
+++ b/core/java/android/content/SyncAdapterType.java
@@ -27,9 +27,12 @@
public class SyncAdapterType implements Parcelable {
public final String authority;
public final String accountType;
- public final boolean userVisible;
+ public final boolean isKey;
+ private final boolean userVisible;
+ private final boolean supportsUploading;
- public SyncAdapterType(String authority, String accountType, boolean userVisible) {
+ public SyncAdapterType(String authority, String accountType, boolean userVisible,
+ boolean supportsUploading) {
if (TextUtils.isEmpty(authority)) {
throw new IllegalArgumentException("the authority must not be empty: " + authority);
}
@@ -39,17 +42,49 @@
this.authority = authority;
this.accountType = accountType;
this.userVisible = userVisible;
+ this.supportsUploading = supportsUploading;
+ this.isKey = false;
+ }
+
+ private SyncAdapterType(String authority, String accountType) {
+ if (TextUtils.isEmpty(authority)) {
+ throw new IllegalArgumentException("the authority must not be empty: " + authority);
+ }
+ if (TextUtils.isEmpty(accountType)) {
+ throw new IllegalArgumentException("the accountType must not be empty: " + accountType);
+ }
+ this.authority = authority;
+ this.accountType = accountType;
+ this.userVisible = true;
+ this.supportsUploading = true;
+ this.isKey = true;
+ }
+
+ public boolean supportsUploading() {
+ if (isKey) {
+ throw new IllegalStateException(
+ "this method is not allowed to be called when this is a key");
+ }
+ return supportsUploading;
+ }
+
+ public boolean isUserVisible() {
+ if (isKey) {
+ throw new IllegalStateException(
+ "this method is not allowed to be called when this is a key");
+ }
+ return userVisible;
}
public static SyncAdapterType newKey(String authority, String accountType) {
- return new SyncAdapterType(authority, accountType, true);
+ return new SyncAdapterType(authority, accountType);
}
public boolean equals(Object o) {
if (o == this) return true;
if (!(o instanceof SyncAdapterType)) return false;
final SyncAdapterType other = (SyncAdapterType)o;
- // don't include userVisible in the equality check
+ // don't include userVisible or supportsUploading in the equality check
return authority.equals(other.authority) && accountType.equals(other.accountType);
}
@@ -57,13 +92,22 @@
int result = 17;
result = 31 * result + authority.hashCode();
result = 31 * result + accountType.hashCode();
- // don't include userVisible in the hash
+ // don't include userVisible or supportsUploading the hash
return result;
}
public String toString() {
- return "SyncAdapterType {name=" + authority + ", type=" + accountType
- + ", userVisible=" + userVisible + "}";
+ if (isKey) {
+ return "SyncAdapterType Key {name=" + authority
+ + ", type=" + accountType
+ + "}";
+ } else {
+ return "SyncAdapterType {name=" + authority
+ + ", type=" + accountType
+ + ", userVisible=" + userVisible
+ + ", supportsUploading=" + supportsUploading
+ + "}";
+ }
}
public int describeContents() {
@@ -71,13 +115,22 @@
}
public void writeToParcel(Parcel dest, int flags) {
+ if (isKey) {
+ throw new IllegalStateException("keys aren't parcelable");
+ }
+
dest.writeString(authority);
dest.writeString(accountType);
dest.writeInt(userVisible ? 1 : 0);
+ dest.writeInt(supportsUploading ? 1 : 0);
}
public SyncAdapterType(Parcel source) {
- this(source.readString(), source.readString(), source.readInt() != 0);
+ this(
+ source.readString(),
+ source.readString(),
+ source.readInt() != 0,
+ source.readInt() != 0);
}
public static final Creator<SyncAdapterType> CREATOR = new Creator<SyncAdapterType>() {
diff --git a/core/java/android/content/SyncAdaptersCache.java b/core/java/android/content/SyncAdaptersCache.java
index c27fd25..7d9f1de 100644
--- a/core/java/android/content/SyncAdaptersCache.java
+++ b/core/java/android/content/SyncAdaptersCache.java
@@ -49,7 +49,10 @@
}
final boolean userVisible =
sa.getBoolean(com.android.internal.R.styleable.SyncAdapter_userVisible, true);
- return new SyncAdapterType(authority, accountType, userVisible);
+ final boolean supportsUploading =
+ sa.getBoolean(com.android.internal.R.styleable.SyncAdapter_supportsUploading,
+ true);
+ return new SyncAdapterType(authority, accountType, userVisible, supportsUploading);
} finally {
sa.recycle();
}
diff --git a/core/java/android/content/SyncManager.java b/core/java/android/content/SyncManager.java
index 34efc51..82cf23f 100644
--- a/core/java/android/content/SyncManager.java
+++ b/core/java/android/content/SyncManager.java
@@ -526,13 +526,6 @@
public void scheduleSync(Account requestedAccount, String requestedAuthority,
Bundle extras, long delay, boolean onlyThoseWithUnkownSyncableState) {
boolean isLoggable = Log.isLoggable(TAG, Log.VERBOSE);
- if (isLoggable) {
- Log.v(TAG, "scheduleSync:"
- + " delay " + delay
- + ", account " + requestedAccount
- + ", authority " + requestedAuthority
- + ", extras " + ((extras == null) ? "(null)" : extras));
- }
if (!isSyncEnabled()) {
if (isLoggable) {
@@ -617,13 +610,27 @@
if (onlyThoseWithUnkownSyncableState && isSyncable >= 0) {
continue;
}
- if (mSyncAdapters.getServiceInfo(SyncAdapterType.newKey(authority, account.type))
- != null) {
+ final RegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapterInfo =
+ mSyncAdapters.getServiceInfo(
+ SyncAdapterType.newKey(authority, account.type));
+ if (syncAdapterInfo != null) {
+ if (!syncAdapterInfo.type.supportsUploading() && uploadOnly) {
+ continue;
+ }
// make this an initialization sync if the isSyncable state is unknown
- Bundle extrasCopy = new Bundle(extras);
+ Bundle extrasCopy = extras;
if (isSyncable < 0) {
+ extrasCopy = new Bundle(extras);
extrasCopy.putBoolean(ContentResolver.SYNC_EXTRAS_INITIALIZE, true);
}
+ if (isLoggable) {
+ Log.v(TAG, "scheduleSync:"
+ + " delay " + delay
+ + ", source " + source
+ + ", account " + account
+ + ", authority " + authority
+ + ", extras " + extrasCopy);
+ }
scheduleSyncOperation(
new SyncOperation(account, source, authority, extrasCopy, delay));
}
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index 6ee92ce..1f640ea 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -1992,8 +1992,9 @@
req.flags = InputConnection.GET_TEXT_WITH_STYLES;
req.hintMaxLines = 10;
req.hintMaxChars = 10000;
- mExtractedText = getCurrentInputConnection().getExtractedText(req,
- InputConnection.GET_EXTRACTED_TEXT_MONITOR);
+ InputConnection ic = getCurrentInputConnection();
+ mExtractedText = ic == null? null
+ : ic.getExtractedText(req, InputConnection.GET_EXTRACTED_TEXT_MONITOR);
final EditorInfo ei = getCurrentInputEditorInfo();
diff --git a/core/java/android/inputmethodservice/KeyboardView.java b/core/java/android/inputmethodservice/KeyboardView.java
index 9e966cd..a141a2a 100755
--- a/core/java/android/inputmethodservice/KeyboardView.java
+++ b/core/java/android/inputmethodservice/KeyboardView.java
@@ -1037,6 +1037,10 @@
me.getX(), me.getY(), me.getMetaState());
result = onModifiedTouchEvent(down);
down.recycle();
+ // If it's an up action, then deliver the up as well.
+ if (me.getAction() == MotionEvent.ACTION_UP) {
+ result = onModifiedTouchEvent(me);
+ }
} else {
// Send an up event for the last pointer
MotionEvent up = MotionEvent.obtain(now, now, MotionEvent.ACTION_UP,
@@ -1067,7 +1071,7 @@
if (mGestureDetector.onTouchEvent(me)) {
showPreview(NOT_A_KEY);
mHandler.removeMessages(MSG_REPEAT);
- mHandler.removeMessages(MSG_LONGPRESS);
+ mHandler.removeMessages(MSG_LONGPRESS);
return true;
}
@@ -1116,7 +1120,7 @@
if (keyIndex == mCurrentKey) {
mCurrentKeyTime += eventTime - mLastMoveTime;
continueLongPress = true;
- } else {
+ } else if (mRepeatKeyIndex == NOT_A_KEY) {
resetMultiTap();
mLastKey = mCurrentKey;
mLastCodeX = mLastX;
@@ -1127,10 +1131,6 @@
mCurrentKeyTime = 0;
}
}
- if (keyIndex != mRepeatKeyIndex) {
- mHandler.removeMessages(MSG_REPEAT);
- mRepeatKeyIndex = NOT_A_KEY;
- }
}
if (!continueLongPress) {
// Cancel old longpress
@@ -1141,7 +1141,7 @@
mHandler.sendMessageDelayed(msg, LONGPRESS_TIMEOUT);
}
}
- showPreview(keyIndex);
+ showPreview(mCurrentKey);
break;
case MotionEvent.ACTION_UP:
diff --git a/core/java/android/net/MobileDataStateTracker.java b/core/java/android/net/MobileDataStateTracker.java
index 85ee1ca..f9effa2 100644
--- a/core/java/android/net/MobileDataStateTracker.java
+++ b/core/java/android/net/MobileDataStateTracker.java
@@ -143,8 +143,9 @@
boolean unavailable = intent.getBooleanExtra(Phone.NETWORK_UNAVAILABLE_KEY,
false);
if (DBG) Log.d(TAG, mApnType + " Received " + intent.getAction() +
- " broadcast - state = " + state + ", unavailable = " + unavailable +
- ", reason = " + (reason == null ? "(unspecified)" : reason));
+ " broadcast - state = " + state + ", oldstate = " + mMobileDataState +
+ ", unavailable = " + unavailable + ", reason = " +
+ (reason == null ? "(unspecified)" : reason));
if (isApnTypeIncluded(apnTypeList)) {
if (mEnabled == false) {
@@ -152,10 +153,12 @@
// we should record the interface name if one's provided. If the user
// turns on this network we will need the interfacename but won't get
// a fresh connected message - TODO fix this..
- if (mInterfaceName == null && state == Phone.DataState.CONNECTED) {
+ if (state == Phone.DataState.CONNECTED) {
+ if (DBG) Log.d(TAG, "replacing old mInterfaceName (" +
+ mInterfaceName + ") with " +
+ intent.getStringExtra(Phone.DATA_IFACE_NAME_KEY) +
+ " for " + mApnType);
mInterfaceName = intent.getStringExtra(Phone.DATA_IFACE_NAME_KEY);
- } else if (state == Phone.DataState.DISCONNECTED) {
- mInterfaceName = null;
}
if (DBG) Log.d(TAG, " dropped - mEnabled = false");
return;
@@ -179,6 +182,8 @@
if (mInterfaceName != null) {
NetworkUtils.resetConnections(mInterfaceName);
}
+ if (DBG) Log.d(TAG, "clearing mInterfaceName for "+ mApnType +
+ " as it DISCONNECTED");
mInterfaceName = null;
mDefaultGatewayAddr = 0;
break;
@@ -301,6 +306,8 @@
switch (setEnableApn(mApnType, true)) {
case Phone.APN_ALREADY_ACTIVE:
mEnabled = true;
+ // need to set self to CONNECTING so the below message is handled.
+ mMobileDataState = Phone.DataState.CONNECTING;
//send out a connected message
Intent intent = new Intent(TelephonyIntents.
ACTION_ANY_DATA_CONNECTION_STATE_CHANGED);
@@ -316,6 +323,12 @@
// no need to do anything - we're already due some status update intents
break;
case Phone.APN_REQUEST_FAILED:
+ if (mPhoneService == null && mApnType == Phone.APN_TYPE_DEFAULT) {
+ // on startup we may try to talk to the phone before it's ready
+ // just leave mEnabled as it is for the default apn.
+ return false;
+ }
+ // else fall through
case Phone.APN_TYPE_NOT_AVAILABLE:
mEnabled = false;
break;
@@ -406,10 +419,11 @@
*/
@Override
public boolean requestRouteToHost(int hostAddress) {
+ if (DBG) {
+ Log.d(TAG, "Requested host route to " + Integer.toHexString(hostAddress) +
+ " for " + mApnType + "(" + mInterfaceName + ")");
+ }
if (mInterfaceName != null && hostAddress != -1) {
- if (DBG) {
- Log.d(TAG, "Requested host route to " + Integer.toHexString(hostAddress));
- }
return NetworkUtils.addHostRoute(mInterfaceName, hostAddress) == 0;
} else {
return false;
diff --git a/core/java/android/pim/ContactsAsyncHelper.java b/core/java/android/pim/ContactsAsyncHelper.java
index a21281e..342d208 100644
--- a/core/java/android/pim/ContactsAsyncHelper.java
+++ b/core/java/android/pim/ContactsAsyncHelper.java
@@ -27,8 +27,7 @@
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
-import android.provider.Contacts;
-import android.provider.Contacts.People;
+import android.provider.ContactsContract.Contacts;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
@@ -39,35 +38,35 @@
* Helper class for async access of images.
*/
public class ContactsAsyncHelper extends Handler {
-
+
private static final boolean DBG = false;
private static final String LOG_TAG = "ContactsAsyncHelper";
-
+
/**
* Interface for a WorkerHandler result return.
*/
public interface OnImageLoadCompleteListener {
/**
* Called when the image load is complete.
- *
+ *
* @param imagePresent true if an image was found
- */
+ */
public void onImageLoadComplete(int token, Object cookie, ImageView iView,
boolean imagePresent);
}
-
+
// constants
private static final int EVENT_LOAD_IMAGE = 1;
private static final int DEFAULT_TOKEN = -1;
-
+
// static objects
private static Handler sThreadHandler;
private static ContactsAsyncHelper sInstance;
-
+
static {
sInstance = new ContactsAsyncHelper();
}
-
+
private static final class WorkerArgs {
public Context context;
public ImageView view;
@@ -78,12 +77,12 @@
public OnImageLoadCompleteListener listener;
public CallerInfo info;
}
-
+
/**
- * public inner class to help out the ContactsAsyncHelper callers
- * with tracking the state of the CallerInfo Queries and image
+ * public inner class to help out the ContactsAsyncHelper callers
+ * with tracking the state of the CallerInfo Queries and image
* loading.
- *
+ *
* Logic contained herein is used to remove the race conditions
* that exist as the CallerInfo queries run and mix with the image
* loads, which then mix with the Phone state changes.
@@ -94,11 +93,11 @@
public static final int DISPLAY_UNDEFINED = 0;
public static final int DISPLAY_IMAGE = -1;
public static final int DISPLAY_DEFAULT = -2;
-
+
// State of the image on the imageview.
private CallerInfo mCurrentCallerInfo;
private int displayMode;
-
+
public ImageTracker() {
mCurrentCallerInfo = null;
displayMode = DISPLAY_UNDEFINED;
@@ -107,17 +106,17 @@
/**
* Used to see if the requested call / connection has a
* different caller attached to it than the one we currently
- * have in the CallCard.
+ * have in the CallCard.
*/
public boolean isDifferentImageRequest(CallerInfo ci) {
// note, since the connections are around for the lifetime of the
- // call, and the CallerInfo-related items as well, we can
+ // call, and the CallerInfo-related items as well, we can
// definitely use a simple != comparison.
return (mCurrentCallerInfo != ci);
}
-
+
public boolean isDifferentImageRequest(Connection connection) {
- // if the connection does not exist, see if the
+ // if the connection does not exist, see if the
// mCurrentCallerInfo is also null to match.
if (connection == null) {
if (DBG) Log.d(LOG_TAG, "isDifferentImageRequest: connection is null");
@@ -133,57 +132,58 @@
}
return runQuery;
}
-
+
/**
- * Simple setter for the CallerInfo object.
+ * Simple setter for the CallerInfo object.
*/
public void setPhotoRequest(CallerInfo ci) {
- mCurrentCallerInfo = ci;
+ mCurrentCallerInfo = ci;
}
-
+
/**
- * Convenience method used to retrieve the URI
- * representing the Photo file recorded in the attached
- * CallerInfo Object.
+ * Convenience method used to retrieve the URI
+ * representing the Photo file recorded in the attached
+ * CallerInfo Object.
*/
public Uri getPhotoUri() {
if (mCurrentCallerInfo != null) {
- return ContentUris.withAppendedId(People.CONTENT_URI,
+ return ContentUris.withAppendedId(Contacts.CONTENT_URI,
mCurrentCallerInfo.person_id);
}
- return null;
+ return null;
}
-
+
/**
- * Simple setter for the Photo state.
+ * Simple setter for the Photo state.
*/
public void setPhotoState(int state) {
displayMode = state;
}
-
+
/**
- * Simple getter for the Photo state.
+ * Simple getter for the Photo state.
*/
public int getPhotoState() {
return displayMode;
}
}
-
+
/**
- * Thread worker class that handles the task of opening the stream and loading
+ * Thread worker class that handles the task of opening the stream and loading
* the images.
*/
private class WorkerHandler extends Handler {
public WorkerHandler(Looper looper) {
super(looper);
}
-
+
+ @Override
public void handleMessage(Message msg) {
WorkerArgs args = (WorkerArgs) msg.obj;
-
+
switch (msg.arg1) {
case EVENT_LOAD_IMAGE:
- InputStream inputStream = Contacts.People.openContactPhotoInputStream(
+ InputStream inputStream = Contacts.openContactPhotoInputStream(
args.context.getContentResolver(), args.uri);
if (inputStream != null) {
args.result = Drawable.createFromStream(inputStream, args.uri.toString());
@@ -192,22 +192,22 @@
" token: " + msg.what + " image URI: " + args.uri);
} else {
args.result = null;
- if (DBG) Log.d(LOG_TAG, "Problem with image: " + msg.arg1 +
- " token: " + msg.what + " image URI: " + args.uri +
+ if (DBG) Log.d(LOG_TAG, "Problem with image: " + msg.arg1 +
+ " token: " + msg.what + " image URI: " + args.uri +
", using default image.");
}
break;
default:
}
-
- // send the reply to the enclosing class.
+
+ // send the reply to the enclosing class.
Message reply = ContactsAsyncHelper.this.obtainMessage(msg.what);
reply.arg1 = msg.arg1;
reply.obj = msg.obj;
reply.sendToTarget();
}
}
-
+
/**
* Private constructor for static class
*/
@@ -216,14 +216,14 @@
thread.start();
sThreadHandler = new WorkerHandler(thread.getLooper());
}
-
+
/**
* Convenience method for calls that do not want to deal with listeners and tokens.
*/
- public static final void updateImageViewWithContactPhotoAsync(Context context,
+ public static final void updateImageViewWithContactPhotoAsync(Context context,
ImageView imageView, Uri person, int placeholderImageResource) {
// Added additional Cookie field in the callee.
- updateImageViewWithContactPhotoAsync (null, DEFAULT_TOKEN, null, null, context,
+ updateImageViewWithContactPhotoAsync (null, DEFAULT_TOKEN, null, null, context,
imageView, person, placeholderImageResource);
}
@@ -231,24 +231,24 @@
* Convenience method for calls that do not want to deal with listeners and tokens, but have
* a CallerInfo object to cache the image to.
*/
- public static final void updateImageViewWithContactPhotoAsync(CallerInfo info, Context context,
+ public static final void updateImageViewWithContactPhotoAsync(CallerInfo info, Context context,
ImageView imageView, Uri person, int placeholderImageResource) {
// Added additional Cookie field in the callee.
- updateImageViewWithContactPhotoAsync (info, DEFAULT_TOKEN, null, null, context,
+ updateImageViewWithContactPhotoAsync (info, DEFAULT_TOKEN, null, null, context,
imageView, person, placeholderImageResource);
}
-
+
/**
* Start an image load, attach the result to the specified CallerInfo object.
* Note, when the query is started, we make the ImageView INVISIBLE if the
* placeholderImageResource value is -1. When we're given a valid (!= -1)
* placeholderImageResource value, we make sure the image is visible.
*/
- public static final void updateImageViewWithContactPhotoAsync(CallerInfo info, int token,
- OnImageLoadCompleteListener listener, Object cookie, Context context,
+ public static final void updateImageViewWithContactPhotoAsync(CallerInfo info, int token,
+ OnImageLoadCompleteListener listener, Object cookie, Context context,
ImageView imageView, Uri person, int placeholderImageResource) {
-
+
// in case the source caller info is null, the URI will be null as well.
// just update using the placeholder image in this case.
if (person == null) {
@@ -257,10 +257,10 @@
imageView.setImageResource(placeholderImageResource);
return;
}
-
+
// Added additional Cookie field in the callee to handle arguments
// sent to the callback function.
-
+
// setup arguments
WorkerArgs args = new WorkerArgs();
args.cookie = cookie;
@@ -270,15 +270,15 @@
args.defaultResource = placeholderImageResource;
args.listener = listener;
args.info = info;
-
+
// setup message arguments
Message msg = sThreadHandler.obtainMessage(token);
msg.arg1 = EVENT_LOAD_IMAGE;
msg.obj = args;
-
- if (DBG) Log.d(LOG_TAG, "Begin loading image: " + args.uri +
+
+ if (DBG) Log.d(LOG_TAG, "Begin loading image: " + args.uri +
", displaying default image for now.");
-
+
// set the default image first, when the query is complete, we will
// replace the image with the correct one.
if (placeholderImageResource != -1) {
@@ -287,11 +287,11 @@
} else {
imageView.setVisibility(View.INVISIBLE);
}
-
+
// notify the thread to begin working
sThreadHandler.sendMessage(msg);
}
-
+
/**
* Called when loading is done.
*/
@@ -316,21 +316,21 @@
args.view.setVisibility(View.VISIBLE);
args.view.setImageResource(args.defaultResource);
}
-
+
// Note that the data is cached.
if (args.info != null) {
args.info.isCachedPhotoCurrent = true;
}
-
+
// notify the listener if it is there.
if (args.listener != null) {
- if (DBG) Log.d(LOG_TAG, "Notifying listener: " + args.listener.toString() +
+ if (DBG) Log.d(LOG_TAG, "Notifying listener: " + args.listener.toString() +
" image: " + args.uri + " completed");
args.listener.onImageLoadComplete(msg.what, args.cookie, args.view,
imagePresent);
}
break;
- default:
+ default:
}
}
}
diff --git a/core/java/android/preference/CheckBoxPreference.java b/core/java/android/preference/CheckBoxPreference.java
index cf5664c..f16a7e4 100644
--- a/core/java/android/preference/CheckBoxPreference.java
+++ b/core/java/android/preference/CheckBoxPreference.java
@@ -149,14 +149,12 @@
* @param checked The checked state.
*/
public void setChecked(boolean checked) {
-
- mChecked = checked;
-
- persistBoolean(checked);
-
- notifyDependencyChange(shouldDisableDependents());
-
- notifyChanged();
+ if (mChecked != checked) {
+ mChecked = checked;
+ persistBoolean(checked);
+ notifyDependencyChange(shouldDisableDependents());
+ notifyChanged();
+ }
}
/**
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index 09d0327..18b666c 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -19,12 +19,20 @@
import android.accounts.Account;
import android.content.ContentProviderClient;
import android.content.ContentProviderOperation;
+import android.content.ContentResolver;
+import android.content.ContentUris;
+import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
+import android.database.Cursor;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.RemoteException;
import android.provider.ContactsContract.CommonDataKinds.GroupMembership;
+import android.text.TextUtils;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
/**
* The contract between the contacts provider and applications. Contains definitions
@@ -296,17 +304,65 @@
* The directory twig for this sub-table
*/
public static final String CONTENT_DIRECTORY = "suggestions";
+ }
- /**
- * An optional query parameter that can be supplied to limit the number of returned
- * suggestions.
- * <p>
- * Type: INTEGER
- *
- * @deprecated Please use the "limit" parameter
- */
- @Deprecated
- public static final String MAX_SUGGESTIONS = "max_suggestions";
+ /**
+ * Returns a URI that can be used to retrieve the contact's default photo.
+ *
+ * @param contactUri the contact whose photo should be used
+ */
+ public static Uri getPhotoUri(ContentResolver cr, Uri contactUri) {
+
+ // TODO remove try/catch block as soon as eclair-dev is merged in eclair
+ try {
+ long photoId = -1;
+ Cursor cursor = cr.query(contactUri, new String[] {Contacts.PHOTO_ID},
+ null, null, null);
+ try {
+ if (!cursor.moveToNext()) {
+ return null;
+ }
+
+ if (cursor.isNull(0)) {
+ return null;
+ }
+
+ photoId = cursor.getLong(0);
+ } finally {
+ cursor.close();
+ }
+
+ return ContentUris.withAppendedId(ContactsContract.Data.CONTENT_URI, photoId);
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ /**
+ * Opens an InputStream for the person's default photo and returns the
+ * photo as a Bitmap stream.
+ *
+ * @param contactUri the contact whose photo should be used
+ */
+ public static InputStream openContactPhotoInputStream(ContentResolver cr, Uri contactUri) {
+ Uri photoUri = getPhotoUri(cr, contactUri);
+ if (photoUri == null) {
+ return null;
+ }
+ Cursor cursor = cr.query(photoUri,
+ new String[]{ContactsContract.CommonDataKinds.Photo.PHOTO}, null, null, null);
+ try {
+ if (!cursor.moveToNext()) {
+ return null;
+ }
+ byte[] data = cursor.getBlob(0);
+ if (data == null) {
+ return null;
+ }
+ return new ByteArrayInputStream(data);
+ } finally {
+ cursor.close();
+ }
}
}
@@ -541,13 +597,33 @@
public static final String CONTENT_TYPE = "vnd.android.cursor.dir/data";
}
+ private interface PhoneLookupColumns {
+ /**
+ * The phone number as the user entered it.
+ * <P>Type: TEXT</P>
+ */
+ public static final String NUMBER = "number";
+
+ /**
+ * The type of phone number, for example Home or Work.
+ * <P>Type: INTEGER</P>
+ */
+ public static final String TYPE = "type";
+
+ /**
+ * The user defined label for the phone number.
+ * <P>Type: TEXT</P>
+ */
+ public static final String LABEL = "label";
+ }
+
/**
* A table that represents the result of looking up a phone number, for
- * example for caller ID. The table joins that data row for the phone number
- * with the raw contact that owns the number. To perform a lookup you must
- * append the number you want to find to {@link #CONTENT_FILTER_URI}.
+ * example for caller ID. To perform a lookup you must append the number you
+ * want to find to {@link #CONTENT_FILTER_URI}.
*/
- public static final class PhoneLookup implements BaseColumns, DataColumns, ContactsColumns {
+ public static final class PhoneLookup implements BaseColumns, PhoneLookupColumns,
+ ContactsColumns, ContactOptionsColumns {
/**
* This utility class cannot be instantiated
*/
@@ -881,6 +957,32 @@
* <P>Type: TEXT</P>
*/
public static final String NUMBER = DATA;
+
+ public static final CharSequence getDisplayLabel(Context context, int type,
+ CharSequence label, CharSequence[] labelArray) {
+ CharSequence display = "";
+
+ if (type != Phone.TYPE_CUSTOM) {
+ CharSequence[] labels = labelArray != null? labelArray
+ : context.getResources().getTextArray(
+ com.android.internal.R.array.phoneTypes);
+ try {
+ display = labels[type - 1];
+ } catch (ArrayIndexOutOfBoundsException e) {
+ display = labels[Phone.TYPE_CUSTOM];
+ }
+ } else {
+ if (!TextUtils.isEmpty(label)) {
+ display = label;
+ }
+ }
+ return display;
+ }
+
+ public static final CharSequence getDisplayLabel(Context context, int type,
+ CharSequence label) {
+ return getDisplayLabel(context, type, label, null);
+ }
}
/**
@@ -1520,9 +1622,8 @@
public static final String SHOULD_SYNC = "should_sync";
/**
- * Flag indicating if the contacts from this source, but that don't have
- * any specific {@link GroupMembership} entries should be visible in any
- * user interface.
+ * Flag indicating if contacts without any {@link GroupMembership}
+ * entries should be visible in any user interface.
* <p>
* Type: INTEGER (boolean)
*/
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 1861095..84e07f0 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -3390,6 +3390,13 @@
"google_calendar_sync_window_days";
/**
+ * How often to update the calendar sync window.
+ * The window will be advanced every n days.
+ */
+ public static final String GOOGLE_CALENDAR_SYNC_WINDOW_UPDATE_DAYS =
+ "google_calendar_sync_window_update_days";
+
+ /**
* @deprecated
* @hide
*/
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index 9ec1013..5cecac3 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -246,7 +246,7 @@
};
/**
- * Sets the display metrics used to provide canva's width/height in comaptibility mode.
+ * Sets the display metrics used to provide canva's width/height in compatibility mode.
*/
void setCompatibleDisplayMetrics(DisplayMetrics metrics, Translator translator) {
mCompatibleDisplayMetrics = metrics;
@@ -275,7 +275,8 @@
public native void clear();
/** draw into a surface */
- public Canvas lockCanvas(Rect dirty) throws OutOfResourcesException {
+ public Canvas lockCanvas(Rect dirty) throws OutOfResourcesException, IllegalArgumentException
+ {
/* the dirty rectangle may be expanded to the surface's size, if
* for instance it has been resized or if the bits were lost, since
* the last call.
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index f4e9900..ea08f33 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -344,6 +344,12 @@
public final int TRANSIT_TASK_TO_FRONT = 10;
/** A window in an existing task is being put below all other tasks. */
public final int TRANSIT_TASK_TO_BACK = 11;
+ /** A window in a new activity is being opened on top of an existing one,
+ * and both are on top of the wallpaper. */
+ public final int TRANSIT_WALLPAPER_ACTIVITY_OPEN = 12;
+ /** The window in the top-most activity is being closed to reveal the
+ * previous activity, and both are on top of he wallpaper. */
+ public final int TRANSIT_WALLPAPER_ACTIVITY_CLOSE = 13;
/** Screen turned off because of power button */
public final int OFF_BECAUSE_OF_USER = 1;
diff --git a/core/java/android/widget/AbsSeekBar.java b/core/java/android/widget/AbsSeekBar.java
index f92eb99..2a0e5e5 100644
--- a/core/java/android/widget/AbsSeekBar.java
+++ b/core/java/android/widget/AbsSeekBar.java
@@ -64,10 +64,10 @@
TypedArray a = context.obtainStyledAttributes(attrs,
com.android.internal.R.styleable.SeekBar, defStyle, 0);
Drawable thumb = a.getDrawable(com.android.internal.R.styleable.SeekBar_thumb);
- setThumb(thumb);
+ setThumb(thumb); // will guess mThumbOffset if thumb != null...
+ // ...but allow layout to override this
int thumbOffset =
- a.getDimensionPixelOffset(com.android.internal.R.styleable.SeekBar_thumbOffset, 0);
- setThumbOffset(thumbOffset);
+ a.getDimensionPixelOffset(com.android.internal.R.styleable.SeekBar_thumbOffset, getThumbOffset());
a.recycle();
a = context.obtainStyledAttributes(attrs,
@@ -77,13 +77,21 @@
}
/**
- * Sets the thumb that will be drawn at the end of the progress meter within the SeekBar
+ * Sets the thumb that will be drawn at the end of the progress meter within the SeekBar.
+ * <p>
+ * If the thumb is a valid drawable (i.e. not null), half its width will be
+ * used as the new thumb offset (@see #setThumbOffset(int)).
*
* @param thumb Drawable representing the thumb
*/
public void setThumb(Drawable thumb) {
if (thumb != null) {
thumb.setCallback(this);
+
+ // Assuming the thumb drawable is symmetric, set the thumb offset
+ // such that the thumb will hang halfway off either edge of the
+ // progress bar.
+ mThumbOffset = (int)thumb.getIntrinsicWidth() / 2;
}
mThumb = thumb;
invalidate();
diff --git a/core/java/android/widget/VideoView.java b/core/java/android/widget/VideoView.java
index e60ff25..549f984 100644
--- a/core/java/android/widget/VideoView.java
+++ b/core/java/android/widget/VideoView.java
@@ -267,12 +267,17 @@
// Get the capabilities of the player for this stream
Metadata data = mp.getMetadata(MediaPlayer.METADATA_ALL,
MediaPlayer.BYPASS_METADATA_FILTER);
- mCanPause = !data.has(Metadata.PAUSE_AVAILABLE)
- || data.getBoolean(Metadata.PAUSE_AVAILABLE);
- mCanSeekBack = !data.has(Metadata.SEEK_BACKWARD_AVAILABLE)
- || data.getBoolean(Metadata.SEEK_BACKWARD_AVAILABLE);
- mCanSeekForward = !data.has(Metadata.SEEK_FORWARD_AVAILABLE)
- || data.getBoolean(Metadata.SEEK_FORWARD_AVAILABLE);
+
+ if (data != null) {
+ mCanPause = !data.has(Metadata.PAUSE_AVAILABLE)
+ || data.getBoolean(Metadata.PAUSE_AVAILABLE);
+ mCanSeekBack = !data.has(Metadata.SEEK_BACKWARD_AVAILABLE)
+ || data.getBoolean(Metadata.SEEK_BACKWARD_AVAILABLE);
+ mCanSeekForward = !data.has(Metadata.SEEK_FORWARD_AVAILABLE)
+ || data.getBoolean(Metadata.SEEK_FORWARD_AVAILABLE);
+ } else {
+ mCanPause = mCanSeekForward = mCanSeekForward = true;
+ }
if (mOnPreparedListener != null) {
mOnPreparedListener.onPrepared(mMediaPlayer);
diff --git a/core/java/com/android/internal/widget/ContactHeaderWidget.java b/core/java/com/android/internal/widget/ContactHeaderWidget.java
index 30349b3..70f2779 100644
--- a/core/java/com/android/internal/widget/ContactHeaderWidget.java
+++ b/core/java/com/android/internal/widget/ContactHeaderWidget.java
@@ -116,7 +116,7 @@
//Projection used for looking up contact id from phone number
protected static final String[] PHONE_LOOKUP_PROJECTION = new String[] {
- RawContacts.CONTACT_ID,
+ PhoneLookup._ID,
};
protected static final int PHONE_LOOKUP_CONTACT_ID_COLUMN_INDEX = 0;
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 2e73372..f61e247 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -525,6 +525,7 @@
char dexoptFlagsBuf[PROPERTY_VALUE_MAX];
char enableAssertBuf[sizeof("-ea:")-1 + PROPERTY_VALUE_MAX];
char jniOptsBuf[sizeof("-Xjniopts:")-1 + PROPERTY_VALUE_MAX];
+ char heapsizeOptsBuf[sizeof("-Xmx")-1 + PROPERTY_VALUE_MAX];
char* stackTraceFile = NULL;
bool checkJni = false;
bool checkDexSum = false;
@@ -597,16 +598,10 @@
mOptions.add(opt);
//options[curOpt++].optionString = "-verbose:class";
-#ifdef CUSTOM_RUNTIME_HEAP_MAX
-#define __make_max_heap_opt(val) #val
-#define _make_max_heap_opt(val) "-Xmx" __make_max_heap_opt(val)
- opt.optionString = _make_max_heap_opt(CUSTOM_RUNTIME_HEAP_MAX);
-#undef __make_max_heap_opt
-#undef _make_max_heap_opt
-#else
- /* limit memory use to 16MB */
- opt.optionString = "-Xmx16m";
-#endif
+ strcpy(heapsizeOptsBuf, "-Xmx");
+ property_get("dalvik.vm.heapsize", heapsizeOptsBuf+4, "16m");
+ //LOGI("Heap size: %s", heapsizeOptsBuf);
+ opt.optionString = heapsizeOptsBuf;
mOptions.add(opt);
/*
diff --git a/core/res/res/anim/wallpaper_activity_close_enter.xml b/core/res/res/anim/wallpaper_activity_close_enter.xml
new file mode 100644
index 0000000..fc6e332
--- /dev/null
+++ b/core/res/res/anim/wallpaper_activity_close_enter.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/res/anim/options_panel_exit.xml
+**
+** Copyright 2007, 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.
+*/
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:interpolator="@anim/decelerate_interpolator"
+ android:zAdjustment="top">
+ <scale android:fromXScale="2.0" android:toXScale="1.0"
+ android:fromYScale="2.0" android:toYScale="1.0"
+ android:pivotX="50%" android:pivotY="50%"
+ android:duration="@android:integer/config_mediumAnimTime" />
+ <translate android:fromXDelta="-150%" android:toXDelta="0"
+ android:duration="@android:integer/config_mediumAnimTime"/>
+</set>
diff --git a/core/res/res/anim/wallpaper_activity_close_exit.xml b/core/res/res/anim/wallpaper_activity_close_exit.xml
new file mode 100644
index 0000000..edd00fd
--- /dev/null
+++ b/core/res/res/anim/wallpaper_activity_close_exit.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/res/anim/options_panel_exit.xml
+**
+** Copyright 2007, 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.
+*/
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:interpolator="@anim/accelerate_interpolator">
+ <scale android:fromXScale="1.0" android:toXScale=".5"
+ android:fromYScale="1.0" android:toYScale=".5"
+ android:pivotX="50%" android:pivotY="50%"
+ android:duration="@android:integer/config_mediumAnimTime" />
+ <translate android:fromXDelta="0%" android:toXDelta="100%"
+ android:duration="@android:integer/config_mediumAnimTime"/>
+</set>
diff --git a/core/res/res/anim/wallpaper_activity_open_enter.xml b/core/res/res/anim/wallpaper_activity_open_enter.xml
new file mode 100644
index 0000000..5b44d97
--- /dev/null
+++ b/core/res/res/anim/wallpaper_activity_open_enter.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/res/anim/options_panel_exit.xml
+**
+** Copyright 2007, 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.
+*/
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:interpolator="@anim/decelerate_interpolator">
+ <scale android:fromXScale=".5" android:toXScale="1.0"
+ android:fromYScale=".5" android:toYScale="1.0"
+ android:pivotX="50%" android:pivotY="50%"
+ android:duration="@android:integer/config_mediumAnimTime" />
+ <translate android:fromXDelta="100%" android:toXDelta="0"
+ android:duration="@android:integer/config_mediumAnimTime"/>
+</set>
diff --git a/core/res/res/anim/wallpaper_activity_open_exit.xml b/core/res/res/anim/wallpaper_activity_open_exit.xml
new file mode 100644
index 0000000..fa39bee
--- /dev/null
+++ b/core/res/res/anim/wallpaper_activity_open_exit.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/res/anim/options_panel_exit.xml
+**
+** Copyright 2007, 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.
+*/
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:interpolator="@anim/accelerate_interpolator"
+ android:zAdjustment="top">
+ <scale android:fromXScale="1.0" android:toXScale="2.0"
+ android:fromYScale="1.0" android:toYScale="2.0"
+ android:pivotX="50%" android:pivotY="50%"
+ android:duration="@android:integer/config_mediumAnimTime" />
+ <translate android:fromXDelta="0" android:toXDelta="-150%"
+ android:duration="@android:integer/config_mediumAnimTime"/>
+</set>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index eee87e6..729b1db 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -937,18 +937,68 @@
<attr name="windowShowAnimation" format="reference" />
<!-- The animation used when a window is going from VISIBLE to INVISIBLE. -->
<attr name="windowHideAnimation" format="reference" />
+
+ <!-- When opening a new activity, this is the animation that is
+ run on the next activity (which is entering the screen). -->
<attr name="activityOpenEnterAnimation" format="reference" />
+ <!-- When opening a new activity, this is the animation that is
+ run on the previous activity (which is exiting the screen). -->
<attr name="activityOpenExitAnimation" format="reference" />
+ <!-- When closing the current activity, this is the animation that is
+ run on the next activity (which is entering the screen). -->
<attr name="activityCloseEnterAnimation" format="reference" />
+ <!-- When closing the current activity, this is the animation that is
+ run on the current activity (which is exiting the screen). -->
<attr name="activityCloseExitAnimation" format="reference" />
+ <!-- When opening an activity in a new task, this is the animation that is
+ run on the activity of the new task (which is entering the screen). -->
<attr name="taskOpenEnterAnimation" format="reference" />
+ <!-- When opening an activity in a new task, this is the animation that is
+ run on the activity of the old task (which is exiting the screen). -->
<attr name="taskOpenExitAnimation" format="reference" />
+ <!-- When closing the last activity of a task, this is the animation that is
+ run on the activity of the next task (which is entering the screen). -->
<attr name="taskCloseEnterAnimation" format="reference" />
+ <!-- When opening an activity in a new task, this is the animation that is
+ run on the activity of the old task (which is exiting the screen). -->
<attr name="taskCloseExitAnimation" format="reference" />
+ <!-- When bringing an existing task to the foreground, this is the
+ animation that is run on the top activity of the task being brought
+ to the foreground (which is entering the screen). -->
<attr name="taskToFrontEnterAnimation" format="reference" />
+ <!-- When bringing an existing task to the foreground, this is the
+ animation that is run on the current foreground activity
+ (which is exiting the screen). -->
<attr name="taskToFrontExitAnimation" format="reference" />
+ <!-- When sending the current task to the background, this is the
+ animation that is run on the top activity of the task behind
+ it (which is entering the screen). -->
<attr name="taskToBackEnterAnimation" format="reference" />
+ <!-- When sending the current task to the background, this is the
+ animation that is run on the top activity of the current task
+ (which is exiting the screen). -->
<attr name="taskToBackExitAnimation" format="reference" />
+
+ <!-- When opening a new activity that is on top of the wallpaper
+ when the current activity is also on top of the wallpaper,
+ this is the animation that is run on the new activity
+ (which is entering the screen). -->
+ <attr name="wallpaperActivityOpenEnterAnimation" format="reference" />
+ <!-- When opening a new activity that is on top of the wallpaper
+ when the current activity is also on top of the wallpaper,
+ this is the animation that is run on the current activity
+ (which is exiting the screen). -->
+ <attr name="wallpaperActivityOpenExitAnimation" format="reference" />
+ <!-- When closing a foreround activity that is on top of the wallpaper
+ when the previous activity is also on top of the wallpaper,
+ this is the animation that is run on the previous activity
+ (which is entering the screen). -->
+ <attr name="wallpaperActivityCloseEnterAnimation" format="reference" />
+ <!-- When closing a foreround activity that is on top of the wallpaper
+ when the previous activity is also on top of the wallpaper,
+ this is the animation that is run on the current activity
+ (which is exiting the screen). -->
+ <attr name="wallpaperActivityCloseExitAnimation" format="reference" />
</declare-styleable>
<!-- ============================= -->
@@ -3360,6 +3410,7 @@
<attr name="contentAuthority" format="string"/>
<attr name="accountType"/>
<attr name="userVisible" format="boolean"/>
+ <attr name="supportsUploading" format="boolean"/>
</declare-styleable>
<!-- =============================== -->
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 60b492a..4bc376b 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1150,9 +1150,14 @@
<public type="attr" name="contentAuthority" />
<public type="attr" name="userVisible" />
<public type="attr" name="windowShowWallpaper" />
+ <public type="attr" name="wallpaperActivityOpenEnterAnimation" />
+ <public type="attr" name="wallpaperActivityOpenExitAnimation" />
+ <public type="attr" name="wallpaperActivityCloseEnterAnimation" />
+ <public type="attr" name="wallpaperActivityCloseExitAnimation" />
<public type="style" name="Theme.Wallpaper" />
<public type="style" name="Theme.Wallpaper.NoTitleBar" />
<public type="style" name="Theme.Wallpaper.NoTitleBar.Fullscreen" />
+ <public type="attr" name="supportsUploading" />
</resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 22f9136..c14ecc0 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1350,7 +1350,7 @@
<!-- When the battery is low, this is the label of the button to go to the
power usage activity to find out what drained the battery. -->
- <string name="battery_low_why">Why?</string>
+ <string name="battery_low_why">Battery use</string>
<!-- Title of the alert when something went wrong in the factory test. -->
<string name="factorytest_failed">Factory test failed</string>
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 4aa4210..10d2093 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -66,6 +66,10 @@
<item name="taskToFrontExitAnimation">@anim/task_open_exit</item>
<item name="taskToBackEnterAnimation">@anim/task_close_enter</item>
<item name="taskToBackExitAnimation">@anim/task_close_exit</item>
+ <item name="wallpaperActivityOpenEnterAnimation">@anim/wallpaper_activity_open_enter</item>
+ <item name="wallpaperActivityOpenExitAnimation">@anim/wallpaper_activity_open_exit</item>
+ <item name="wallpaperActivityCloseEnterAnimation">@anim/wallpaper_activity_close_enter</item>
+ <item name="wallpaperActivityCloseExitAnimation">@anim/wallpaper_activity_close_exit</item>
</style>
<!-- Standard animations for a non-full-screen window or activity. -->
@@ -130,8 +134,7 @@
<item name="windowExitAnimation">@anim/slide_out_down</item>
</style>
- <!-- Window animations that are applied to input method overlay windows.
- {@hide Pending API council approval} -->
+ <!-- Window animations that are applied to input method overlay windows. -->
<style name="Animation.InputMethod">
<item name="windowEnterAnimation">@anim/input_method_enter</item>
<item name="windowExitAnimation">@anim/input_method_exit</item>
@@ -151,8 +154,7 @@
<item name="windowExitAnimation">@anim/search_bar_exit</item>
</style>
- <!-- Window animations that are applied to the zoom buttons overlay window.
- {@hide Pending API council approval} -->
+ <!-- Window animations that are applied to the zoom buttons overlay window. -->
<style name="Animation.ZoomButtons">
<item name="windowEnterAnimation">@anim/fade_in</item>
<item name="windowExitAnimation">@anim/fade_out</item>
diff --git a/graphics/java/android/renderscript/Type.java b/graphics/java/android/renderscript/Type.java
index 30b952d..b6b7adf 100644
--- a/graphics/java/android/renderscript/Type.java
+++ b/graphics/java/android/renderscript/Type.java
@@ -18,10 +18,6 @@
import java.lang.reflect.Field;
-import android.renderscript.Element;
-import android.util.Config;
-import android.util.Log;
-
/**
* @hide
*
@@ -113,9 +109,7 @@
public void add(Dimension d, int value) {
if(mEntries.length >= mEntryCount) {
Entry[] en = new Entry[mEntryCount + 8];
- for(int ct=0; ct < mEntries.length; ct++) {
- en[ct] = mEntries[ct];
- }
+ System.arraycopy(mEntries, 0, en, 0, mEntries.length);
mEntries = en;
}
mEntries[mEntryCount] = new Entry();
diff --git a/include/binder/MemoryHeapBase.h b/include/binder/MemoryHeapBase.h
index 83c7283..435540e 100644
--- a/include/binder/MemoryHeapBase.h
+++ b/include/binder/MemoryHeapBase.h
@@ -42,7 +42,7 @@
* maps the memory referenced by fd. but DOESN'T take ownership
* of the filedescriptor (it makes a copy with dup()
*/
- MemoryHeapBase(int fd, size_t size, uint32_t flags = 0);
+ MemoryHeapBase(int fd, size_t size, uint32_t flags = 0, uint32_t offset = 0);
/*
* maps memory from the given device
@@ -82,7 +82,7 @@
int flags = 0, const char* device = NULL);
private:
- status_t mapfd(int fd, size_t size);
+ status_t mapfd(int fd, size_t size, uint32_t offset = 0);
int mFD;
size_t mSize;
diff --git a/include/media/stagefright/MetaData.h b/include/media/stagefright/MetaData.h
index 2d5b8d8..be60565 100644
--- a/include/media/stagefright/MetaData.h
+++ b/include/media/stagefright/MetaData.h
@@ -28,23 +28,24 @@
namespace android {
enum {
- kKeyMIMEType = 'mime',
- kKeyWidth = 'widt',
- kKeyHeight = 'heig',
- kKeyChannelCount = '#chn',
- kKeySampleRate = 'srte',
- kKeyBitRate = 'brte',
- kKeyESDS = 'esds',
- kKeyAVCC = 'avcc',
- kKeyTimeUnits = '#tim',
- kKeyTimeScale = 'scal',
- kKeyNeedsNALFraming = 'NALf',
- kKeyIsSyncFrame = 'sync',
- kKeyDuration = 'dura',
- kKeyColorFormat = 'colf',
- kKeyPlatformPrivate = 'priv',
- kKeyDecoderComponent = 'decC',
- kKeyBufferID = 'bfID',
+ kKeyMIMEType = 'mime',
+ kKeyWidth = 'widt',
+ kKeyHeight = 'heig',
+ kKeyChannelCount = '#chn',
+ kKeySampleRate = 'srte',
+ kKeyBitRate = 'brte',
+ kKeyESDS = 'esds',
+ kKeyAVCC = 'avcc',
+ kKeyTimeUnits = '#tim',
+ kKeyTimeScale = 'scal',
+ kKeyWantsNALFragments = 'NALf',
+ kKeyIsSyncFrame = 'sync',
+ kKeyDuration = 'dura',
+ kKeyColorFormat = 'colf',
+ kKeyPlatformPrivate = 'priv',
+ kKeyDecoderComponent = 'decC',
+ kKeyBufferID = 'bfID',
+ kKeyCompressedSize = 'cmpS',
};
enum {
diff --git a/include/media/stagefright/OMXCodec.h b/include/media/stagefright/OMXCodec.h
index d4ae349..0b94118 100644
--- a/include/media/stagefright/OMXCodec.h
+++ b/include/media/stagefright/OMXCodec.h
@@ -79,7 +79,7 @@
enum Quirks {
kNeedsFlushBeforeDisable = 1,
- kWantsRawNALFrames = 2,
+ kWantsNALFragments = 2,
kRequiresLoadedToIdleAfterAllocation = 4,
kRequiresAllocateBufferOnInputPorts = 8,
};
@@ -108,7 +108,7 @@
Vector<CodecSpecificData *> mCodecSpecificData;
size_t mCodecSpecificDataIndex;
- sp<MemoryDealer> mDealer;
+ sp<MemoryDealer> mDealer[2];
State mState;
Vector<BufferInfo> mPortBuffers[2];
@@ -148,6 +148,9 @@
void setImageOutputFormat(
OMX_COLOR_FORMATTYPE format, OMX_U32 width, OMX_U32 height);
+ void setJPEGInputFormat(
+ OMX_U32 width, OMX_U32 height, OMX_U32 compressedSize);
+
status_t allocateBuffers();
status_t allocateBuffersOnPort(OMX_U32 portIndex);
diff --git a/include/media/stagefright/OMXDecoder.h b/include/media/stagefright/OMXDecoder.h
index 0abc5a6..99d803a 100644
--- a/include/media/stagefright/OMXDecoder.h
+++ b/include/media/stagefright/OMXDecoder.h
@@ -76,7 +76,7 @@
};
enum Quirks {
- kWantsRawNALFrames = 1,
+ kWantsNALFragments = 1,
kDoesntReturnBuffersOnDisable = 2,
kDoesntFlushOnExecutingToIdle = 4,
kDoesntProperlyFlushAllPortsAtOnce = 8,
diff --git a/include/ui/ISurfaceFlingerClient.h b/include/ui/ISurfaceFlingerClient.h
index 932a70a..5d231e6d 100644
--- a/include/ui/ISurfaceFlingerClient.h
+++ b/include/ui/ISurfaceFlingerClient.h
@@ -52,6 +52,9 @@
struct surface_data_t {
int32_t token;
int32_t identity;
+ uint32_t width;
+ uint32_t height;
+ uint32_t format;
status_t readFromParcel(const Parcel& parcel);
status_t writeToParcel(Parcel* parcel) const;
};
diff --git a/libs/binder/MemoryHeapBase.cpp b/libs/binder/MemoryHeapBase.cpp
index ac38f51..5df078f 100644
--- a/libs/binder/MemoryHeapBase.cpp
+++ b/libs/binder/MemoryHeapBase.cpp
@@ -78,13 +78,13 @@
}
}
-MemoryHeapBase::MemoryHeapBase(int fd, size_t size, uint32_t flags)
+MemoryHeapBase::MemoryHeapBase(int fd, size_t size, uint32_t flags, uint32_t offset)
: mFD(-1), mSize(0), mBase(MAP_FAILED), mFlags(flags),
mDevice(0), mNeedUnmap(false)
{
const size_t pagesize = getpagesize();
size = ((size + pagesize-1) & ~(pagesize-1));
- mapfd(dup(fd), size);
+ mapfd(dup(fd), size, offset);
}
status_t MemoryHeapBase::init(int fd, void *base, int size, int flags, const char* device)
@@ -100,7 +100,7 @@
return NO_ERROR;
}
-status_t MemoryHeapBase::mapfd(int fd, size_t size)
+status_t MemoryHeapBase::mapfd(int fd, size_t size, uint32_t offset)
{
if (size == 0) {
// try to figure out the size automatically
@@ -121,7 +121,7 @@
if ((mFlags & DONT_MAP_LOCALLY) == 0) {
void* base = (uint8_t*)mmap(0, size,
- PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
+ PROT_READ|PROT_WRITE, MAP_SHARED, fd, offset);
if (base == MAP_FAILED) {
LOGE("mmap(fd=%d, size=%u) failed (%s)",
fd, uint32_t(size), strerror(errno));
diff --git a/libs/rs/java/Fall/res/drawable-hdpi/sky.jpg b/libs/rs/java/Fall/res/drawable-hdpi/sky.jpg
old mode 100755
new mode 100644
index 2508f0c..565a63b
--- a/libs/rs/java/Fall/res/drawable-hdpi/sky.jpg
+++ b/libs/rs/java/Fall/res/drawable-hdpi/sky.jpg
Binary files differ
diff --git a/libs/rs/java/Fall/res/raw/fall.c b/libs/rs/java/Fall/res/raw/fall.c
index edfc926..f348a62 100644
--- a/libs/rs/java/Fall/res/raw/fall.c
+++ b/libs/rs/java/Fall/res/raw/fall.c
@@ -18,25 +18,10 @@
#pragma stateFragmentStore(PFSBackground)
#define RSID_STATE 0
-#define RSID_FRAME_COUNT 0
-#define RSID_WIDTH 1
-#define RSID_HEIGHT 2
-#define RSID_MESH_WIDTH 3
-#define RSID_MESH_HEIGHT 4
-#define RSID_RIPPLE_MAP_SIZE 5
-#define RSID_RIPPLE_INDEX 6
-#define RSID_DROP_X 7
-#define RSID_DROP_Y 8
-#define RSID_RUNNING 9
-#define RSID_LEAVES_COUNT 10
-
#define RSID_RIPPLE_MAP 1
#define RSID_REFRACTION_MAP 2
#define RSID_LEAVES 3
-
-#define RSID_GL_STATE 4
-#define RSID_GL_WIDTH 0
-#define RSID_GL_HEIGHT 1
+#define RSID_DROP 4
#define LEAF_STRUCT_FIELDS_COUNT 11
#define LEAF_STRUCT_X 0
@@ -67,8 +52,8 @@
}
void dropWithStrength(int x, int y, int r, int s) {
- int width = loadI32(RSID_STATE, RSID_MESH_WIDTH);
- int height = loadI32(RSID_STATE, RSID_MESH_HEIGHT);
+ int width = State_meshWidth;
+ int height = State_meshHeight;
if (x < r) x = r;
if (y < r) y = r;
@@ -77,23 +62,24 @@
x = width - x;
- int rippleMapSize = loadI32(RSID_STATE, RSID_RIPPLE_MAP_SIZE);
- int index = loadI32(RSID_STATE, RSID_RIPPLE_INDEX);
+ int rippleMapSize = State_rippleMapSize;
+ int index = State_rippleIndex;
int origin = offset(0, 0, width);
int* current = loadArrayI32(RSID_RIPPLE_MAP, index * rippleMapSize + origin);
int sqr = r * r;
+ float invs = 1.0f / s;
int h = 0;
- for ( ; h < r; h++) {
+ for ( ; h < r; h += 1) {
int sqv = h * h;
int yn = origin + (y - h) * (width + 2);
int yp = origin + (y + h) * (width + 2);
int w = 0;
- for ( ; w < r; w++) {
+ for ( ; w < r; w += 1) {
int squ = w * w;
if (squ + sqv < sqr) {
- int v = -sqrtf((sqr - (squ + sqv)) << 16) / s;
+ int v = -sqrtf((sqr - (squ + sqv)) << 16) * invs;
current[yn + x + w] = v;
current[yp + x + w] = v;
current[yn + x - w] = v;
@@ -108,16 +94,16 @@
}
void updateRipples() {
- int rippleMapSize = loadI32(RSID_STATE, RSID_RIPPLE_MAP_SIZE);
- int width = loadI32(RSID_STATE, RSID_MESH_WIDTH);
- int height = loadI32(RSID_STATE, RSID_MESH_HEIGHT);
- int index = loadI32(RSID_STATE, RSID_RIPPLE_INDEX);
+ int rippleMapSize = State_rippleMapSize;
+ int width = State_meshWidth;
+ int height = State_meshHeight;
+ int index = State_rippleIndex;
int origin = offset(0, 0, width);
int* current = loadArrayI32(RSID_RIPPLE_MAP, index * rippleMapSize + origin);
int* next = loadArrayI32(RSID_RIPPLE_MAP, (1 - index) * rippleMapSize + origin);
- storeI32(RSID_STATE, RSID_RIPPLE_INDEX, 1 - index);
+ storeI32(RSID_STATE, OFFSETOF_WorldState_rippleIndex, 1 - index);
int a = 1;
int b = width + 2;
@@ -125,16 +111,16 @@
while (h) {
int w = width;
while (w) {
- int droplet = ((current[-b] + current[b] + current[-a] + current[a]) >> 1) - next[0];
+ int droplet = ((current[-b] + current[b] + current[-a] + current[a]) >> 1) - *next;
droplet -= (droplet >> DAMP);
- next[0] = droplet;
- current++;
- next++;
- w--;
+ *next = droplet;
+ current += 1;
+ next += 1;
+ w -= 1;
}
current += 2;
next += 2;
- h--;
+ h -= 1;
}
}
@@ -152,22 +138,26 @@
}
void generateRipples() {
- int rippleMapSize = loadI32(RSID_STATE, RSID_RIPPLE_MAP_SIZE);
- int width = loadI32(RSID_STATE, RSID_MESH_WIDTH);
- int height = loadI32(RSID_STATE, RSID_MESH_HEIGHT);
- int index = loadI32(RSID_STATE, RSID_RIPPLE_INDEX);
+ int rippleMapSize = loadI32(RSID_STATE, OFFSETOF_WorldState_rippleMapSize);
+ int width = State_meshWidth;
+ int height = State_meshHeight;
+ int index = State_rippleIndex;
int origin = offset(0, 0, width);
int b = width + 2;
int* current = loadArrayI32(RSID_RIPPLE_MAP, index * rippleMapSize + origin);
int *map = loadArrayI32(RSID_REFRACTION_MAP, 0);
- float *vertices = loadTriangleMeshVerticesF(NAMED_mesh);
+ float *vertices = loadTriangleMeshVerticesF(NAMED_WaterMesh);
+
+ float fw = (float) width;
+ float fh = (float) height;
+ float fy = (1.0f / 512.0f) * (1.0f / RIPPLE_HEIGHT);
int h = height - 1;
while (h >= 0) {
int w = width - 1;
- int wave = current[0];
+ int wave = *current;
int offset = h * width;
while (w >= 0) {
int nextWave = current[1];
@@ -184,40 +174,47 @@
v &= ~(v >> 31);
if (v >= height) v = height - 1;
- vertices[(offset + w) * 8 + 3] = u / (float) width;
- vertices[(offset + w) * 8 + 4] = v / (float) height;
+ int index = (offset + w) << 3;
+ vertices[index + 3] = u / fw;
+ vertices[index + 4] = v / fh;
// Update Z coordinate of the vertex
- vertices[(offset + w) * 8 + 7] = (dy / 512.0f) / RIPPLE_HEIGHT;
+ vertices[index + 7] = dy * fy;
- w--;
- current++;
+ w -= 1;
+ current += 1;
wave = nextWave;
}
- h--;
+ h -= 1;
current += 2;
}
// Compute the normals for lighting
int y = 0;
- for ( ; y < height; y++) {
+ int w8 = width << 3;
+ for ( ; y < height; y += 1) {
int x = 0;
int yOffset = y * width;
- for ( ; x < width; x++) {
+ for ( ; x < width; x += 1) {
+ int o = (yOffset + x) << 3;
+ int o1 = o + 8;
+ int ow = o + w8;
+ int ow1 = ow + 8;
+
// V1
- float v1x = vertices[(yOffset + x) * 8 + 5];
- float v1y = vertices[(yOffset + x) * 8 + 6];
- float v1z = vertices[(yOffset + x) * 8 + 7];
+ float v1x = vertices[o + 5];
+ float v1y = vertices[o + 6];
+ float v1z = vertices[o + 7];
// V2
- float v2x = vertices[(yOffset + x + 1) * 8 + 5];
- float v2y = vertices[(yOffset + x + 1) * 8 + 6];
- float v2z = vertices[(yOffset + x + 1) * 8 + 7];
+ float v2x = vertices[o1 + 5];
+ float v2y = vertices[o1 + 6];
+ float v2z = vertices[o1 + 7];
// V3
- float v3x = vertices[(yOffset + width + x) * 8 + 5];
- float v3y = vertices[(yOffset + width + x) * 8 + 6];
- float v3z = vertices[(yOffset + width + x) * 8 + 7];
+ float v3x = vertices[ow + 5];
+ float v3y = vertices[ow + 6];
+ float v3z = vertices[ow + 7];
// N1
float n1x = v2x - v1x;
@@ -235,15 +232,15 @@
float n3z = n1x * n2y - n1y * n2x;
// Normalize
- float len = magf3(n3x, n3y, n3z);
- n3x /= len;
- n3y /= len;
- n3z /= len;
+ float len = 1.0f / magf3(n3x, n3y, n3z);
+ n3x *= len;
+ n3y *= len;
+ n3z *= len;
// V2
- v2x = vertices[(yOffset + width + x + 1) * 8 + 5];
- v2y = vertices[(yOffset + width + x + 1) * 8 + 6];
- v2z = vertices[(yOffset + width + x + 1) * 8 + 7];
+ v2x = vertices[ow1 + 5];
+ v2y = vertices[ow1 + 6];
+ v2z = vertices[ow1 + 7];
// N1
n1x = v2x - v1x;
@@ -255,23 +252,23 @@
n2y = v3y - v1y;
n2z = v3z - v1z;
- // Avegare of previous normal and N1 x N2
- n3x = n3x / 2.0f + (n1y * n2z - n1z * n2y) / 2.0f;
- n3y = n3y / 2.0f + (n1z * n2x - n1x * n2z) / 2.0f;
- n3z = n3z / 2.0f + (n1x * n2y - n1y * n2x) / 2.0f;
+ // Average of previous normal and N1 x N2
+ n3x = n3x * 0.5f + (n1y * n2z - n1z * n2y) * 0.5f;
+ n3y = n3y * 0.5f + (n1z * n2x - n1x * n2z) * 0.5f;
+ n3z = n3z * 0.5f + (n1x * n2y - n1y * n2x) * 0.5f;
// Normalize
- len = magf3(n3x, n3y, n3z);
- n3x /= len;
- n3y /= len;
- n3z /= len;
+ len = 1.0f / magf3(n3x, n3y, n3z);
+ n3x *= len;
+ n3y *= len;
+ n3z *= len;
- vertices[(yOffset + x) * 8 + 0] = n3x;
- vertices[(yOffset + x) * 8 + 1] = n3y;
- vertices[(yOffset + x) * 8 + 2] = -n3z;
+ vertices[o + 0] = n3x;
+ vertices[o + 1] = n3y;
+ vertices[o + 2] = -n3z;
// reset Z
- //vertices[(yOffset + x) * 8 + 7] = 0.0f;
+ //vertices[(yOffset + x) << 3 + 7] = 0.0f;
}
}
}
@@ -279,10 +276,10 @@
float averageZ(float x1, float x2, float y1, float y2, float* vertices,
int meshWidth, int meshHeight, float glWidth, float glHeight) {
- x1 = ((x1 + glWidth / 2.0f) / glWidth) * meshWidth;
- x2 = ((x2 + glWidth / 2.0f) / glWidth) * meshWidth;
- y1 = ((y1 + glHeight / 2.0f) / glHeight) * meshHeight;
- y2 = ((y2 + glHeight / 2.0f) / glHeight) * meshHeight;
+ x1 = ((x1 + glWidth * 0.5f) / glWidth) * meshWidth;
+ x2 = ((x2 + glWidth * 0.5f) / glWidth) * meshWidth;
+ y1 = ((y1 + glHeight * 0.5f) / glHeight) * meshHeight;
+ y2 = ((y2 + glHeight * 0.5f) / glHeight) * meshHeight;
int quadX1 = clamp(x1, 0, meshWidth);
int quadX2 = clamp(x2, 0, meshWidth);
@@ -293,19 +290,19 @@
int vertexCount = 0;
int y = quadY1;
- for ( ; y < quadY2; y++) {
+ for ( ; y < quadY2; y += 1) {
int x = quadX1;
int yOffset = y * meshWidth;
- for ( ; x < quadX2; x++) {
- z += vertices[(yOffset + x) * 8 + 7];
- vertexCount++;
+ for ( ; x < quadX2; x += 1) {
+ z += vertices[(yOffset + x) << 3 + 7];
+ vertexCount += 1;
}
}
return 55.0f * z / vertexCount;
}
-void drawLeaf(int index, int frameCount, float* vertices, int meshWidth, int meshHeight,
+void drawLeaf(int index, float* vertices, int meshWidth, int meshHeight,
float glWidth, float glHeight) {
float *leafStruct = loadArrayF(RSID_LEAVES, index);
@@ -334,10 +331,10 @@
if (a > 0.0f) {
tz = -a;
} else {
- z1 = averageZ(x1, x, y1, y, vertices, meshWidth, meshHeight, glWidth, glHeight);
- z2 = averageZ(x, x2, y1, y, vertices, meshWidth, meshHeight, glWidth, glHeight);
- z3 = averageZ(x, x2, y, y2, vertices, meshWidth, meshHeight, glWidth, glHeight);
- z4 = averageZ(x1, x, y, y2, vertices, meshWidth, meshHeight, glWidth, glHeight);
+// z1 = averageZ(x1, x, y1, y, vertices, meshWidth, meshHeight, glWidth, glHeight);
+// z2 = averageZ(x, x2, y1, y, vertices, meshWidth, meshHeight, glWidth, glHeight);
+// z3 = averageZ(x, x2, y, y2, vertices, meshWidth, meshHeight, glWidth, glHeight);
+// z4 = averageZ(x1, x, y, y2, vertices, meshWidth, meshHeight, glWidth, glHeight);
}
x1 -= x;
@@ -361,16 +358,16 @@
if (a <= 0.0f) {
float rippled = leafStruct[LEAF_STRUCT_RIPPLED];
if (rippled < 0.0f) {
- drop(((x + glWidth / 2.0f) / glWidth) * meshWidth,
- meshHeight - ((y + glHeight / 2.0f) / glHeight) * meshHeight,
+ drop(((x + glWidth * 0.5f) / glWidth) * meshWidth,
+ meshHeight - ((y + glHeight * 0.5f) / glHeight) * meshHeight,
DROP_RADIUS);
spin /= 4.0f;
leafStruct[LEAF_STRUCT_SPIN] = spin;
leafStruct[LEAF_STRUCT_RIPPLED] = 1.0f;
} else {
- dropWithStrength(((x + glWidth / 2.0f) / glWidth) * meshWidth,
- meshHeight - ((y + glHeight / 2.0f) / glHeight) * meshHeight,
- 2, 5);
+// dropWithStrength(((x + glWidth / 2.0f) / glWidth) * meshWidth,
+// meshHeight - ((y + glHeight / 2.0f) / glHeight) * meshHeight,
+// 2, 5);
}
leafStruct[LEAF_STRUCT_X] = x + leafStruct[LEAF_STRUCT_DELTAX];
leafStruct[LEAF_STRUCT_Y] = y + leafStruct[LEAF_STRUCT_DELTAY];
@@ -398,23 +395,24 @@
}
}
-void drawLeaves(int frameCount) {
+void drawLeaves() {
bindProgramFragment(NAMED_PFBackground);
bindProgramFragmentStore(NAMED_PFSLeaf);
+ bindProgramVertex(NAMED_PVSky);
bindTexture(NAMED_PFBackground, 0, NAMED_TLeaves);
- int leavesCount = loadI32(RSID_STATE, RSID_LEAVES_COUNT);
+ int leavesCount = State_leavesCount;
int count = leavesCount * LEAF_STRUCT_FIELDS_COUNT;
- int width = loadI32(RSID_STATE, RSID_MESH_WIDTH);
- int height = loadI32(RSID_STATE, RSID_MESH_HEIGHT);
- float glWidth = loadF(RSID_GL_STATE, RSID_GL_WIDTH);
- float glHeight = loadF(RSID_GL_STATE, RSID_GL_HEIGHT);
+ int width = State_meshWidth;
+ int height = State_meshHeight;
+ float glWidth = State_glWidth;
+ float glHeight = State_glHeight;
- float *vertices = loadTriangleMeshVerticesF(NAMED_mesh);
+ float *vertices = loadTriangleMeshVerticesF(NAMED_WaterMesh);
int i = 0;
for ( ; i < count; i += LEAF_STRUCT_FIELDS_COUNT) {
- drawLeaf(i, frameCount, vertices, width, height, glWidth, glHeight);
+ drawLeaf(i, vertices, width, height, glWidth, glHeight);
}
float matrix[16];
@@ -422,47 +420,99 @@
vpLoadModelMatrix(matrix);
}
-int main(int index) {
- int frameCount = loadI32(RSID_STATE, RSID_FRAME_COUNT);
-
- int dropX = loadI32(RSID_STATE, RSID_DROP_X);
- if (dropX != -1) {
- int dropY = loadI32(RSID_STATE, RSID_DROP_Y);
- drop(dropX, dropY, DROP_RADIUS);
- storeI32(RSID_STATE, RSID_DROP_X, -1);
- storeI32(RSID_STATE, RSID_DROP_Y, -1);
- }
-
- int isRunning = loadI32(RSID_STATE, RSID_RUNNING);
- if (isRunning) {
- updateRipples();
- generateRipples();
- updateTriangleMesh(NAMED_mesh);
- }
-
+void drawRiverbed() {
bindTexture(NAMED_PFBackground, 0, NAMED_TRiverbed);
- drawTriangleMesh(NAMED_mesh);
- color(1.0f, 1.0f, 1.0f, 0.7f);
+ drawTriangleMesh(NAMED_WaterMesh);
+}
+
+void drawSky() {
+ color(1.0f, 1.0f, 1.0f, 0.8f);
+
bindProgramFragment(NAMED_PFSky);
bindProgramFragmentStore(NAMED_PFSLeaf);
bindTexture(NAMED_PFSky, 0, NAMED_TSky);
- drawTriangleMesh(NAMED_mesh);
+ float x = State_skyOffsetX + State_skySpeedX;
+ float y = State_skyOffsetY + State_skySpeedY;
+
+ if (x > 1.0f) x = 0.0f;
+ if (x < -1.0f) x = 0.0f;
+ if (y > 1.0f) y = 0.0f;
+
+ storeF(RSID_STATE, OFFSETOF_WorldState_skyOffsetX, x);
+ storeF(RSID_STATE, OFFSETOF_WorldState_skyOffsetY, y);
+
+ float matrix[16];
+ matrixLoadTranslate(matrix, x, y, 0.0f);
+ vpLoadTextureMatrix(matrix);
+
+ drawTriangleMesh(NAMED_WaterMesh);
+
+ matrixLoadIdentity(matrix);
+ vpLoadTextureMatrix(matrix);
+}
+
+void drawLighting() {
ambient(0.0f, 0.0f, 0.0f, 1.0f);
diffuse(0.0f, 0.0f, 0.0f, 1.0f);
specular(0.44f, 0.44f, 0.44f, 1.0f);
shininess(40.0f);
+
bindProgramFragmentStore(NAMED_PFSBackground);
bindProgramFragment(NAMED_PFLighting);
bindProgramVertex(NAMED_PVLight);
- drawTriangleMesh(NAMED_mesh);
+
+ drawTriangleMesh(NAMED_WaterMesh);
+}
+
+void drawNormals() {
+ int width = State_meshWidth;
+ int height = State_meshHeight;
+
+ float *vertices = loadTriangleMeshVerticesF(NAMED_WaterMesh);
bindProgramVertex(NAMED_PVSky);
- drawLeaves(frameCount);
+ bindProgramFragment(NAMED_PFLighting);
- frameCount++;
- storeI32(RSID_STATE, RSID_FRAME_COUNT, frameCount);
+ color(1.0f, 0.0f, 0.0f, 1.0f);
+
+ float scale = 1.0f / 10.0f;
+ int y = 0;
+ for ( ; y < height; y += 1) {
+ int yOffset = y * width;
+ int x = 0;
+ for ( ; x < width; x += 1) {
+ int offset = (yOffset + x) << 3;
+ float vx = vertices[offset + 5];
+ float vy = vertices[offset + 6];
+ float vz = vertices[offset + 7];
+ float nx = vertices[offset + 0];
+ float ny = vertices[offset + 1];
+ float nz = vertices[offset + 2];
+ drawLine(vx, vy, vz, vx + nx * scale, vy + ny * scale, vz + nz * scale);
+ }
+ }
+}
+
+int main(int index) {
+ int dropX = Drop_dropX;
+ if (dropX != -1) {
+ int dropY = Drop_dropY;
+ drop(dropX, dropY, DROP_RADIUS);
+ storeI32(RSID_DROP, OFFSETOF_DropState_dropX, -1);
+ storeI32(RSID_DROP, OFFSETOF_DropState_dropY, -1);
+ }
+
+ updateRipples();
+ generateRipples();
+ updateTriangleMesh(NAMED_WaterMesh);
+
+ drawRiverbed();
+ drawSky();
+ drawLighting();
+ drawLeaves();
+ //drawNormals();
return 1;
}
diff --git a/libs/rs/java/Fall/src/com/android/fall/rs/FallRS.java b/libs/rs/java/Fall/src/com/android/fall/rs/FallRS.java
index b4f96f3..3b13bed 100644
--- a/libs/rs/java/Fall/src/com/android/fall/rs/FallRS.java
+++ b/libs/rs/java/Fall/src/com/android/fall/rs/FallRS.java
@@ -26,6 +26,7 @@
import android.renderscript.Sampler;
import android.renderscript.Element;
import android.renderscript.Light;
+import android.renderscript.Type;
import static android.renderscript.Sampler.Value.LINEAR;
import static android.renderscript.Sampler.Value.WRAP;
import static android.renderscript.ProgramStore.DepthFunc.*;
@@ -43,18 +44,7 @@
private static final int MESH_RESOLUTION = 48;
private static final int RSID_STATE = 0;
- private static final int RSID_STATE_FRAMECOUNT = 0;
- private static final int RSID_STATE_WIDTH = 1;
- private static final int RSID_STATE_HEIGHT = 2;
- private static final int RSID_STATE_MESH_WIDTH = 3;
- private static final int RSID_STATE_MESH_HEIGHT = 4;
- private static final int RSID_STATE_RIPPLE_MAP_SIZE = 5;
- private static final int RSID_STATE_RIPPLE_INDEX = 6;
- private static final int RSID_STATE_DROP_X = 7;
- private static final int RSID_STATE_DROP_Y = 8;
- private static final int RSID_STATE_RUNNING = 9;
- private static final int RSID_STATE_LEAVES_COUNT = 10;
-
+
private static final int TEXTURES_COUNT = 3;
private static final int LEAVES_TEXTURES_COUNT = 4;
private static final int RSID_TEXTURE_RIVERBED = 0;
@@ -80,12 +70,8 @@
private static final int LEAF_STRUCT_DELTAX = 9;
private static final int LEAF_STRUCT_DELTAY = 10;
- private static final int RSID_GL_STATE = 4;
- private static final int RSID_STATE_GL_WIDTH = 0;
- private static final int RSID_STATE_GL_HEIGHT = 1;
-
- private boolean mIsRunning = true;
-
+ private static final int RSID_DROP = 4;
+
private Resources mResources;
private RenderScript mRS;
@@ -94,34 +80,35 @@
private final int mWidth;
private final int mHeight;
- private ScriptC mScript;
- private Sampler mSampler;
+ @SuppressWarnings({"FieldCanBeLocal"})
private ProgramFragment mPfBackground;
+ @SuppressWarnings({"FieldCanBeLocal"})
private ProgramFragment mPfLighting;
+ @SuppressWarnings({"FieldCanBeLocal"})
private ProgramFragment mPfSky;
+ @SuppressWarnings({"FieldCanBeLocal"})
private ProgramStore mPfsBackground;
+ @SuppressWarnings({"FieldCanBeLocal"})
private ProgramStore mPfsLeaf;
+ @SuppressWarnings({"FieldCanBeLocal"})
private ProgramVertex mPvLight;
+ @SuppressWarnings({"FieldCanBeLocal"})
private ProgramVertex mPvSky;
- private ProgramVertex.MatrixAllocation mPvOrthoAlloc;
- private Light mLight;
-
- private Allocation[] mTextures;
private Allocation mState;
- private RenderScript.TriangleMesh mMesh;
+ private Allocation mDropState;
+ private DropState mDrop;
+ private Type mStateType;
+ private Type mDropType;
private int mMeshWidth;
- private int mMeshHeight;
+ private int mMeshHeight;
private Allocation mRippleMap;
private Allocation mRefractionMap;
+
private Allocation mLeaves;
-
- private Allocation mGlState;
private float mGlHeight;
- private final int[] mIntData2 = new int[2];
-
public FallRS(int width, int height) {
mWidth = width;
mHeight = height;
@@ -135,38 +122,6 @@
initRS();
}
- public void destroy() {
- mScript.destroy();
- mSampler.destroy();
- mPfBackground.destroy();
- mPfsBackground.destroy();
- mPvLight.destroy();
- mPvOrthoAlloc.mAlloc.destroy();
- for (Allocation a : mTextures) {
- a.destroy();
- }
- mState.destroy();
- mMesh.destroy();
- mLight.destroy();
- mRippleMap.destroy();
- mRefractionMap.destroy();
- mPvSky.destroy();
- mPfLighting.destroy();
- mLeaves.destroy();
- mPfsLeaf.destroy();
- mPfSky.destroy();
- mGlState.destroy();
- }
-
- @Override
- protected void finalize() throws Throwable {
- try {
- destroy();
- } finally {
- super.finalize();
- }
- }
-
private void initRS() {
createProgramVertex();
createProgramFragmentStore();
@@ -176,19 +131,22 @@
loadTextures();
ScriptC.Builder sb = new ScriptC.Builder(mRS);
+ sb.setType(mStateType, "State", RSID_STATE);
+ sb.setType(mDropType, "Drop", RSID_DROP);
sb.setScript(mResources, R.raw.fall);
sb.setRoot(true);
- mScript = sb.create();
- mScript.setClearColor(0.0f, 0.0f, 0.0f, 1.0f);
- mScript.setTimeZone(TimeZone.getDefault().getID());
- mScript.bindAllocation(mState, RSID_STATE);
- mScript.bindAllocation(mRippleMap, RSID_RIPPLE_MAP);
- mScript.bindAllocation(mRefractionMap, RSID_REFRACTION_MAP);
- mScript.bindAllocation(mLeaves, RSID_LEAVES);
- mScript.bindAllocation(mGlState, RSID_GL_STATE);
+ ScriptC script = sb.create();
+ script.setClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+ script.setTimeZone(TimeZone.getDefault().getID());
- mRS.contextBindRootScript(mScript);
+ script.bindAllocation(mState, RSID_STATE);
+ script.bindAllocation(mRippleMap, RSID_RIPPLE_MAP);
+ script.bindAllocation(mRefractionMap, RSID_REFRACTION_MAP);
+ script.bindAllocation(mLeaves, RSID_LEAVES);
+ script.bindAllocation(mDropState, RSID_DROP);
+
+ mRS.contextBindRootScript(script);
}
private void createMesh() {
@@ -219,27 +177,42 @@
hResolution += 2;
for (int y = 0; y <= hResolution; y++) {
+ final boolean shift = (y & 0x1) == 0;
final float yOffset = y * quadHeight - glHeight / 2.0f - quadHeight;
final float t = 1.0f - y / (float) hResolution;
for (int x = 0; x <= wResolution; x++) {
- rs.triangleMeshAddVertex_XYZ_ST_NORM(
- -1.0f + x * quadWidth - quadWidth, yOffset, 0.0f,
- x / (float) wResolution, t,
- 0.0f, 0.0f, -1.0f);
+ if (shift) {
+ rs.triangleMeshAddVertex_XYZ_ST_NORM(
+ -1.0f + x * quadWidth - quadWidth, yOffset, 0.0f,
+ x / (float) wResolution, t,
+ 0.0f, 0.0f, -1.0f);
+ } else {
+ rs.triangleMeshAddVertex_XYZ_ST_NORM(
+ -1.0f + x * quadWidth - quadWidth * 0.5f, yOffset, 0.0f,
+ x / (float) wResolution, t,
+ 0.0f, 0.0f, -1.0f);
+ }
}
}
for (int y = 0; y < hResolution; y++) {
+ final boolean shift = (y & 0x1) == 0;
+ final int yOffset = y * (wResolution + 1);
for (int x = 0; x < wResolution; x++) {
- final int index = y * (wResolution + 1) + x;
+ final int index = yOffset + x;
final int iWR1 = index + wResolution + 1;
- rs.triangleMeshAddTriangle(index, index + 1, iWR1);
- rs.triangleMeshAddTriangle(index + 1, iWR1, iWR1 + 1);
+ if (shift) {
+ rs.triangleMeshAddTriangle(index, index + 1, iWR1);
+ rs.triangleMeshAddTriangle(index + 1, iWR1 + 1, iWR1);
+ } else {
+ rs.triangleMeshAddTriangle(index, iWR1 + 1, iWR1);
+ rs.triangleMeshAddTriangle(index, index + 1, iWR1 + 1);
+ }
}
}
- mMesh = rs.triangleMeshCreate();
- mMesh.setName("mesh");
+ RenderScript.TriangleMesh mesh = rs.triangleMeshCreate();
+ mesh.setName("WaterMesh");
mMeshWidth = wResolution + 1;
mMeshHeight = hResolution + 1;
@@ -249,7 +222,6 @@
final int rippleMapSize = (mMeshWidth + 2) * (mMeshHeight + 2);
createState(rippleMapSize);
- createGlState();
createRippleMap(rippleMapSize);
createRefractionMap();
createLeaves();
@@ -281,29 +253,53 @@
mRippleMap.data(rippleMap);
}
- private void createGlState() {
- final float[] meshState = new float[2];
- mGlState = Allocation.createSized(mRS, USER_FLOAT, meshState.length);
- meshState[RSID_STATE_GL_WIDTH] = 2.0f;
- meshState[RSID_STATE_GL_HEIGHT] = mGlHeight;
- mGlState.data(meshState);
+ static class WorldState {
+ public int frameCount;
+ public int width;
+ public int height;
+ public int meshWidth;
+ public int meshHeight;
+ public int rippleMapSize;
+ public int rippleIndex;
+ public int leavesCount;
+ public float glWidth;
+ public float glHeight;
+ public float skyOffsetX;
+ public float skyOffsetY;
+ public float skySpeedX;
+ public float skySpeedY;
+ }
+
+ static class DropState {
+ public int dropX;
+ public int dropY;
}
private void createState(int rippleMapSize) {
- final int[] data = new int[11];
- mState = Allocation.createSized(mRS, USER_I32, data.length);
- data[RSID_STATE_FRAMECOUNT] = 0;
- data[RSID_STATE_WIDTH] = mWidth;
- data[RSID_STATE_HEIGHT] = mHeight;
- data[RSID_STATE_MESH_WIDTH] = mMeshWidth;
- data[RSID_STATE_MESH_HEIGHT] = mMeshHeight;
- data[RSID_STATE_RIPPLE_MAP_SIZE] = rippleMapSize;
- data[RSID_STATE_RIPPLE_INDEX] = 0;
- data[RSID_STATE_DROP_X] = -1;
- data[RSID_STATE_DROP_Y] = -1;
- data[RSID_STATE_RUNNING] = 1;
- data[RSID_STATE_LEAVES_COUNT] = LEAVES_COUNT;
- mState.data(data);
+ WorldState worldState = new WorldState();
+ worldState.width = mWidth;
+ worldState.height = mHeight;
+ worldState.meshWidth = mMeshWidth;
+ worldState.meshHeight = mMeshHeight;
+ worldState.rippleMapSize = rippleMapSize;
+ worldState.rippleIndex = 0;
+ worldState.leavesCount = LEAVES_COUNT;
+ worldState.glWidth = 2.0f;
+ worldState.glHeight = mGlHeight;
+ worldState.skySpeedX = random(-0.001f, 0.001f);
+ worldState.skySpeedY = random(0.00008f, 0.0002f);
+
+ mStateType = Type.createFromClass(mRS, WorldState.class, 1, "WorldState");
+ mState = Allocation.createTyped(mRS, mStateType);
+ mState.data(worldState);
+
+ mDrop = new DropState();
+ mDrop.dropX = -1;
+ mDrop.dropY = -1;
+
+ mDropType = Type.createFromClass(mRS, DropState.class, 1, "DropState");
+ mDropState = Allocation.createTyped(mRS, mDropType);
+ mDropState.data(mDrop);
}
private void createLeaf(float[] leaves, int index) {
@@ -323,9 +319,7 @@
}
private void loadTextures() {
- mTextures = new Allocation[TEXTURES_COUNT];
-
- final Allocation[] textures = mTextures;
+ final Allocation[] textures = new Allocation[TEXTURES_COUNT];
textures[RSID_TEXTURE_RIVERBED] = loadTexture(R.drawable.riverbed, "TRiverbed");
textures[RSID_TEXTURE_LEAVES] = loadTextureARGB(R.drawable.leaves, "TLeaves");
textures[RSID_TEXTURE_SKY] = loadTextureARGB(R.drawable.sky, "TSky");
@@ -357,27 +351,27 @@
sampleBuilder.setMag(LINEAR);
sampleBuilder.setWrapS(WRAP);
sampleBuilder.setWrapT(WRAP);
- mSampler = sampleBuilder.create();
+ Sampler sampler = sampleBuilder.create();
ProgramFragment.Builder builder = new ProgramFragment.Builder(mRS, null, null);
builder.setTexEnable(true, 0);
builder.setTexEnvMode(REPLACE, 0);
mPfBackground = builder.create();
mPfBackground.setName("PFBackground");
- mPfBackground.bindSampler(mSampler, 0);
+ mPfBackground.bindSampler(sampler, 0);
builder = new ProgramFragment.Builder(mRS, null, null);
builder.setTexEnable(false, 0);
mPfLighting = builder.create();
mPfLighting.setName("PFLighting");
- mPfLighting.bindSampler(mSampler, 0);
+ mPfLighting.bindSampler(sampler, 0);
builder = new ProgramFragment.Builder(mRS, null, null);
builder.setTexEnable(true, 0);
builder.setTexEnvMode(MODULATE, 0);
mPfSky = builder.create();
mPfSky.setName("PFSky");
- mPfSky.bindSampler(mSampler, 0);
+ mPfSky.bindSampler(sampler, 0);
}
private void createProgramFragmentStore() {
@@ -399,33 +393,28 @@
}
private void createProgramVertex() {
- mPvOrthoAlloc = new ProgramVertex.MatrixAllocation(mRS);
- mPvOrthoAlloc.setupProjectionNormalized(mWidth, mHeight);
+ ProgramVertex.MatrixAllocation pvOrthoAlloc = new ProgramVertex.MatrixAllocation(mRS);
+ pvOrthoAlloc.setupProjectionNormalized(mWidth, mHeight);
- mLight = new Light.Builder(mRS).create();
- mLight.setPosition(0.0f, 2.0f, -8.0f);
+ Light light = new Light.Builder(mRS).create();
+ light.setPosition(0.0f, 2.0f, -8.0f);
ProgramVertex.Builder builder = new ProgramVertex.Builder(mRS, null, null);
- builder.setTextureMatrixEnable(true);
- builder.addLight(mLight);
+ builder.addLight(light);
mPvLight = builder.create();
- mPvLight.bindAllocation(mPvOrthoAlloc);
+ mPvLight.bindAllocation(pvOrthoAlloc);
mPvLight.setName("PVLight");
builder = new ProgramVertex.Builder(mRS, null, null);
+ builder.setTextureMatrixEnable(true);
mPvSky = builder.create();
- mPvSky.bindAllocation(mPvOrthoAlloc);
+ mPvSky.bindAllocation(pvOrthoAlloc);
mPvSky.setName("PVSky");
}
void addDrop(float x, float y) {
- mIntData2[0] = (int) ((x / mWidth) * mMeshWidth);
- mIntData2[1] = (int) ((y / mHeight) * mMeshHeight);
- mState.subData1D(RSID_STATE_DROP_X, 2, mIntData2);
- }
-
- void togglePause() {
- mIsRunning = !mIsRunning;
- mState.subData1D(RSID_STATE_RUNNING, 1, new int[] { mIsRunning ? 1 : 0 });
+ mDrop.dropX = (int) ((x / mWidth) * mMeshWidth);
+ mDrop.dropY = (int) ((y / mHeight) * mMeshHeight);
+ mDropState.data(mDrop);
}
}
diff --git a/libs/rs/java/Fall/src/com/android/fall/rs/FallView.java b/libs/rs/java/Fall/src/com/android/fall/rs/FallView.java
index d7573be..fa2caa7 100644
--- a/libs/rs/java/Fall/src/com/android/fall/rs/FallView.java
+++ b/libs/rs/java/Fall/src/com/android/fall/rs/FallView.java
@@ -42,20 +42,6 @@
}
@Override
- public void surfaceDestroyed(SurfaceHolder holder) {
- if (mRender != null) mRender.destroy();
- }
-
- @Override
- public boolean onKeyDown(int keyCode, KeyEvent event) {
- if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER ||
- keyCode == KeyEvent.KEYCODE_MENU) {
- mRender.togglePause();
- }
- return super.onKeyDown(keyCode, event);
- }
-
- @Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
diff --git a/libs/rs/java/Galaxy/res/raw/galaxy.c b/libs/rs/java/Galaxy/res/raw/galaxy.c
index 59c31a1..9ff449f 100644
--- a/libs/rs/java/Galaxy/res/raw/galaxy.c
+++ b/libs/rs/java/Galaxy/res/raw/galaxy.c
@@ -19,11 +19,13 @@
#define RSID_PARTICLES 1
-#define PARTICLE_STRUCT_FIELDS_COUNT 4
+#define PARTICLE_STRUCT_FIELDS_COUNT 6
#define PARTICLE_STRUCT_ANGLE 0
#define PARTICLE_STRUCT_DISTANCE 1
#define PARTICLE_STRUCT_SPEED 2
#define PARTICLE_STRUCT_RADIUS 3
+#define PARTICLE_STRUCT_S 4
+#define PARTICLE_STRUCT_T 5
#define RSID_PARTICLES_BUFFER 2
#define PARTICLE_BUFFER_COMPONENTS_COUNT 5
@@ -31,19 +33,14 @@
#define PARTICLES_TEXTURES_COUNT 2
#define ELLIPSE_RATIO 0.892f
-#define ELLIPSE_TWIST 0.02333333333f
void drawSpace(int width, int height) {
bindTexture(NAMED_PFBackground, 0, NAMED_TSpace);
drawQuadTexCoords(
- 0.0f, 0.0f, 0.0f,
- 0.0f, 1.0f,
- width, 0.0f, 0.0f,
- 2.0f, 1.0f,
- width, height, 0.0f,
- 2.0f, 0.0f,
- 0.0f, height, 0.0f,
- 0.0f, 0.0f);
+ 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
+ width, 0.0f, 0.0f, 2.0f, 1.0f,
+ width, height, 0.0f, 2.0f, 0.0f,
+ 0.0f, height, 0.0f, 0.0f, 0.0f);
}
void drawLights(int width, int height) {
@@ -61,39 +58,34 @@
x + 512.0f * 1.1f, y + 512.0f, 0.0f);
}
-void drawParticle(float *particle, int index, float *particleBuffer, int bufferIndex,
- float w, float h) {
-
- float distance = particle[index + PARTICLE_STRUCT_DISTANCE];
- float angle = particle[index + PARTICLE_STRUCT_ANGLE];
- float speed = particle[index + PARTICLE_STRUCT_SPEED];
- float r = particle[index + PARTICLE_STRUCT_RADIUS];
+void drawParticle(float *particle, float *particleBuffer, float w, float h) {
+ float distance = particle[PARTICLE_STRUCT_DISTANCE];
+ float angle = particle[PARTICLE_STRUCT_ANGLE];
+ float speed = particle[PARTICLE_STRUCT_SPEED];
+ float r = particle[PARTICLE_STRUCT_RADIUS];
float a = angle + speed;
float x = distance * sinf_fast(a);
float y = distance * cosf_fast(a) * ELLIPSE_RATIO;
- float z = distance * ELLIPSE_TWIST;
- float s = cosf_fast(z);
- float t = sinf_fast(z);
+ float s = particle[PARTICLE_STRUCT_S];
+ float t = particle[PARTICLE_STRUCT_T];
float sX = t * x + s * y + w;
float sY = s * x - t * y + h;
// lower left vertex of the particle's triangle
- particleBuffer[bufferIndex + 1] = sX - r; // X
- particleBuffer[bufferIndex + 2] = sY + r; // Y
+ particleBuffer[1] = sX - r; // X
+ particleBuffer[2] = sY + r; // Y
// lower right vertex of the particle's triangle
- bufferIndex += PARTICLE_BUFFER_COMPONENTS_COUNT;
- particleBuffer[bufferIndex + 1] = sX + r; // X
- particleBuffer[bufferIndex + 2] = sY + r; // Y
+ particleBuffer[6] = sX + r; // X
+ particleBuffer[7] = sY + r; // Y
// upper middle vertex of the particle's triangle
- bufferIndex += PARTICLE_BUFFER_COMPONENTS_COUNT;
- particleBuffer[bufferIndex + 1] = sX; // X
- particleBuffer[bufferIndex + 2] = sY - r; // Y
+ particleBuffer[11] = sX; // X
+ particleBuffer[12] = sY - r; // Y
- particle[index + PARTICLE_STRUCT_ANGLE] = a;
+ particle[PARTICLE_STRUCT_ANGLE] = a;
}
void drawParticles(int width, int height) {
@@ -103,7 +95,6 @@
int radius = State_galaxyRadius;
int particlesCount = State_particlesCount;
- int count = particlesCount * PARTICLE_STRUCT_FIELDS_COUNT;
float *particle = loadArrayF(RSID_PARTICLES, 0);
float *particleBuffer = loadArrayF(RSID_PARTICLES_BUFFER, 0);
@@ -112,11 +103,11 @@
float h = height * 0.5f;
int i = 0;
- int bufferIndex = 0;
- for ( ; i < count; i += PARTICLE_STRUCT_FIELDS_COUNT) {
- drawParticle(particle, i, particleBuffer, bufferIndex, w, h);
- // each particle is a triangle (3 vertices) of 6 properties (ABGR, X, Y, Z, S, T)
- bufferIndex += 3 * PARTICLE_BUFFER_COMPONENTS_COUNT;
+ for ( ; i < particlesCount; i++) {
+ drawParticle(particle, particleBuffer, w, h);
+ particle += PARTICLE_STRUCT_FIELDS_COUNT;
+ // each particle is a triangle (3 vertices) of 5 properties (ABGR, X, Y, S, T)
+ particleBuffer += 3 * PARTICLE_BUFFER_COMPONENTS_COUNT;
}
uploadToBufferObject(NAMED_ParticlesBuffer);
diff --git a/libs/rs/java/Galaxy/src/com/android/galaxy/rs/GalaxyRS.java b/libs/rs/java/Galaxy/src/com/android/galaxy/rs/GalaxyRS.java
index 717100d..c6f5816 100644
--- a/libs/rs/java/Galaxy/src/com/android/galaxy/rs/GalaxyRS.java
+++ b/libs/rs/java/Galaxy/src/com/android/galaxy/rs/GalaxyRS.java
@@ -42,9 +42,11 @@
import java.util.TimeZone;
+@SuppressWarnings({"FieldCanBeLocal"})
class GalaxyRS {
private static final int GALAXY_RADIUS = 300;
private static final int PARTICLES_COUNT = 12000;
+ private static final float ELLIPSE_TWIST = 0.023333333f;
private static final int RSID_STATE = 0;
@@ -54,11 +56,13 @@
private static final int RSID_TEXTURE_FLARES = 2;
private static final int RSID_PARTICLES = 1;
- private static final int PARTICLE_STRUCT_FIELDS_COUNT = 4;
+ private static final int PARTICLE_STRUCT_FIELDS_COUNT = 6;
private static final int PARTICLE_STRUCT_ANGLE = 0;
private static final int PARTICLE_STRUCT_DISTANCE = 1;
private static final int PARTICLE_STRUCT_SPEED = 2;
private static final int PARTICLE_STRUCT_RADIUS = 3;
+ private static final int PARTICLE_STRUCT_S = 4;
+ private static final int PARTICLE_STRUCT_T = 5;
private static final int RSID_PARTICLES_BUFFER = 2;
@@ -103,35 +107,6 @@
initRS();
}
- public void destroy() {
- mScript.destroy();
- mSampler.destroy();
- mLightSampler.destroy();
- mPfBackground.destroy();
- mPfsBackground.destroy();
- mPvBackground.destroy();
- mPvOrthoAlloc.mAlloc.destroy();
- for (Allocation a : mTextures) {
- a.destroy();
- }
- mState.destroy();
- mPfLighting.destroy();
- mParticles.destroy();
- mPfsLights.destroy();
- mParticlesMesh.destroy();
- mParticlesBuffer.destroy();
- mStateType.destroy();
- }
-
- @Override
- protected void finalize() throws Throwable {
- try {
- destroy();
- } finally {
- super.finalize();
- }
- }
-
private void initRS() {
createProgramVertex();
createProgramFragmentStore();
@@ -218,13 +193,16 @@
float d = abs(randomGauss()) * GALAXY_RADIUS / 2.0f + random(-4.0f, 4.0f);
float z = randomGauss() * 0.5f * 0.8f * ((GALAXY_RADIUS - d) / (float) GALAXY_RADIUS);
z += 1.0f;
+ float p = d * ELLIPSE_TWIST;
particles[index + PARTICLE_STRUCT_ANGLE] = random(0.0f, (float) (Math.PI * 2.0));
particles[index + PARTICLE_STRUCT_DISTANCE] = d;
particles[index + PARTICLE_STRUCT_SPEED] = random(0.0015f, 0.0025f) *
(0.5f + (0.5f * (float) GALAXY_RADIUS / d)) * 0.7f;
particles[index + PARTICLE_STRUCT_RADIUS] = z * random(1.2f, 2.1f);
-
+ particles[index + PARTICLE_STRUCT_S] = (float) Math.cos(p);
+ particles[index + PARTICLE_STRUCT_T] = (float) Math.sin(p);
+
int red, green, blue;
if (d < GALAXY_RADIUS / 3.0f) {
red = (int) (220 + (d / (float) GALAXY_RADIUS) * 35);
diff --git a/libs/rs/java/Galaxy/src/com/android/galaxy/rs/GalaxyView.java b/libs/rs/java/Galaxy/src/com/android/galaxy/rs/GalaxyView.java
index 341293b..4f6d3f0 100644
--- a/libs/rs/java/Galaxy/src/com/android/galaxy/rs/GalaxyView.java
+++ b/libs/rs/java/Galaxy/src/com/android/galaxy/rs/GalaxyView.java
@@ -22,8 +22,6 @@
import android.renderscript.RSSurfaceView;
class GalaxyView extends RSSurfaceView {
- private GalaxyRS mRender;
-
public GalaxyView(Context context) {
super(context);
setFocusable(true);
@@ -34,12 +32,7 @@
super.surfaceChanged(holder, format, w, h);
RenderScript RS = createRenderScript();
- mRender = new GalaxyRS(w, h);
- mRender.init(RS, getResources());
- }
-
- @Override
- public void surfaceDestroyed(SurfaceHolder holder) {
- if (mRender != null) mRender.destroy();
+ GalaxyRS render = new GalaxyRS(w, h);
+ render.init(RS, getResources());
}
}
diff --git a/libs/rs/rsContext.cpp b/libs/rs/rsContext.cpp
index 7bfa81ed..413caab 100644
--- a/libs/rs/rsContext.cpp
+++ b/libs/rs/rsContext.cpp
@@ -25,7 +25,6 @@
using namespace android;
using namespace android::renderscript;
-Context * Context::gCon = NULL;
pthread_key_t Context::gThreadTLSKey = 0;
void Context::initEGL()
@@ -84,6 +83,9 @@
bool Context::runRootScript()
{
+#if RS_LOG_TIMES
+ timerSet(RS_TIMER_CLEAR_SWAP);
+#endif
rsAssert(mRootScript->mEnviroment.mIsRoot);
//glColor4f(1,1,1,1);
@@ -102,24 +104,55 @@
glClear(GL_DEPTH_BUFFER_BIT);
#if RS_LOG_TIMES
- struct timespec startTime;
- clock_gettime(CLOCK_MONOTONIC, &startTime);
+ timerSet(RS_TIMER_SCRIPT);
#endif
bool ret = runScript(mRootScript.get(), 0);
-
-#if RS_LOG_TIMES
- struct timespec endTime;
- clock_gettime(CLOCK_MONOTONIC, &endTime);
-
- uint64_t t1 = endTime.tv_nsec + ((uint64_t)endTime.tv_sec * 1000 * 1000 * 1000);
- uint64_t t2 = startTime.tv_nsec + ((uint64_t)startTime.tv_sec * 1000 * 1000 * 1000);
- int t3 = (int)((t1 - t2) / 1000 / 1000);
- LOGE("times %i", t3);
-#endif
-
return ret;
}
+uint64_t Context::getTime() const
+{
+ struct timespec t;
+ clock_gettime(CLOCK_MONOTONIC, &t);
+ return t.tv_nsec + ((uint64_t)t.tv_sec * 1000 * 1000 * 1000);
+}
+
+void Context::timerReset()
+{
+ for (int ct=0; ct < _RS_TIMER_TOTAL; ct++) {
+ mTimers[ct] = 0;
+ }
+}
+
+void Context::timerInit()
+{
+ mTimeLast = getTime();
+ mTimerActive = RS_TIMER_INTERNAL;
+ timerReset();
+}
+
+void Context::timerSet(Timers tm)
+{
+ uint64_t last = mTimeLast;
+ mTimeLast = getTime();
+ mTimers[mTimerActive] += mTimeLast - last;
+ mTimerActive = tm;
+}
+
+void Context::timerPrint()
+{
+ double total = 0;
+ for (int ct = 0; ct < _RS_TIMER_TOTAL; ct++) {
+ total += mTimers[ct];
+ }
+
+ LOGV("RS Time Data: Idle %2.1f (%lli), Internal %2.1f (%lli), Script %2.1f (%lli), Clear & Swap %2.1f (%lli)",
+ 100.0 * mTimers[RS_TIMER_IDLE] / total, mTimers[RS_TIMER_IDLE] / 1000000,
+ 100.0 * mTimers[RS_TIMER_INTERNAL] / total, mTimers[RS_TIMER_INTERNAL] / 1000000,
+ 100.0 * mTimers[RS_TIMER_SCRIPT] / total, mTimers[RS_TIMER_SCRIPT] / 1000000,
+ 100.0 * mTimers[RS_TIMER_CLEAR_SWAP] / total, mTimers[RS_TIMER_CLEAR_SWAP] / 1000000);
+}
+
void Context::setupCheck()
{
if (mFragmentStore.get()) {
@@ -168,9 +201,19 @@
if (mDraw) {
mDraw = rsc->runRootScript();
+#if RS_LOG_TIMES
+ rsc->timerSet(RS_TIMER_CLEAR_SWAP);
+#endif
eglSwapBuffers(rsc->mDisplay, rsc->mSurface);
+#if RS_LOG_TIMES
+ rsc->timerSet(RS_TIMER_INTERNAL);
+ rsc->timerPrint();
+ rsc->timerReset();
+#endif
}
- rsc->objDestroyOOBRun();
+ if (rsc->mObjDestroy.mNeedToEmpty) {
+ rsc->objDestroyOOBRun();
+ }
}
glClearColor(0,0,0,0);
@@ -188,9 +231,6 @@
mRunning = false;
mExit = false;
- // see comment in header
- gCon = this;
-
int status;
pthread_attr_t threadAttr;
@@ -213,6 +253,7 @@
mWndSurface = sur;
objDestroyOOBInit();
+ timerInit();
LOGV("RS Launching thread");
status = pthread_create(&mThreadId, &threadAttr, threadProc, this);
diff --git a/libs/rs/rsContext.h b/libs/rs/rsContext.h
index 52901b2..ca67e40 100644
--- a/libs/rs/rsContext.h
+++ b/libs/rs/rsContext.h
@@ -72,8 +72,6 @@
ScriptCState mScriptC;
- static Context * getContext() {return gCon;}
-
void swapBuffers();
void setRootScript(Script *);
void setVertex(ProgramVertex *);
@@ -120,6 +118,20 @@
ThreadIO mIO;
void objDestroyAdd(ObjectBase *);
+ // Timers
+ enum Timers {
+ RS_TIMER_IDLE,
+ RS_TIMER_INTERNAL,
+ RS_TIMER_SCRIPT,
+ RS_TIMER_CLEAR_SWAP,
+ _RS_TIMER_TOTAL
+ };
+ uint64_t getTime() const;
+ void timerInit();
+ void timerReset();
+ void timerSet(Timers);
+ void timerPrint();
+
protected:
Device *mDev;
@@ -164,13 +176,15 @@
static void * threadProc(void *);
- // todo: put in TLS
- static Context *gCon;
Surface *mWndSurface;
Vector<ObjectBase *> mNames;
KeyedVector<String8,int> mInt32Defines;
KeyedVector<String8,float> mFloatDefines;
+
+ uint64_t mTimers[_RS_TIMER_TOTAL];
+ Timers mTimerActive;
+ uint64_t mTimeLast;
};
diff --git a/libs/rs/rsThreadIO.cpp b/libs/rs/rsThreadIO.cpp
index 20b0a94..4a1dbbb 100644
--- a/libs/rs/rsThreadIO.cpp
+++ b/libs/rs/rsThreadIO.cpp
@@ -32,12 +32,18 @@
bool ThreadIO::playCoreCommands(Context *con, bool waitForCommand)
{
- uint32_t cmdID = 0;
- uint32_t cmdSize = 0;
bool ret = false;
while(!mToCore.isEmpty() || waitForCommand) {
+ uint32_t cmdID = 0;
+ uint32_t cmdSize = 0;
ret = true;
+#if RS_LOG_TIMES
+ con->timerSet(Context::RS_TIMER_IDLE);
+#endif
const void * data = mToCore.get(&cmdID, &cmdSize);
+#if RS_LOG_TIMES
+ con->timerSet(Context::RS_TIMER_INTERNAL);
+#endif
waitForCommand = false;
//LOGV("playCoreCommands 3 %i %i", cmdID, cmdSize);
diff --git a/libs/surfaceflinger/LayerBase.cpp b/libs/surfaceflinger/LayerBase.cpp
index 419574c..fd54e35 100644
--- a/libs/surfaceflinger/LayerBase.cpp
+++ b/libs/surfaceflinger/LayerBase.cpp
@@ -730,14 +730,6 @@
return owner;
}
-
-void LayerBaseClient::Surface::getSurfaceData(
- ISurfaceFlingerClient::surface_data_t* params) const
-{
- params->token = mToken;
- params->identity = mIdentity;
-}
-
status_t LayerBaseClient::Surface::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
diff --git a/libs/surfaceflinger/LayerBase.h b/libs/surfaceflinger/LayerBase.h
index 65bf55b..7791941 100644
--- a/libs/surfaceflinger/LayerBase.h
+++ b/libs/surfaceflinger/LayerBase.h
@@ -321,10 +321,9 @@
class Surface : public BnSurface
{
public:
+ int32_t getToken() const { return mToken; }
+ int32_t getIdentity() const { return mIdentity; }
- virtual void getSurfaceData(
- ISurfaceFlingerClient::surface_data_t* params) const;
-
protected:
Surface(const sp<SurfaceFlinger>& flinger,
SurfaceID id, int identity,
diff --git a/libs/surfaceflinger/LayerBitmap.cpp b/libs/surfaceflinger/LayerBitmap.cpp
index 5e74451..dd61e1a 100644
--- a/libs/surfaceflinger/LayerBitmap.cpp
+++ b/libs/surfaceflinger/LayerBitmap.cpp
@@ -97,11 +97,9 @@
err = allocator.alloc(w, h, format, usage, &handle, &stride);
if (err == NO_ERROR) {
- if (err == NO_ERROR) {
- width = w;
- height = h;
- mVStride = 0;
- }
+ width = w;
+ height = h;
+ mVStride = 0;
}
return err;
diff --git a/libs/surfaceflinger/SurfaceFlinger.cpp b/libs/surfaceflinger/SurfaceFlinger.cpp
index 102899c..3824024 100644
--- a/libs/surfaceflinger/SurfaceFlinger.cpp
+++ b/libs/surfaceflinger/SurfaceFlinger.cpp
@@ -1239,9 +1239,11 @@
switch (flags & eFXSurfaceMask) {
case eFXSurfaceNormal:
if (UNLIKELY(flags & ePushBuffers)) {
- layer = createPushBuffersSurfaceLocked(client, d, id, w, h, flags);
+ layer = createPushBuffersSurfaceLocked(client, d, id,
+ w, h, flags);
} else {
- layer = createNormalSurfaceLocked(client, d, id, w, h, format, flags);
+ layer = createNormalSurfaceLocked(client, d, id,
+ w, h, flags, format);
}
break;
case eFXSurfaceBlur:
@@ -1255,8 +1257,13 @@
if (layer != 0) {
setTransactionFlags(eTransactionNeeded);
surfaceHandle = layer->getSurface();
- if (surfaceHandle != 0)
- surfaceHandle->getSurfaceData(params);
+ if (surfaceHandle != 0) {
+ params->token = surfaceHandle->getToken();
+ params->identity = surfaceHandle->getIdentity();
+ params->width = w;
+ params->height = h;
+ params->format = format;
+ }
}
return surfaceHandle;
@@ -1264,7 +1271,8 @@
sp<LayerBaseClient> SurfaceFlinger::createNormalSurfaceLocked(
const sp<Client>& client, DisplayID display,
- int32_t id, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags)
+ int32_t id, uint32_t w, uint32_t h, uint32_t flags,
+ PixelFormat& format)
{
// initialize the surfaces
switch (format) { // TODO: take h/w into account
diff --git a/libs/surfaceflinger/SurfaceFlinger.h b/libs/surfaceflinger/SurfaceFlinger.h
index 2569a0f..56ea97a 100644
--- a/libs/surfaceflinger/SurfaceFlinger.h
+++ b/libs/surfaceflinger/SurfaceFlinger.h
@@ -195,8 +195,8 @@
sp<LayerBaseClient> createNormalSurfaceLocked(
const sp<Client>& client, DisplayID display,
- int32_t id, uint32_t w, uint32_t h,
- PixelFormat format, uint32_t flags);
+ int32_t id, uint32_t w, uint32_t h, uint32_t flags,
+ PixelFormat& format);
sp<LayerBaseClient> createBlurSurfaceLocked(
const sp<Client>& client, DisplayID display,
diff --git a/libs/ui/ISurfaceFlingerClient.cpp b/libs/ui/ISurfaceFlingerClient.cpp
index 51e8422..4a6a1d7 100644
--- a/libs/ui/ISurfaceFlingerClient.cpp
+++ b/libs/ui/ISurfaceFlingerClient.cpp
@@ -189,8 +189,11 @@
status_t ISurfaceFlingerClient::surface_data_t::readFromParcel(const Parcel& parcel)
{
- token = parcel.readInt32();
- identity = parcel.readInt32();
+ token = parcel.readInt32();
+ identity = parcel.readInt32();
+ width = parcel.readInt32();
+ height = parcel.readInt32();
+ format = parcel.readInt32();
return NO_ERROR;
}
@@ -198,6 +201,9 @@
{
parcel->writeInt32(token);
parcel->writeInt32(identity);
+ parcel->writeInt32(width);
+ parcel->writeInt32(height);
+ parcel->writeInt32(format);
return NO_ERROR;
}
diff --git a/libs/ui/Surface.cpp b/libs/ui/Surface.cpp
index f6792c4..36a10cf 100644
--- a/libs/ui/Surface.cpp
+++ b/libs/ui/Surface.cpp
@@ -64,11 +64,16 @@
{
// we own the handle in this case
width = data.readInt32();
- height = data.readInt32();
- stride = data.readInt32();
- format = data.readInt32();
- usage = data.readInt32();
- handle = data.readNativeHandle();
+ if (width < 0) {
+ width = height = stride = format = usage = 0;
+ handle = 0;
+ } else {
+ height = data.readInt32();
+ stride = data.readInt32();
+ format = data.readInt32();
+ usage = data.readInt32();
+ handle = data.readNativeHandle();
+ }
}
SurfaceBuffer::~SurfaceBuffer()
@@ -108,16 +113,25 @@
status_t SurfaceBuffer::writeToParcel(Parcel* reply,
android_native_buffer_t const* buffer)
{
- if (buffer == NULL) {
+ if (buffer == NULL)
return BAD_VALUE;
+
+ if (buffer->width < 0 || buffer->height < 0)
+ return BAD_VALUE;
+
+ status_t err = NO_ERROR;
+ if (buffer->handle == NULL) {
+ // this buffer doesn't have a handle
+ reply->writeInt32(NO_MEMORY);
+ } else {
+ reply->writeInt32(buffer->width);
+ reply->writeInt32(buffer->height);
+ reply->writeInt32(buffer->stride);
+ reply->writeInt32(buffer->format);
+ reply->writeInt32(buffer->usage);
+ err = reply->writeNativeHandle(buffer->handle);
}
- reply->writeInt32(buffer->width);
- reply->writeInt32(buffer->height);
- reply->writeInt32(buffer->stride);
- reply->writeInt32(buffer->format);
- reply->writeInt32(buffer->usage);
- reply->writeNativeHandle(buffer->handle);
- return NO_ERROR;
+ return err;
}
// ----------------------------------------------------------------------
@@ -183,7 +197,8 @@
uint32_t w, uint32_t h, PixelFormat format, uint32_t flags)
: mClient(client), mSurface(surface),
mToken(data.token), mIdentity(data.identity),
- mWidth(w), mHeight(h), mFormat(format), mFlags(flags)
+ mWidth(data.width), mHeight(data.height), mFormat(data.format),
+ mFlags(flags)
{
}
@@ -434,7 +449,7 @@
// this is a client-side operation, the surface is destroyed, unmap
// its buffers in this process.
for (int i=0 ; i<2 ; i++) {
- if (mBuffers[i] != 0) {
+ if (mBuffers[i] != 0 && mBuffers[i]->handle != 0) {
getBufferMapper().unregisterBuffer(mBuffers[i]->handle);
}
}
@@ -590,17 +605,24 @@
if ((back->flags & surface_info_t::eNeedNewBuffer) || mUsageChanged) {
mUsageChanged = false;
err = getBufferLocked(backIdx, mUsage);
+ if (err == NO_ERROR) {
+ // reset the width/height with the what we get from the buffer
+ const sp<SurfaceBuffer>& backBuffer(mBuffers[backIdx]);
+ mWidth = uint32_t(backBuffer->width);
+ mHeight = uint32_t(backBuffer->height);
+ }
}
if (err == NO_ERROR) {
const sp<SurfaceBuffer>& backBuffer(mBuffers[backIdx]);
- // reset the width/height with the what we get from the buffer
- mWidth = uint32_t(backBuffer->width);
- mHeight = uint32_t(backBuffer->height);
- mDirtyRegion.set(backBuffer->width, backBuffer->height);
- *buffer = backBuffer.get();
+ if (backBuffer != 0) {
+ mDirtyRegion.set(backBuffer->width, backBuffer->height);
+ *buffer = backBuffer.get();
+ } else {
+ err = NO_MEMORY;
+ }
}
-
+
return err;
}
@@ -716,7 +738,8 @@
} else {
newDirtyRegion.andSelf(bounds);
const sp<SurfaceBuffer>& frontBuffer(mBuffers[1-mBackbufferIndex]);
- if (backBuffer->width == frontBuffer->width &&
+ if (frontBuffer !=0 &&
+ backBuffer->width == frontBuffer->width &&
backBuffer->height == frontBuffer->height &&
!(lcblk->flags & eNoCopyBack))
{
@@ -788,18 +811,24 @@
if (s == 0) return NO_INIT;
status_t err = NO_MEMORY;
+
+ // free the current buffer
+ sp<SurfaceBuffer>& currentBuffer(mBuffers[index]);
+ if (currentBuffer != 0) {
+ getBufferMapper().unregisterBuffer(currentBuffer->handle);
+ currentBuffer.clear();
+ }
+
sp<SurfaceBuffer> buffer = s->getBuffer(usage);
LOGE_IF(buffer==0, "ISurface::getBuffer() returned NULL");
- if (buffer != 0) {
- sp<SurfaceBuffer>& currentBuffer(mBuffers[index]);
- if (currentBuffer != 0) {
- getBufferMapper().unregisterBuffer(currentBuffer->handle);
- currentBuffer.clear();
- }
- err = getBufferMapper().registerBuffer(buffer->handle);
- LOGW_IF(err, "registerBuffer(...) failed %d (%s)", err, strerror(-err));
- if (err == NO_ERROR) {
- currentBuffer = buffer;
+ if (buffer != 0) { // this should never happen by construction
+ if (buffer->handle != NULL) {
+ err = getBufferMapper().registerBuffer(buffer->handle);
+ LOGW_IF(err, "registerBuffer(...) failed %d (%s)",
+ err, strerror(-err));
+ if (err == NO_ERROR) {
+ currentBuffer = buffer;
+ }
}
}
return err;
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index 05b68d4..0a1b142 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -1391,21 +1391,26 @@
} else if (action.equals(BluetoothIntent.HEADSET_STATE_CHANGED_ACTION)) {
int state = intent.getIntExtra(BluetoothIntent.HEADSET_STATE,
BluetoothHeadset.STATE_ERROR);
- BluetoothDevice btDevice = intent.getParcelableExtra(BluetoothIntent.DEVICE);
- String address = btDevice.getAddress();
int device = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO;
- int btClass = btDevice.getBluetoothClass();
- if (BluetoothClass.Device.Major.getDeviceMajor(btClass) == BluetoothClass.Device.Major.AUDIO_VIDEO) {
- switch (BluetoothClass.Device.getDevice(btClass)) {
- case BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET:
- case BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE:
- device = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_HEADSET;
- break;
- case BluetoothClass.Device.AUDIO_VIDEO_CAR_AUDIO:
- device = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_CARKIT;
- break;
- default:
- break;
+ BluetoothDevice btDevice = intent.getParcelableExtra(BluetoothIntent.DEVICE);
+ String address = null;
+ int btClass = BluetoothClass.ERROR;
+ if (btDevice != null) {
+ address = btDevice.getAddress();
+ btClass = btDevice.getBluetoothClass();
+ if (BluetoothClass.Device.Major.getDeviceMajor(btClass) ==
+ BluetoothClass.Device.Major.AUDIO_VIDEO) {
+ switch (BluetoothClass.Device.getDevice(btClass)) {
+ case BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET:
+ case BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE:
+ device = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_HEADSET;
+ break;
+ case BluetoothClass.Device.AUDIO_VIDEO_CAR_AUDIO:
+ device = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_CARKIT;
+ break;
+ default:
+ break;
+ }
}
}
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index 662d5fb..894d46c 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -19,9 +19,6 @@
#include <arpa/inet.h>
-#undef NDEBUG
-#include <assert.h>
-
#include <ctype.h>
#include <stdint.h>
#include <stdlib.h>
@@ -31,6 +28,7 @@
#include <media/stagefright/MPEG4Extractor.h>
#include <media/stagefright/MediaBuffer.h>
#include <media/stagefright/MediaBufferGroup.h>
+#include <media/stagefright/MediaDebug.h>
#include <media/stagefright/MediaSource.h>
#include <media/stagefright/MetaData.h>
#include <media/stagefright/SampleTable.h>
@@ -70,10 +68,8 @@
MediaBufferGroup *mGroup;
MediaBuffer *mBuffer;
- size_t mBufferOffset;
- size_t mBufferSizeRemaining;
- bool mNeedsNALFraming;
+ bool mWantsNALFragments;
uint8_t *mSrcBuffer;
@@ -138,7 +134,7 @@
return "video/avc";
default:
- assert(!"should not be here.");
+ CHECK(!"should not be here.");
return NULL;
}
}
@@ -279,7 +275,7 @@
return err;
}
}
- assert(*offset == stop_offset);
+ CHECK_EQ(*offset, stop_offset);
if (chunk_type == FOURCC('m', 'o', 'o', 'v')) {
mHaveMetadata = true;
@@ -291,7 +287,7 @@
case FOURCC('t', 'k', 'h', 'd'):
{
- assert(chunk_data_size >= 4);
+ CHECK(chunk_data_size >= 4);
uint8_t version;
if (mDataSource->read_at(data_offset, &version, 1) < 1) {
@@ -444,7 +440,7 @@
}
uint8_t buffer[8];
- assert(chunk_data_size >= (off_t)sizeof(buffer));
+ CHECK(chunk_data_size >= (off_t)sizeof(buffer));
if (mDataSource->read_at(
data_offset, buffer, 8) < 8) {
return ERROR_IO;
@@ -470,7 +466,7 @@
return err;
}
}
- assert(*offset == stop_offset);
+ CHECK_EQ(*offset, stop_offset);
break;
}
@@ -518,7 +514,7 @@
return err;
}
}
- assert(*offset == stop_offset);
+ CHECK_EQ(*offset, stop_offset);
break;
}
@@ -560,7 +556,7 @@
return err;
}
}
- assert(*offset == stop_offset);
+ CHECK_EQ(*offset, stop_offset);
break;
}
@@ -728,16 +724,14 @@
mStarted(false),
mGroup(NULL),
mBuffer(NULL),
- mBufferOffset(0),
- mBufferSizeRemaining(0),
- mNeedsNALFraming(false),
+ mWantsNALFragments(false),
mSrcBuffer(NULL) {
const char *mime;
bool success = mFormat->findCString(kKeyMIMEType, &mime);
- assert(success);
+ CHECK(success);
success = mFormat->findInt32(kKeyTimeScale, &mTimescale);
- assert(success);
+ CHECK(success);
mIsAVC = !strcasecmp(mime, "video/avc");
}
@@ -749,21 +743,21 @@
}
status_t MPEG4Source::start(MetaData *params) {
- assert(!mStarted);
+ CHECK(!mStarted);
int32_t val;
- if (mIsAVC && params && params->findInt32(kKeyNeedsNALFraming, &val)
+ if (params && params->findInt32(kKeyWantsNALFragments, &val)
&& val != 0) {
- mNeedsNALFraming = true;
+ mWantsNALFragments = true;
} else {
- mNeedsNALFraming = false;
+ mWantsNALFragments = false;
}
mGroup = new MediaBufferGroup;
size_t max_size;
status_t err = mSampleTable->getMaxSampleSize(&max_size);
- assert(err == OK);
+ CHECK_EQ(err, OK);
// Assume that a given buffer only contains at most 10 fragments,
// each fragment originally prefixed with a 2 byte length will
@@ -779,7 +773,7 @@
}
status_t MPEG4Source::stop() {
- assert(mStarted);
+ CHECK(mStarted);
if (mBuffer != NULL) {
mBuffer->release();
@@ -804,7 +798,7 @@
status_t MPEG4Source::read(
MediaBuffer **out, const ReadOptions *options) {
- assert(mStarted);
+ CHECK(mStarted);
*out = NULL;
@@ -830,38 +824,124 @@
off_t offset;
size_t size;
- status_t err = mSampleTable->getSampleOffsetAndSize(
- mCurrentSampleIndex, &offset, &size);
-
- if (err != OK) {
- return err;
- }
-
uint32_t dts;
- err = mSampleTable->getDecodingTime(mCurrentSampleIndex, &dts);
+ bool newBuffer = false;
+ if (mBuffer == NULL) {
+ newBuffer = true;
- if (err != OK) {
- return err;
+ status_t err = mSampleTable->getSampleOffsetAndSize(
+ mCurrentSampleIndex, &offset, &size);
+
+ if (err != OK) {
+ return err;
+ }
+
+ err = mSampleTable->getDecodingTime(mCurrentSampleIndex, &dts);
+
+ if (err != OK) {
+ return err;
+ }
+
+ err = mGroup->acquire_buffer(&mBuffer);
+ if (err != OK) {
+ CHECK_EQ(mBuffer, NULL);
+ return err;
+ }
}
- err = mGroup->acquire_buffer(&mBuffer);
- if (err != OK) {
- assert(mBuffer == NULL);
- return err;
- }
+ if (!mIsAVC || mWantsNALFragments) {
+ if (newBuffer) {
+ ssize_t num_bytes_read =
+ mDataSource->read_at(offset, (uint8_t *)mBuffer->data(), size);
- if (!mIsAVC || !mNeedsNALFraming) {
+ if (num_bytes_read < (ssize_t)size) {
+ mBuffer->release();
+ mBuffer = NULL;
+
+ return ERROR_IO;
+ }
+
+ mBuffer->set_range(0, size);
+ mBuffer->meta_data()->clear();
+ mBuffer->meta_data()->setInt32(kKeyTimeUnits, dts);
+ mBuffer->meta_data()->setInt32(kKeyTimeScale, mTimescale);
+ ++mCurrentSampleIndex;
+ }
+
+ if (!mIsAVC) {
+ *out = mBuffer;
+ mBuffer = NULL;
+
+ return OK;
+ }
+
+ // Each NAL unit is split up into its constituent fragments and
+ // each one of them returned in its own buffer.
+
+ CHECK(mBuffer->range_length() >= 2);
+
+ const uint8_t *src =
+ (const uint8_t *)mBuffer->data() + mBuffer->range_offset();
+
+ size_t nal_size = U16_AT(src);
+
+ CHECK(mBuffer->range_length() >= 2 + nal_size);
+
+ MediaBuffer *clone = mBuffer->clone();
+ clone->set_range(mBuffer->range_offset() + 2, nal_size);
+
+ mBuffer->set_range(
+ mBuffer->range_offset() + 2 + nal_size,
+ mBuffer->range_length() - 2 - nal_size);
+
+ if (mBuffer->range_length() == 0) {
+ mBuffer->release();
+ mBuffer = NULL;
+ }
+
+ *out = clone;
+
+ return OK;
+ } else {
+ // Whole NAL units are returned but each fragment is prefixed by
+ // the start code (0x00 00 00 01).
+
ssize_t num_bytes_read =
- mDataSource->read_at(offset, (uint8_t *)mBuffer->data(), size);
+ mDataSource->read_at(offset, mSrcBuffer, size);
if (num_bytes_read < (ssize_t)size) {
mBuffer->release();
mBuffer = NULL;
- return err;
+ return ERROR_IO;
}
- mBuffer->set_range(0, size);
+ uint8_t *dstData = (uint8_t *)mBuffer->data();
+ size_t srcOffset = 0;
+ size_t dstOffset = 0;
+ while (srcOffset < size) {
+ CHECK(srcOffset + 1 < size);
+ size_t nalLength =
+ (mSrcBuffer[srcOffset] << 8) | mSrcBuffer[srcOffset + 1];
+ CHECK(srcOffset + 1 + nalLength < size);
+ srcOffset += 2;
+
+ if (nalLength == 0) {
+ continue;
+ }
+
+ CHECK(dstOffset + 4 <= mBuffer->size());
+
+ dstData[dstOffset++] = 0;
+ dstData[dstOffset++] = 0;
+ dstData[dstOffset++] = 0;
+ dstData[dstOffset++] = 1;
+ memcpy(&dstData[dstOffset], &mSrcBuffer[srcOffset], nalLength);
+ srcOffset += nalLength;
+ dstOffset += nalLength;
+ }
+
+ mBuffer->set_range(0, dstOffset);
mBuffer->meta_data()->clear();
mBuffer->meta_data()->setInt32(kKeyTimeUnits, dts);
mBuffer->meta_data()->setInt32(kKeyTimeScale, mTimescale);
@@ -872,52 +952,6 @@
return OK;
}
-
- ssize_t num_bytes_read =
- mDataSource->read_at(offset, mSrcBuffer, size);
-
- if (num_bytes_read < (ssize_t)size) {
- mBuffer->release();
- mBuffer = NULL;
-
- return err;
- }
-
- uint8_t *dstData = (uint8_t *)mBuffer->data();
- size_t srcOffset = 0;
- size_t dstOffset = 0;
- while (srcOffset < size) {
- assert(srcOffset + 1 < size);
- size_t nalLength =
- (mSrcBuffer[srcOffset] << 8) | mSrcBuffer[srcOffset + 1];
- assert(srcOffset + 1 + nalLength < size);
- srcOffset += 2;
-
- if (nalLength == 0) {
- continue;
- }
-
- assert(dstOffset + 4 <= mBuffer->size());
-
- dstData[dstOffset++] = 0;
- dstData[dstOffset++] = 0;
- dstData[dstOffset++] = 0;
- dstData[dstOffset++] = 1;
- memcpy(&dstData[dstOffset], &mSrcBuffer[srcOffset], nalLength);
- srcOffset += nalLength;
- dstOffset += nalLength;
- }
-
- mBuffer->set_range(0, dstOffset);
- mBuffer->meta_data()->clear();
- mBuffer->meta_data()->setInt32(kKeyTimeUnits, dts);
- mBuffer->meta_data()->setInt32(kKeyTimeScale, mTimescale);
- ++mCurrentSampleIndex;
-
- *out = mBuffer;
- mBuffer = NULL;
-
- return OK;
}
bool SniffMPEG4(
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 35d599c..ec9f6d3 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -30,6 +30,7 @@
#include <media/stagefright/MetaData.h>
#include <media/stagefright/MmapSource.h>
#include <media/stagefright/OMXCodec.h>
+#include <media/stagefright/Utils.h>
#include <utils/Vector.h>
#include <OMX_Audio.h>
@@ -116,6 +117,39 @@
return NULL;
}
+enum {
+ kAVCProfileBaseline = 0x42,
+ kAVCProfileMain = 0x4d,
+ kAVCProfileExtended = 0x58,
+ kAVCProfileHigh = 0x64,
+ kAVCProfileHigh10 = 0x6e,
+ kAVCProfileHigh422 = 0x7a,
+ kAVCProfileHigh444 = 0xf4,
+ kAVCProfileCAVLC444Intra = 0x2c
+};
+
+static const char *AVCProfileToString(uint8_t profile) {
+ switch (profile) {
+ case kAVCProfileBaseline:
+ return "Baseline";
+ case kAVCProfileMain:
+ return "Main";
+ case kAVCProfileExtended:
+ return "Extended";
+ case kAVCProfileHigh:
+ return "High";
+ case kAVCProfileHigh10:
+ return "High 10";
+ case kAVCProfileHigh422:
+ return "High 422";
+ case kAVCProfileHigh444:
+ return "High 444";
+ case kAVCProfileCAVLC444Intra:
+ return "CAVLC 444 Intra";
+ default: return "Unknown";
+ }
+}
+
// static
sp<OMXCodec> OMXCodec::Create(
const sp<IOMX> &omx,
@@ -152,7 +186,7 @@
uint32_t quirks = 0;
if (!strcmp(componentName, "OMX.PV.avcdec")) {
- quirks |= kWantsRawNALFrames;
+ quirks |= kWantsNALFragments;
}
if (!strcmp(componentName, "OMX.TI.MP3.decode")) {
quirks |= kNeedsFlushBeforeDisable;
@@ -189,29 +223,72 @@
} else if (meta->findData(kKeyAVCC, &type, &data, &size)) {
printf("found avcc of size %d\n", size);
- const uint8_t *ptr = (const uint8_t *)data + 6;
+ // Parse the AVCDecoderConfigurationRecord
+
+ const uint8_t *ptr = (const uint8_t *)data;
+
+ CHECK(size >= 7);
+ CHECK_EQ(ptr[0], 1); // configurationVersion == 1
+ uint8_t profile = ptr[1];
+ uint8_t level = ptr[3];
+
+ CHECK((ptr[4] >> 2) == 0x3f); // reserved
+
+ size_t lengthSize = 1 + (ptr[4] & 3);
+
+ // commented out check below as H264_QVGA_500_NO_AUDIO.3gp
+ // violates it...
+ // CHECK((ptr[5] >> 5) == 7); // reserved
+
+ size_t numSeqParameterSets = ptr[5] & 31;
+
+ ptr += 6;
size -= 6;
- while (size >= 2) {
- size_t length = ptr[0] << 8 | ptr[1];
+
+ for (size_t i = 0; i < numSeqParameterSets; ++i) {
+ CHECK(size >= 2);
+ size_t length = U16_AT(ptr);
ptr += 2;
size -= 2;
- // printf("length = %d, size = %d\n", length, size);
-
CHECK(size >= length);
codec->addCodecSpecificData(ptr, length);
ptr += length;
size -= length;
+ }
- if (size <= 1) {
- break;
- }
+ CHECK(size >= 1);
+ size_t numPictureParameterSets = *ptr;
+ ++ptr;
+ --size;
- ptr++; // XXX skip trailing 0x01 byte???
- --size;
+ for (size_t i = 0; i < numPictureParameterSets; ++i) {
+ CHECK(size >= 2);
+ size_t length = U16_AT(ptr);
+
+ ptr += 2;
+ size -= 2;
+
+ CHECK(size >= length);
+
+ codec->addCodecSpecificData(ptr, length);
+
+ ptr += length;
+ size -= length;
+ }
+
+ LOGI("AVC profile = %d (%s), level = %d",
+ (int)profile, AVCProfileToString(profile), (int)level / 10);
+
+ if (!strcmp(componentName, "OMX.TI.Video.Decoder")
+ && (profile != kAVCProfileBaseline || level > 39)) {
+ // This stream exceeds the decoder's capabilities.
+
+ LOGE("Profile and/or level exceed the decoder's capabilities.");
+ return NULL;
}
}
@@ -225,7 +302,7 @@
int32_t width, height;
bool success = meta->findInt32(kKeyWidth, &width);
success = success && meta->findInt32(kKeyHeight, &height);
- assert(success);
+ CHECK(success);
if (createEncoder) {
codec->setVideoInputFormat(mime, width, height);
@@ -244,9 +321,16 @@
int32_t width, height;
bool success = meta->findInt32(kKeyWidth, &width);
success = success && meta->findInt32(kKeyHeight, &height);
- assert(success);
+
+ int32_t compressedSize;
+ success = success && meta->findInt32(
+ kKeyCompressedSize, &compressedSize);
+
+ CHECK(success);
+ CHECK(compressedSize > 0);
codec->setImageOutputFormat(format, width, height);
+ codec->setJPEGInputFormat(width, height, (OMX_U32)compressedSize);
}
codec->initOutputFormat(meta);
@@ -278,7 +362,7 @@
}
// The following assertion is violated by TI's video decoder.
- // assert(format.nIndex == index);
+ // CHECK_EQ(format.nIndex, index);
#if 1
LOGI("portIndex: %ld, index: %ld, eCompressionFormat=%d eColorFormat=%d",
@@ -529,7 +613,7 @@
OMXCodec::OMXCodec(
const sp<IOMX> &omx, IOMX::node_id node, uint32_t quirks,
- bool isEncoder,
+ bool isEncoder,
const char *mime,
const char *componentName,
const sp<MediaSource> &source)
@@ -541,7 +625,6 @@
mComponentName(strdup(componentName)),
mSource(source),
mCodecSpecificDataIndex(0),
- mDealer(new MemoryDealer(5 * 1024 * 1024)),
mState(LOADED),
mSignalledEOS(false),
mNoMoreOutputData(false),
@@ -554,7 +637,7 @@
}
OMXCodec::~OMXCodec() {
- CHECK_EQ(mState, LOADED);
+ CHECK(mState == LOADED || mState == ERROR);
status_t err = mOMX->observe_node(mNode, NULL);
CHECK_EQ(err, OK);
@@ -569,7 +652,7 @@
free(mComponentName);
mComponentName = NULL;
-
+
free(mMIME);
mMIME = NULL;
}
@@ -639,8 +722,11 @@
return err;
}
+ size_t totalSize = def.nBufferCountActual * def.nBufferSize;
+ mDealer[portIndex] = new MemoryDealer(totalSize);
+
for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) {
- sp<IMemory> mem = mDealer->allocate(def.nBufferSize);
+ sp<IMemory> mem = mDealer[portIndex]->allocate(def.nBufferSize);
CHECK(mem.get() != NULL);
IOMX::buffer_id buffer;
@@ -772,7 +858,7 @@
mBufferFilled.signal();
} else if (mPortStatus[kPortIndexOutput] != SHUTTING_DOWN) {
CHECK_EQ(mPortStatus[kPortIndexOutput], ENABLED);
-
+
MediaBuffer *buffer = info->mMediaBuffer;
buffer->set_range(
@@ -1149,8 +1235,8 @@
size_t size = specific->mSize;
- if (!strcasecmp(mMIME, "video/avc")
- && !(mQuirks & kWantsRawNALFrames)) {
+ if (!strcasecmp("video/avc", mMIME)
+ && !(mQuirks & kWantsNALFragments)) {
static const uint8_t kNALStartCode[4] =
{ 0x00, 0x00, 0x00, 0x01 };
@@ -1383,7 +1469,7 @@
CHECK_EQ(def.eDomain, OMX_PortDomainImage);
OMX_IMAGE_PORTDEFINITIONTYPE *imageDef = &def.format.image;
-
+
CHECK_EQ(imageDef->eCompressionFormat, OMX_IMAGE_CodingUnused);
imageDef->eColorFormat = format;
imageDef->nFrameWidth = width;
@@ -1414,23 +1500,33 @@
break;
}
+ def.nBufferCountActual = def.nBufferCountMin;
+
err = mOMX->set_parameter(
mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
CHECK_EQ(err, OK);
+}
- ////
-
+void OMXCodec::setJPEGInputFormat(
+ OMX_U32 width, OMX_U32 height, OMX_U32 compressedSize) {
+ OMX_PARAM_PORTDEFINITIONTYPE def;
+ def.nSize = sizeof(def);
+ def.nVersion.s.nVersionMajor = 1;
+ def.nVersion.s.nVersionMinor = 1;
def.nPortIndex = kPortIndexInput;
- err = mOMX->get_parameter(
+ status_t err = mOMX->get_parameter(
mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
CHECK_EQ(err, OK);
+ CHECK_EQ(def.eDomain, OMX_PortDomainImage);
+ OMX_IMAGE_PORTDEFINITIONTYPE *imageDef = &def.format.image;
+
CHECK_EQ(imageDef->eCompressionFormat, OMX_IMAGE_CodingJPEG);
imageDef->nFrameWidth = width;
imageDef->nFrameHeight = height;
- def.nBufferSize = 128 * 1024;
+ def.nBufferSize = compressedSize;
def.nBufferCountActual = def.nBufferCountMin;
err = mOMX->set_parameter(
@@ -1460,10 +1556,10 @@
if (mState != LOADED) {
return UNKNOWN_ERROR;
}
-
+
sp<MetaData> params = new MetaData;
- if (!strcasecmp(mMIME, "video/avc") && !(mQuirks & kWantsRawNALFrames)) {
- params->setInt32(kKeyNeedsNALFraming, true);
+ if (mQuirks & kWantsNALFragments) {
+ params->setInt32(kKeyWantsNALFragments, true);
}
status_t err = mSource->start(params.get());
@@ -1481,7 +1577,7 @@
}
status_t OMXCodec::stop() {
- LOGI("stop");
+ LOGV("stop");
Mutex::Autolock autoLock(mLock);
@@ -1630,7 +1726,7 @@
"OMX_COLOR_Format16bitBGR565",
"OMX_COLOR_Format18bitRGB666",
"OMX_COLOR_Format18bitARGB1665",
- "OMX_COLOR_Format19bitARGB1666",
+ "OMX_COLOR_Format19bitARGB1666",
"OMX_COLOR_Format24bitRGB888",
"OMX_COLOR_Format24bitBGR888",
"OMX_COLOR_Format24bitARGB1887",
@@ -1653,11 +1749,11 @@
"OMX_COLOR_FormatRawBayer8bit",
"OMX_COLOR_FormatRawBayer10bit",
"OMX_COLOR_FormatRawBayer8bitcompressed",
- "OMX_COLOR_FormatL2",
- "OMX_COLOR_FormatL4",
- "OMX_COLOR_FormatL8",
- "OMX_COLOR_FormatL16",
- "OMX_COLOR_FormatL24",
+ "OMX_COLOR_FormatL2",
+ "OMX_COLOR_FormatL4",
+ "OMX_COLOR_FormatL8",
+ "OMX_COLOR_FormatL16",
+ "OMX_COLOR_FormatL24",
"OMX_COLOR_FormatL32",
"OMX_COLOR_FormatYUV420PackedSemiPlanar",
"OMX_COLOR_FormatYUV422PackedSemiPlanar",
diff --git a/media/libstagefright/OMXDecoder.cpp b/media/libstagefright/OMXDecoder.cpp
index 94cca43..cf08fa5 100644
--- a/media/libstagefright/OMXDecoder.cpp
+++ b/media/libstagefright/OMXDecoder.cpp
@@ -139,7 +139,7 @@
uint32_t quirks = 0;
if (!strcmp(codec, "OMX.PV.avcdec")) {
- quirks |= kWantsRawNALFrames;
+ quirks |= kWantsNALFragments;
}
if (!strcmp(codec, "OMX.TI.AAC.decode")
|| !strcmp(codec, "OMX.TI.MP3.decode")) {
@@ -274,8 +274,8 @@
// mDealer->dump("Decoder Dealer");
sp<MetaData> params = new MetaData;
- if (mIsAVC && !(mQuirks & kWantsRawNALFrames)) {
- params->setInt32(kKeyNeedsNALFraming, true);
+ if (mQuirks & kWantsNALFragments) {
+ params->setInt32(kKeyWantsNALFragments, true);
}
status_t err = mSource->start(params.get());
@@ -1331,7 +1331,7 @@
size_t range_length = 0;
- if (mIsAVC && !(mQuirks & kWantsRawNALFrames)) {
+ if (mIsAVC && !(mQuirks & kWantsNALFragments)) {
assert((*mCodecSpecificDataIterator).size + 4 <= mem->size());
memcpy(mem->pointer(), kNALStartCode, 4);
diff --git a/obex/javax/obex/ObexHelper.java b/obex/javax/obex/ObexHelper.java
index f569595..1b66662 100644
--- a/obex/javax/obex/ObexHelper.java
+++ b/obex/javax/obex/ObexHelper.java
@@ -897,6 +897,11 @@
if (lower < 0) {
lower += 256;
}
+ // If upper and lower both equal 0, it should be the end of string.
+ // Ignore left bytes from array to avoid potential issues
+ if (upper == 0 && lower == 0) {
+ return new String(c, 0, i);
+ }
c[i] = (char)((upper << 8) | lower);
}
diff --git a/obex/javax/obex/ServerSession.java b/obex/javax/obex/ServerSession.java
index 423d5a7..675272d 100644
--- a/obex/javax/obex/ServerSession.java
+++ b/obex/javax/obex/ServerSession.java
@@ -168,7 +168,7 @@
} else {
response = validateResponseCode(mListener.onPut(op));
}
- if (response != ResponseCodes.OBEX_HTTP_OK) {
+ if (response != ResponseCodes.OBEX_HTTP_OK && !op.isAborted) {
op.sendReply(response);
} else if (!op.isAborted) {
// wait for the final bit
diff --git a/opengl/libagl/egl.cpp b/opengl/libagl/egl.cpp
index 0762ebf..9c0f7fd 100644
--- a/opengl/libagl/egl.cpp
+++ b/opengl/libagl/egl.cpp
@@ -141,7 +141,8 @@
egl_surface_t(EGLDisplay dpy, EGLConfig config, int32_t depthFormat);
virtual ~egl_surface_t();
- virtual bool isValid() const = 0;
+ bool isValid() const;
+ virtual bool initCheck() const = 0;
virtual EGLBoolean bindDrawSurface(ogles_context_t* gl) = 0;
virtual EGLBoolean bindReadSurface(ogles_context_t* gl) = 0;
@@ -175,6 +176,11 @@
magic = 0;
free(depth.data);
}
+bool egl_surface_t::isValid() const {
+ LOGE_IF(magic != MAGIC, "invalid EGLSurface (%p)", this);
+ return magic == MAGIC;
+}
+
EGLBoolean egl_surface_t::swapBuffers() {
return EGL_FALSE;
}
@@ -208,9 +214,9 @@
int32_t depthFormat,
android_native_window_t* window);
- ~egl_window_surface_v2_t();
+ ~egl_window_surface_v2_t();
- virtual bool isValid() const { return nativeWindow->common.magic == ANDROID_NATIVE_WINDOW_MAGIC; }
+ virtual bool initCheck() const { return true; } // TODO: report failure if ctor fails
virtual EGLBoolean swapBuffers();
virtual EGLBoolean bindDrawSurface(ogles_context_t* gl);
virtual EGLBoolean bindReadSurface(ogles_context_t* gl);
@@ -704,7 +710,7 @@
virtual ~egl_pixmap_surface_t() { }
- virtual bool isValid() const { return nativePixmap.version == sizeof(egl_native_pixmap_t); }
+ virtual bool initCheck() const { return !depth.format || depth.data!=0; }
virtual EGLBoolean bindDrawSurface(ogles_context_t* gl);
virtual EGLBoolean bindReadSurface(ogles_context_t* gl);
virtual EGLint getWidth() const { return nativePixmap.width; }
@@ -726,7 +732,6 @@
depth.data = (GGLubyte*)malloc(depth.stride*depth.height*2);
if (depth.data == 0) {
setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
- return;
}
}
}
@@ -768,7 +773,7 @@
virtual ~egl_pbuffer_surface_t();
- virtual bool isValid() const { return pbuffer.data != 0; }
+ virtual bool initCheck() const { return pbuffer.data != 0; }
virtual EGLBoolean bindDrawSurface(ogles_context_t* gl);
virtual EGLBoolean bindReadSurface(ogles_context_t* gl);
virtual EGLint getWidth() const { return pbuffer.width; }
@@ -1196,6 +1201,11 @@
if (!(surfaceType & EGL_WINDOW_BIT))
return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
+ if (static_cast<android_native_window_t*>(window)->common.magic !=
+ ANDROID_NATIVE_WINDOW_MAGIC) {
+ return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
+ }
+
EGLint configID;
if (getConfigAttrib(dpy, config, EGL_CONFIG_ID, &configID) == EGL_FALSE)
return EGL_FALSE;
@@ -1241,7 +1251,7 @@
surface = new egl_window_surface_v2_t(dpy, config, depthFormat,
static_cast<android_native_window_t*>(window));
- if (!surface->isValid()) {
+ if (!surface->initCheck()) {
// there was a problem in the ctor, the error
// flag has been set.
delete surface;
@@ -1265,6 +1275,11 @@
if (!(surfaceType & EGL_PIXMAP_BIT))
return setError(EGL_BAD_MATCH, EGL_NO_SURFACE);
+ if (static_cast<egl_native_pixmap_t*>(pixmap)->version !=
+ sizeof(egl_native_pixmap_t)) {
+ return setError(EGL_BAD_NATIVE_PIXMAP, EGL_NO_SURFACE);
+ }
+
EGLint configID;
if (getConfigAttrib(dpy, config, EGL_CONFIG_ID, &configID) == EGL_FALSE)
return EGL_FALSE;
@@ -1307,7 +1322,7 @@
new egl_pixmap_surface_t(dpy, config, depthFormat,
static_cast<egl_native_pixmap_t*>(pixmap));
- if (!surface->isValid()) {
+ if (!surface->initCheck()) {
// there was a problem in the ctor, the error
// flag has been set.
delete surface;
@@ -1375,7 +1390,7 @@
egl_surface_t* surface =
new egl_pbuffer_surface_t(dpy, config, depthFormat, w, h, pixelFormat);
- if (!surface->isValid()) {
+ if (!surface->initCheck()) {
// there was a problem in the ctor, the error
// flag has been set.
delete surface;
@@ -1590,7 +1605,7 @@
return setError(EGL_BAD_DISPLAY, EGL_FALSE);
if (eglSurface != EGL_NO_SURFACE) {
egl_surface_t* surface( static_cast<egl_surface_t*>(eglSurface) );
- if (surface->magic != egl_surface_t::MAGIC)
+ if (!surface->isValid())
return setError(EGL_BAD_SURFACE, EGL_FALSE);
if (surface->dpy != dpy)
return setError(EGL_BAD_DISPLAY, EGL_FALSE);
@@ -1610,6 +1625,8 @@
if (egl_display_t::is_valid(dpy) == EGL_FALSE)
return setError(EGL_BAD_DISPLAY, EGL_FALSE);
egl_surface_t* surface = static_cast<egl_surface_t*>(eglSurface);
+ if (!surface->isValid())
+ return setError(EGL_BAD_SURFACE, EGL_FALSE);
if (surface->dpy != dpy)
return setError(EGL_BAD_DISPLAY, EGL_FALSE);
@@ -1702,9 +1719,19 @@
return setError(EGL_BAD_DISPLAY, EGL_FALSE);
if (draw) {
egl_surface_t* s = (egl_surface_t*)draw;
+ if (!s->isValid())
+ return setError(EGL_BAD_SURFACE, EGL_FALSE);
if (s->dpy != dpy)
return setError(EGL_BAD_DISPLAY, EGL_FALSE);
- // TODO: check that draw and read are compatible with the context
+ // TODO: check that draw is compatible with the context
+ }
+ if (read && read!=draw) {
+ egl_surface_t* s = (egl_surface_t*)read;
+ if (!s->isValid())
+ return setError(EGL_BAD_SURFACE, EGL_FALSE);
+ if (s->dpy != dpy)
+ return setError(EGL_BAD_DISPLAY, EGL_FALSE);
+ // TODO: check that read is compatible with the context
}
EGLContext current_ctx = EGL_NO_CONTEXT;
@@ -1737,7 +1764,8 @@
egl_surface_t* r = (egl_surface_t*)read;
if (c->draw) {
- reinterpret_cast<egl_surface_t*>(c->draw)->disconnect();
+ egl_surface_t* s = reinterpret_cast<egl_surface_t*>(c->draw);
+ s->disconnect();
}
if (c->read) {
// FIXME: unlock/disconnect the read surface too
@@ -1860,6 +1888,8 @@
return setError(EGL_BAD_DISPLAY, EGL_FALSE);
egl_surface_t* d = static_cast<egl_surface_t*>(draw);
+ if (!d->isValid())
+ return setError(EGL_BAD_SURFACE, EGL_FALSE);
if (d->dpy != dpy)
return setError(EGL_BAD_DISPLAY, EGL_FALSE);
@@ -2073,6 +2103,8 @@
return setError(EGL_BAD_DISPLAY, EGL_FALSE);
egl_surface_t* d = static_cast<egl_surface_t*>(draw);
+ if (!d->isValid())
+ return setError(EGL_BAD_SURFACE, EGL_FALSE);
if (d->dpy != dpy)
return setError(EGL_BAD_DISPLAY, EGL_FALSE);
@@ -2088,6 +2120,8 @@
return setError(EGL_BAD_DISPLAY, (EGLClientBuffer)0);
egl_surface_t* d = static_cast<egl_surface_t*>(draw);
+ if (!d->isValid())
+ return setError(EGL_BAD_SURFACE, (EGLClientBuffer)0);
if (d->dpy != dpy)
return setError(EGL_BAD_DISPLAY, (EGLClientBuffer)0);
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index 72a1192..df37d35 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -513,7 +513,8 @@
mNetRequestersPids[usedNetworkType].add(currentPid);
}
- if (ni.isConnectedOrConnecting() == true) {
+ if ((ni.isConnectedOrConnecting() == true) &&
+ !network.isTeardownRequested()) {
if (ni.isConnected() == true) {
// add the pid-specific dns
handleDnsConfigurationChange();
@@ -686,6 +687,7 @@
++numConnectedNets;
}
}
+ if (DBG) Log.d(TAG, "numConnectedNets returning "+numConnectedNets);
return numConnectedNets;
}
@@ -792,7 +794,8 @@
if (newNet.isAvailable()) {
NetworkInfo switchTo = newNet.getNetworkInfo();
switchTo.setFailover(true);
- if (!switchTo.isConnectedOrConnecting()) {
+ if (!switchTo.isConnectedOrConnecting() ||
+ newNet.isTeardownRequested()) {
newNet.reconnect();
}
if (DBG) {
diff --git a/services/java/com/android/server/HardwareService.java b/services/java/com/android/server/HardwareService.java
index 7597f85..6ac72e0 100755
--- a/services/java/com/android/server/HardwareService.java
+++ b/services/java/com/android/server/HardwareService.java
@@ -141,8 +141,11 @@
!= PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("Requires VIBRATE permission");
}
- if (mCurrentVibration != null
- && mCurrentVibration.hasLongerTimeout(milliseconds)) {
+ // We're running in the system server so we cannot crash. Check for a
+ // timeout of 0 or negative. This will ensure that a vibration has
+ // either a timeout of > 0 or a non-null pattern.
+ if (milliseconds <= 0 || (mCurrentVibration != null
+ && mCurrentVibration.hasLongerTimeout(milliseconds))) {
// Ignore this vibration since the current vibration will play for
// longer than milliseconds.
return;
diff --git a/services/java/com/android/server/TelephonyRegistry.java b/services/java/com/android/server/TelephonyRegistry.java
index 7379b5d..170a9f8 100644
--- a/services/java/com/android/server/TelephonyRegistry.java
+++ b/services/java/com/android/server/TelephonyRegistry.java
@@ -535,9 +535,12 @@
intent.putExtra(Phone.STATE_CHANGE_REASON_KEY, reason);
}
intent.putExtra(Phone.DATA_APN_KEY, apn);
- String types = apnTypes[0];
- for (int i = 1; i < apnTypes.length; i++) {
- types = types+","+apnTypes[i];
+ String types = new String("");
+ if (apnTypes.length > 0) {
+ types = apnTypes[0];
+ for (int i = 1; i < apnTypes.length; i++) {
+ types = types+","+apnTypes[i];
+ }
}
intent.putExtra(Phone.DATA_APN_TYPES_KEY, types);
intent.putExtra(Phone.DATA_IFACE_NAME_KEY, interfaceName);
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index a00a756..7ca8b52 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -405,6 +405,7 @@
// If non-null, this is the currently visible window that is associated
// with the wallpaper.
WindowState mWallpaperTarget = null;
+ WindowState mUpcomingWallpaperTarget = null;
int mWallpaperAnimLayerAdjustment;
AppWindowToken mFocusedApp = null;
@@ -1178,60 +1179,136 @@
boolean adjustWallpaperWindowsLocked() {
boolean changed = false;
+ mUpcomingWallpaperTarget = null;
+
// First find top-most window that has asked to be on top of the
// wallpaper; all wallpapers go behind it.
final ArrayList localmWindows = mWindows;
int N = localmWindows.size();
WindowState w = null;
+ WindowState foundW = null;
+ int foundI = 0;
+ AppWindowToken topToken = null;
+ AppWindowToken behindToken = null;
int i = N;
- boolean visible = false;
while (i > 0) {
i--;
w = (WindowState)localmWindows.get(i);
+ if (topToken != null) {
+ if (w.mAppToken == topToken) {
+ continue;
+ }
+ if (w.mAppToken != null) {
+ if (behindToken == null) {
+ // We need to look through for what is behind the
+ // potential new wallpaper target... skip all tokens
+ // that are hidden and not animating, since they can't
+ // be involved with the transition.
+ if (w.mAppToken.hidden && w.mAppToken.animation == null) {
+ continue;
+ }
+ behindToken = w.mAppToken;
+ }
+ if (w.mAppToken != behindToken) {
+ break;
+ }
+ }
+ }
if ((w.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0 && w.isReadyForDisplay()
&& !w.mDrawPending && !w.mCommitDrawPending) {
- visible = true;
+ if (behindToken != null && w.mAppToken == behindToken) {
+ // We had previously found a wallpaper window that was
+ // animating, and now we found one behind it. We could
+ // be doing an animation between two windows on top of
+ // the wallpaper!
+ if (mWallpaperTarget == w || mWallpaperTarget == foundW) {
+ // Retain the current wallpaper target (don't move
+ // the wallpaper yet), but note the window that is
+ // going to become the wallpaper target so that
+ // others know about this special state.
+ if (DEBUG_WALLPAPER) Log.v(TAG,
+ "Switching wallpaper activities: cur#" + i + "="
+ + w + " upcoming#" + foundI + "=" + foundW);
+ mUpcomingWallpaperTarget = foundW;
+ foundW = w;
+ foundI = i;
+ break;
+ }
+ }
+ foundW = w;
+ foundI = i;
+ if (w.mAppToken != null && w.mAppToken.animation != null) {
+ // If this app token is animating, we want to keep the
+ // wallpaper below it if it is animating on top of another
+ // app with a wallpaper.
+ topToken = w.mAppToken;
+ continue;
+ }
break;
}
}
- if (!visible) w = null;
- if (DEBUG_WALLPAPER && mWallpaperTarget != w) {
- Log.v(TAG, "New wallpaper target: " + w);
+ if (mNextAppTransition != WindowManagerPolicy.TRANSIT_NONE) {
+ // If we are currently waiting for an app transition, and either
+ // the current target or the next target are involved with it,
+ // then hold off on doing anything with the wallpaper.
+ // Note that we are checking here for just whether the target
+ // is part of an app token... which is potentially overly aggressive
+ // (the app token may not be involved in the transition), but good
+ // enough (we'll just wait until whatever transition is pending
+ // executes).
+ if (mWallpaperTarget != null && mWallpaperTarget.mAppToken != null) {
+ return false;
+ }
+ if (foundW != null && foundW.mAppToken != null) {
+ return false;
+ }
+ if (mUpcomingWallpaperTarget != null && mUpcomingWallpaperTarget.mAppToken != null) {
+ return false;
+ }
}
- mWallpaperTarget = w;
+ if (mWallpaperTarget != foundW) {
+ mWallpaperTarget = foundW;
+ if (DEBUG_WALLPAPER) {
+ Log.v(TAG, "New wallpaper target: " + foundW);
+ }
+ }
+
+ boolean visible = foundW != null;
if (visible) {
// The window is visible to the compositor... but is it visible
// to the user? That is what the wallpaper cares about.
- visible = !w.mObscured;
+ visible = !foundW.mObscured;
if (DEBUG_WALLPAPER) Log.v(TAG, "Wallpaper visibility: " + visible);
// If the wallpaper target is animating, we may need to copy
- // its layer adjustment.
- mWallpaperAnimLayerAdjustment = w.mAppToken != null
- ? w.mAppToken.animLayerAdjustment : 0;
+ // its layer adjustment. Only do this if we are not transfering
+ // between two wallpaper targets.
+ mWallpaperAnimLayerAdjustment =
+ (mUpcomingWallpaperTarget == null && foundW.mAppToken != null)
+ ? foundW.mAppToken.animLayerAdjustment : 0;
// Now w is the window we are supposed to be behind... but we
// need to be sure to also be behind any of its attached windows,
// AND any starting window associated with it.
- while (i > 0) {
- WindowState wb = (WindowState)localmWindows.get(i-1);
- if (wb.mAttachedWindow != w &&
+ while (foundI > 0) {
+ WindowState wb = (WindowState)localmWindows.get(foundI-1);
+ if (wb.mAttachedWindow != foundW &&
(wb.mAttrs.type != TYPE_APPLICATION_STARTING ||
- wb.mToken != w.mToken)) {
+ wb.mToken != foundW.mToken)) {
// This window is not related to the previous one in any
// interesting way, so stop here.
break;
}
- w = wb;
- i--;
+ foundW = wb;
+ foundI--;
}
}
// Okay i is the position immediately above the wallpaper. Look at
// what is below it for later.
- w = i > 0 ? (WindowState)localmWindows.get(i-1) : null;
+ foundW = foundI > 0 ? (WindowState)localmWindows.get(foundI-1) : null;
final int dw = mDisplay.getWidth();
final int dh = mDisplay.getHeight();
@@ -1271,9 +1348,10 @@
// First, if this window is at the current index, then all
// is well.
- if (wallpaper == w) {
- i--;
- w = i > 0 ? (WindowState)localmWindows.get(i-1) : null;
+ if (wallpaper == foundW) {
+ foundI--;
+ foundW = foundI > 0
+ ? (WindowState)localmWindows.get(foundI-1) : null;
continue;
}
@@ -1283,16 +1361,16 @@
int oldIndex = localmWindows.indexOf(wallpaper);
if (oldIndex >= 0) {
localmWindows.remove(oldIndex);
- if (oldIndex < i) {
- i--;
+ if (oldIndex < foundI) {
+ foundI--;
}
}
// Now stick it in.
if (DEBUG_WALLPAPER) Log.v(TAG, "Moving wallpaper " + wallpaper
- + " from " + oldIndex + " to " + i);
+ + " from " + oldIndex + " to " + foundI);
- localmWindows.add(i, wallpaper);
+ localmWindows.add(foundI, wallpaper);
changed = true;
}
}
@@ -2246,6 +2324,16 @@
? com.android.internal.R.styleable.WindowAnimation_taskToBackEnterAnimation
: com.android.internal.R.styleable.WindowAnimation_taskToBackExitAnimation;
break;
+ case WindowManagerPolicy.TRANSIT_WALLPAPER_ACTIVITY_OPEN:
+ animAttr = enter
+ ? com.android.internal.R.styleable.WindowAnimation_wallpaperActivityOpenEnterAnimation
+ : com.android.internal.R.styleable.WindowAnimation_wallpaperActivityOpenExitAnimation;
+ break;
+ case WindowManagerPolicy.TRANSIT_WALLPAPER_ACTIVITY_CLOSE:
+ animAttr = enter
+ ? com.android.internal.R.styleable.WindowAnimation_wallpaperActivityCloseEnterAnimation
+ : com.android.internal.R.styleable.WindowAnimation_wallpaperActivityCloseExitAnimation;
+ break;
}
a = loadAnimation(lp, animAttr);
if (DEBUG_ANIM) Log.v(TAG, "applyAnimation: wtoken=" + wtoken
@@ -6874,7 +6962,8 @@
// Wallpapers are animated based on the "real" window they
// are currently targeting.
- if (mAttrs.type == TYPE_WALLPAPER && mWallpaperTarget != null) {
+ if (mAttrs.type == TYPE_WALLPAPER && mUpcomingWallpaperTarget == null
+ && mWallpaperTarget != null) {
if (mWallpaperTarget.mHasLocalTransformation) {
attachedTransformation = mWallpaperTarget.mTransformation;
}
@@ -7511,7 +7600,7 @@
if (w == mInputMethodTarget) {
setInputMethodAnimLayerAdjustment(adj);
}
- if (w == mWallpaperTarget) {
+ if (w == mWallpaperTarget && mUpcomingWallpaperTarget == null) {
setWallpaperAnimLayerAdjustmentLocked(adj);
}
}
@@ -8636,6 +8725,60 @@
mH.removeMessages(H.APP_TRANSITION_TIMEOUT);
+ boolean wallpaperMoved = adjustWallpaperWindowsLocked();
+ if (DEBUG_APP_TRANSITIONS) Log.v(TAG,
+ "Old wallpaper target=" + mWallpaperTarget
+ + ", upcoming target=" + mUpcomingWallpaperTarget);
+ if (mUpcomingWallpaperTarget != mWallpaperTarget &&
+ mUpcomingWallpaperTarget != null &&
+ mWallpaperTarget != null) {
+ // Need to determine if both the closing and
+ // opening app token sets are wallpaper targets,
+ // in which case special animations are needed
+ // (since the wallpaper needs to stay static
+ // behind them).
+ int found = 0;
+ NN = mOpeningApps.size();
+ for (i=0; i<NN; i++) {
+ AppWindowToken wtoken = mOpeningApps.get(i);
+ if (mUpcomingWallpaperTarget.mAppToken == wtoken) {
+ found |= 1;
+ }
+ if (mWallpaperTarget.mAppToken == wtoken) {
+ found |= 1;
+ }
+ }
+ NN = mClosingApps.size();
+ for (i=0; i<NN; i++) {
+ AppWindowToken wtoken = mClosingApps.get(i);
+ if (mUpcomingWallpaperTarget.mAppToken == wtoken) {
+ found |= 2;
+ }
+ if (mWallpaperTarget.mAppToken == wtoken) {
+ found |= 2;
+ }
+ }
+
+ if (found == 3) {
+ if (DEBUG_APP_TRANSITIONS) Log.v(TAG,
+ "Wallpaper animation!");
+ switch (transit) {
+ case WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN:
+ case WindowManagerPolicy.TRANSIT_TASK_OPEN:
+ case WindowManagerPolicy.TRANSIT_TASK_TO_FRONT:
+ transit = WindowManagerPolicy.TRANSIT_WALLPAPER_ACTIVITY_OPEN;
+ break;
+ case WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE:
+ case WindowManagerPolicy.TRANSIT_TASK_CLOSE:
+ case WindowManagerPolicy.TRANSIT_TASK_TO_BACK:
+ transit = WindowManagerPolicy.TRANSIT_WALLPAPER_ACTIVITY_CLOSE;
+ break;
+ }
+ if (DEBUG_APP_TRANSITIONS) Log.v(TAG,
+ "New transit: " + transit);
+ }
+ }
+
// We need to figure out which animation to use...
WindowManager.LayoutParams lp = findAnimations(mAppTokens,
mOpeningApps, mClosingApps);
@@ -8671,7 +8814,6 @@
// This has changed the visibility of windows, so perform
// a new layout to get them all up-to-date.
mLayoutNeeded = true;
- adjustWallpaperWindowsLocked();
if (!moveInputMethodWindowsIfNeededLocked(true)) {
assignLayersLocked();
}
diff --git a/telephony/java/com/android/internal/telephony/CallerInfo.java b/telephony/java/com/android/internal/telephony/CallerInfo.java
index afc8b62..bda2d22 100644
--- a/telephony/java/com/android/internal/telephony/CallerInfo.java
+++ b/telephony/java/com/android/internal/telephony/CallerInfo.java
@@ -20,9 +20,8 @@
import android.database.Cursor;
import android.graphics.drawable.Drawable;
import android.net.Uri;
-import android.provider.Contacts;
-import android.provider.Contacts.People;
-import android.provider.Contacts.Phones;
+import android.provider.ContactsContract.PhoneLookup;
+import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.text.TextUtils;
import android.telephony.TelephonyManager;
import android.telephony.PhoneNumberUtils;
@@ -134,44 +133,39 @@
int columnIndex;
// Look for the name
- columnIndex = cursor.getColumnIndex(People.NAME);
+ columnIndex = cursor.getColumnIndex(PhoneLookup.DISPLAY_NAME);
if (columnIndex != -1) {
info.name = cursor.getString(columnIndex);
}
// Look for the number
- columnIndex = cursor.getColumnIndex(Phones.NUMBER);
+ columnIndex = cursor.getColumnIndex(PhoneLookup.NUMBER);
if (columnIndex != -1) {
info.phoneNumber = cursor.getString(columnIndex);
}
// Look for the label/type combo
- columnIndex = cursor.getColumnIndex(Phones.LABEL);
+ columnIndex = cursor.getColumnIndex(PhoneLookup.LABEL);
if (columnIndex != -1) {
- int typeColumnIndex = cursor.getColumnIndex(Phones.TYPE);
+ int typeColumnIndex = cursor.getColumnIndex(PhoneLookup.TYPE);
if (typeColumnIndex != -1) {
info.numberType = cursor.getInt(typeColumnIndex);
info.numberLabel = cursor.getString(columnIndex);
- info.phoneLabel = Contacts.Phones.getDisplayLabel(context,
+ info.phoneLabel = Phone.getDisplayLabel(context,
info.numberType, info.numberLabel)
.toString();
}
}
// Look for the person ID
- columnIndex = cursor.getColumnIndex(Phones.PERSON_ID);
+ columnIndex = cursor.getColumnIndex(PhoneLookup._ID);
if (columnIndex != -1) {
info.person_id = cursor.getLong(columnIndex);
- } else {
- columnIndex = cursor.getColumnIndex(People._ID);
- if (columnIndex != -1) {
- info.person_id = cursor.getLong(columnIndex);
- }
}
// look for the custom ringtone, create from the string stored
// in the database.
- columnIndex = cursor.getColumnIndex(People.CUSTOM_RINGTONE);
+ columnIndex = cursor.getColumnIndex(PhoneLookup.CUSTOM_RINGTONE);
if ((columnIndex != -1) && (cursor.getString(columnIndex) != null)) {
info.contactRingtoneUri = Uri.parse(cursor.getString(columnIndex));
} else {
@@ -180,7 +174,7 @@
// look for the send to voicemail flag, set it to true only
// under certain circumstances.
- columnIndex = cursor.getColumnIndex(People.SEND_TO_VOICEMAIL);
+ columnIndex = cursor.getColumnIndex(PhoneLookup.SEND_TO_VOICEMAIL);
info.shouldSendToVoicemail = (columnIndex != -1) &&
((cursor.getInt(columnIndex)) == 1);
info.contactExists = true;
@@ -256,8 +250,7 @@
}
}
- Uri contactUri = Uri.withAppendedPath(Contacts.Phones.CONTENT_FILTER_URL,
- Uri.encode(number));
+ Uri contactUri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, number);
CallerInfo info = getCallerInfo(context, contactUri);
diff --git a/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java b/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java
index f81f42a..ef456f0 100644
--- a/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java
+++ b/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java
@@ -24,7 +24,7 @@
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
-import android.provider.Contacts;
+import android.provider.ContactsContract.PhoneLookup;
import android.telephony.PhoneNumberUtils;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
@@ -303,7 +303,7 @@
public static CallerInfoAsyncQuery startQuery(int token, Context context, String number,
OnQueryCompleteListener listener, Object cookie) {
//contruct the URI object and start Query.
- Uri contactRef = Uri.withAppendedPath(Contacts.Phones.CONTENT_FILTER_URL, number);
+ Uri contactRef = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, number);
CallerInfoAsyncQuery c = new CallerInfoAsyncQuery();
c.allocate(context, contactRef);
diff --git a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
index 29e89b5..cc981c9 100644
--- a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
@@ -456,16 +456,19 @@
if (dataEnabled[id] != enable) {
dataEnabled[id] = enable;
+ // count the total number of enabled APN's
+ // if we just enabled the first APN, start our Data connection,
+ // if we disabled the last, stop our data connection
if (enable) {
enabledCount++;
+ if (enabledCount == 1) {
+ setPrivateDataEnabled(true);
+ }
} else {
enabledCount--;
- }
-
- if (enabledCount == 0) {
- setPrivateDataEnabled(false);
- } else if (enabledCount == 1) {
- setPrivateDataEnabled(true);
+ if (enabledCount == 0) {
+ setPrivateDataEnabled(false);
+ }
}
}
}
diff --git a/telephony/java/com/android/internal/telephony/IccCard.java b/telephony/java/com/android/internal/telephony/IccCard.java
index c2bed88..6657060 100644
--- a/telephony/java/com/android/internal/telephony/IccCard.java
+++ b/telephony/java/com/android/internal/telephony/IccCard.java
@@ -595,7 +595,7 @@
// this is common for all radio technologies
if (!mIccCardStatus.getCardState().isCardPresent()) {
- return IccCard.State.NOT_READY;
+ return IccCard.State.ABSENT;
}
RadioState currentRadioState = mPhone.mCM.getRadioState();
diff --git a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
index 9c04305..1597427 100755
--- a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
+++ b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
@@ -29,6 +29,7 @@
import com.android.internal.telephony.cdma.sms.CdmaSmsAddress;
import com.android.internal.telephony.cdma.sms.SmsEnvelope;
import com.android.internal.telephony.cdma.sms.UserData;
+import com.android.internal.util.HexDump;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
@@ -67,6 +68,7 @@
*/
public class SmsMessage extends SmsMessageBase {
static final String LOG_TAG = "CDMA";
+ private final static Boolean DBG_SMS = false;
/**
* Status of a previously submitted SMS.
@@ -541,6 +543,11 @@
return;
}
mBearerData = BearerData.decode(mEnvelope.bearerData);
+ if (DBG_SMS) {
+ Log.d(LOG_TAG, "MT raw BearerData = '" +
+ HexDump.toHexString(mEnvelope.bearerData) + "'");
+ Log.d(LOG_TAG, "MT (decoded) BearerData = " + mBearerData);
+ }
messageRef = mBearerData.messageId;
if (mBearerData.userData != null) {
userData = mBearerData.userData.payload;
@@ -644,14 +651,17 @@
bearerData.reportReq = false;
bearerData.userData = userData;
- bearerData.hasUserDataHeader = (userData.userDataHeader != null);
+
+ byte[] encodedBearerData = BearerData.encode(bearerData);
+ if (DBG_SMS) {
+ Log.d(LOG_TAG, "MO (encoded) BearerData = " + bearerData);
+ Log.d(LOG_TAG, "MO raw BearerData = '" + HexDump.toHexString(encodedBearerData) + "'");
+ }
+ if (encodedBearerData == null) return null;
int teleservice = bearerData.hasUserDataHeader ?
SmsEnvelope.TELESERVICE_WEMT : SmsEnvelope.TELESERVICE_WMT;
- byte[] encodedBearerData = BearerData.encode(bearerData);
- if (encodedBearerData == null) return null;
-
SmsEnvelope envelope = new SmsEnvelope();
envelope.messageType = SmsEnvelope.MESSAGE_TYPE_POINT_TO_POINT;
envelope.teleService = teleservice;
diff --git a/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java b/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java
index fefeb12..721729d 100644
--- a/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java
+++ b/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java
@@ -484,7 +484,7 @@
Gsm7bitCodingResult result = new Gsm7bitCodingResult();
result.data = new byte[fullData.length - 1];
System.arraycopy(fullData, 1, result.data, 0, fullData.length - 1);
- result.septets = fullData[0];
+ result.septets = fullData[0] & 0x00FF;
return result;
} catch (com.android.internal.telephony.EncodeException ex) {
throw new CodingException("7bit GSM encode failed: " + ex);
@@ -498,6 +498,7 @@
int udhSeptets = ((udhBytes * 8) + 6) / 7;
Gsm7bitCodingResult gcr = encode7bitGsm(uData.payloadStr, udhSeptets, force);
uData.msgEncoding = UserData.ENCODING_GSM_7BIT_ALPHABET;
+ uData.msgEncodingSet = true;
uData.numFields = gcr.septets;
uData.payload = gcr.data;
uData.payload[0] = (byte)udhData.length;
@@ -512,6 +513,8 @@
int udhCodeUnits = (udhBytes + 1) / 2;
int udhPadding = udhBytes % 2;
int payloadCodeUnits = payload.length / 2;
+ uData.msgEncoding = UserData.ENCODING_UNICODE_16;
+ uData.msgEncodingSet = true;
uData.numFields = udhCodeUnits + payloadCodeUnits;
uData.payload = new byte[uData.numFields * 2];
uData.payload[0] = (byte)udhData.length;
@@ -606,14 +609,16 @@
* copies by passing outStream directly.
*/
encodeUserDataPayload(bData.userData);
+ bData.hasUserDataHeader = bData.userData.userDataHeader != null;
+
if (bData.userData.payload.length > SmsMessage.MAX_USER_DATA_BYTES) {
throw new CodingException("encoded user data too large (" +
bData.userData.payload.length +
" > " + SmsMessage.MAX_USER_DATA_BYTES + " bytes)");
}
- /**
- * XXX/TODO: figure out what the right answer is WRT padding bits
+ /*
+ * TODO(cleanup): figure out what the right answer is WRT paddingBits field
*
* userData.paddingBits = (userData.payload.length * 8) - (userData.numFields * 7);
* userData.paddingBits = 0; // XXX this seems better, but why?
diff --git a/telephony/java/com/android/internal/telephony/cdma/sms/UserData.java b/telephony/java/com/android/internal/telephony/cdma/sms/UserData.java
index 9b6e19d..d93852c 100644
--- a/telephony/java/com/android/internal/telephony/cdma/sms/UserData.java
+++ b/telephony/java/com/android/internal/telephony/cdma/sms/UserData.java
@@ -154,7 +154,7 @@
builder.append("{ msgEncoding=" + (msgEncodingSet ? msgEncoding : "unset"));
builder.append(", msgType=" + msgType);
builder.append(", paddingBits=" + paddingBits);
- builder.append(", numFields=" + (int)numFields);
+ builder.append(", numFields=" + numFields);
builder.append(", userDataHeader=" + userDataHeader);
builder.append(", payload='" + HexDump.toHexString(payload) + "'");
builder.append(", payloadStr='" + payloadStr + "'");