Merge change Ib482ce88 into eclair-mr2
* changes:
Revive support for video encoding in OMXCodec.
diff --git a/Android.mk b/Android.mk
index 5008ad7..a40d3f9 100644
--- a/Android.mk
+++ b/Android.mk
@@ -108,7 +108,6 @@
core/java/android/hardware/ISensorService.aidl \
core/java/android/net/IConnectivityManager.aidl \
core/java/android/os/ICheckinService.aidl \
- core/java/android/os/IDropBox.aidl \
core/java/android/os/IHardwareService.aidl \
core/java/android/os/IMessenger.aidl \
core/java/android/os/IMountService.aidl \
@@ -137,6 +136,7 @@
core/java/com/android/internal/appwidget/IAppWidgetService.aidl \
core/java/com/android/internal/appwidget/IAppWidgetHost.aidl \
core/java/com/android/internal/backup/IBackupTransport.aidl \
+ core/java/com/android/internal/os/IDropBoxService.aidl \
core/java/com/android/internal/os/IResultReceiver.aidl \
core/java/com/android/internal/view/IInputContext.aidl \
core/java/com/android/internal/view/IInputContextCallback.aidl \
@@ -217,7 +217,7 @@
frameworks/base/core/java/android/appwidget/AppWidgetProviderInfo.aidl \
frameworks/base/core/java/android/net/Uri.aidl \
frameworks/base/core/java/android/os/Bundle.aidl \
- frameworks/base/core/java/android/os/DropBoxEntry.aidl \
+ frameworks/base/core/java/android/os/DropBox.aidl \
frameworks/base/core/java/android/os/ParcelFileDescriptor.aidl \
frameworks/base/core/java/android/os/ParcelUuid.aidl \
frameworks/base/core/java/android/view/KeyEvent.aidl \
@@ -491,6 +491,8 @@
include $(BUILD_DROIDDOC)
+# explicitly specify that online-sdk depends on framework-res.
+$(full_target): framework-res-package-target
# ==== docs that have all of the stuff that's @hidden =======================
include $(CLEAR_VARS)
diff --git a/api/current.xml b/api/current.xml
index 4cd9718..6ba1199 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -99410,6 +99410,17 @@
visibility="public"
>
</field>
+<field name="ECLAIR_MR1"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="6"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
</class>
<class name="Bundle"
extends="java.lang.Object"
diff --git a/core/java/android/app/ApplicationContext.java b/core/java/android/app/ApplicationContext.java
index f48f150..305ee6a 100644
--- a/core/java/android/app/ApplicationContext.java
+++ b/core/java/android/app/ApplicationContext.java
@@ -70,6 +70,7 @@
import android.net.wifi.WifiManager;
import android.os.Binder;
import android.os.Bundle;
+import android.os.DropBox;
import android.os.FileUtils;
import android.os.Handler;
import android.os.IBinder;
@@ -93,6 +94,8 @@
import android.accounts.AccountManager;
import android.accounts.IAccountManager;
+import com.android.internal.os.IDropBoxService;
+
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
@@ -182,6 +185,7 @@
private ClipboardManager mClipboardManager = null;
private boolean mRestricted;
private AccountManager mAccountManager; // protected by mSync
+ private DropBox mDropBox = null;
private final Object mSync = new Object();
@@ -896,6 +900,8 @@
return getClipboardManager();
} else if (WALLPAPER_SERVICE.equals(name)) {
return getWallpaperManager();
+ } else if (DROPBOX_SERVICE.equals(name)) {
+ return getDropBox();
}
return null;
@@ -1045,7 +1051,7 @@
}
return mVibrator;
}
-
+
private AudioManager getAudioManager()
{
if (mAudioManager == null) {
@@ -1054,6 +1060,17 @@
return mAudioManager;
}
+ private DropBox getDropBox() {
+ synchronized (mSync) {
+ if (mDropBox == null) {
+ IBinder b = ServiceManager.getService(DROPBOX_SERVICE);
+ IDropBoxService service = IDropBoxService.Stub.asInterface(b);
+ mDropBox = new DropBox(service);
+ }
+ }
+ return mDropBox;
+ }
+
@Override
public int checkPermission(String permission, int pid, int uid) {
if (permission == null) {
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 8f1c671..b4ab408 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -1309,7 +1309,7 @@
* @see #getSystemService
*/
public static final String APPWIDGET_SERVICE = "appwidget";
-
+
/**
* Use with {@link #getSystemService} to retrieve an
* {@blink android.backup.IBackupManager IBackupManager} for communicating
@@ -1319,7 +1319,16 @@
* @see #getSystemService
*/
public static final String BACKUP_SERVICE = "backup";
-
+
+ /**
+ * Use with {@link #getSystemService} to retrieve a
+ * {@blink android.os.DropBox DropBox} instance for recording
+ * diagnostic logs.
+ * @hide
+ * @see #getSystemService
+ */
+ public static final String DROPBOX_SERVICE = "dropbox";
+
/**
* Determine whether the given permission is allowed for a particular
* process and user ID running in the system.
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 0f8bc08..d4aaba3 100644
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -103,16 +103,19 @@
* October 2008: The original, first, version of Android. Yay!
*/
public static final int BASE = 1;
+
/**
* February 2009: First Android update, officially called 1.1.
*/
public static final int BASE_1_1 = 2;
+
/**
* May 2009: Android 1.5.
*/
public static final int CUPCAKE = 3;
+
/**
- * Current work on "Donut" development branch.
+ * September 2009: Android 1.6.
*
* <p>Applications targeting this or a later release will get these
* new changes in behavior:</p>
@@ -133,8 +136,9 @@
* </ul>
*/
public static final int DONUT = 4;
+
/**
- * Current work on "Eclair" development branch.
+ * November 2009: Android 2.0
*
* <p>Applications targeting this or a later release will get these
* new changes in behavior:</p>
@@ -152,6 +156,11 @@
* </ul>
*/
public static final int ECLAIR = 5;
+
+ /**
+ * Current work on Eclair MR1.
+ */
+ public static final int ECLAIR_MR1 = 6;
}
/** The type of build, like "user" or "eng". */
diff --git a/core/java/android/os/DropBoxEntry.aidl b/core/java/android/os/DropBox.aidl
similarity index 95%
rename from core/java/android/os/DropBoxEntry.aidl
rename to core/java/android/os/DropBox.aidl
index 225eee1..77abd22 100644
--- a/core/java/android/os/DropBoxEntry.aidl
+++ b/core/java/android/os/DropBox.aidl
@@ -16,4 +16,4 @@
package android.os;
-parcelable DropBoxEntry;
+parcelable DropBox.Entry;
diff --git a/core/java/android/os/DropBox.java b/core/java/android/os/DropBox.java
new file mode 100644
index 0000000..0551dc1
--- /dev/null
+++ b/core/java/android/os/DropBox.java
@@ -0,0 +1,276 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+import android.util.Log;
+
+import com.android.internal.os.IDropBoxService;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.zip.GZIPInputStream;
+
+/**
+ * Enqueues chunks of data (from various sources -- application crashes, kernel
+ * log records, etc.). The queue is size bounded and will drop old data if the
+ * enqueued data exceeds the maximum size. You can think of this as a
+ * persistent, system-wide, blob-oriented "logcat".
+ *
+ * <p>You can obtain an instance of this class by calling
+ * {@link android.content.Context#getSystemService}
+ * with {@link android.content.Context#DROPBOX_SERVICE}.
+ *
+ * <p>DropBox entries are not sent anywhere directly, but other system services
+ * and debugging tools may scan and upload entries for processing.
+ *
+ * {@pending}
+ */
+public class DropBox {
+ private static final String TAG = "DropBox";
+ private final IDropBoxService mService;
+
+ /** Flag value: Entry's content was deleted to save space. */
+ public static final int IS_EMPTY = 1;
+
+ /** Flag value: Content is human-readable UTF-8 text (can be combined with IS_GZIPPED). */
+ public static final int IS_TEXT = 2;
+
+ /** Flag value: Content can be decompressed with {@link GZIPOutputStream}. */
+ public static final int IS_GZIPPED = 4;
+
+ /**
+ * A single entry retrieved from the drop box.
+ * This may include a reference to a stream, so you must call
+ * {@link #close()} when you are done using it.
+ */
+ public static class Entry implements Parcelable {
+ private final String mTag;
+ private final long mTimeMillis;
+
+ private final byte[] mData;
+ private final ParcelFileDescriptor mFileDescriptor;
+ private final int mFlags;
+
+ /** Create a new empty Entry with no contents. */
+ public Entry(String tag, long millis) {
+ this(tag, millis, (Object) null, IS_EMPTY);
+ }
+
+ /** Create a new Entry with plain text contents. */
+ public Entry(String tag, long millis, String text) {
+ this(tag, millis, (Object) text.getBytes(), IS_TEXT);
+ }
+
+ /**
+ * Create a new Entry with byte array contents.
+ * The data array must not be modified after creating this entry.
+ */
+ public Entry(String tag, long millis, byte[] data, int flags) {
+ this(tag, millis, (Object) data, flags);
+ }
+
+ /**
+ * Create a new Entry with streaming data contents.
+ * Takes ownership of the ParcelFileDescriptor.
+ */
+ public Entry(String tag, long millis, ParcelFileDescriptor data, int flags) {
+ this(tag, millis, (Object) data, flags);
+ }
+
+ /**
+ * Create a new Entry with the contents read from a file.
+ * The file will be read when the entry's contents are requested.
+ */
+ public Entry(String tag, long millis, File data, int flags) throws IOException {
+ this(tag, millis, (Object) ParcelFileDescriptor.open(
+ data, ParcelFileDescriptor.MODE_READ_ONLY), flags);
+ }
+
+ /** Internal constructor for CREATOR.createFromParcel(). */
+ private Entry(String tag, long millis, Object value, int flags) {
+ if (tag == null) throw new NullPointerException();
+ if (((flags & IS_EMPTY) != 0) != (value == null)) throw new IllegalArgumentException();
+
+ mTag = tag;
+ mTimeMillis = millis;
+ mFlags = flags;
+
+ if (value == null) {
+ mData = null;
+ mFileDescriptor = null;
+ } else if (value instanceof byte[]) {
+ mData = (byte[]) value;
+ mFileDescriptor = null;
+ } else if (value instanceof ParcelFileDescriptor) {
+ mData = null;
+ mFileDescriptor = (ParcelFileDescriptor) value;
+ } else {
+ throw new IllegalArgumentException();
+ }
+ }
+
+ /** Close the input stream associated with this entry. */
+ public void close() {
+ try { if (mFileDescriptor != null) mFileDescriptor.close(); } catch (IOException e) { }
+ }
+
+ /** @return the tag originally attached to the entry. */
+ public String getTag() { return mTag; }
+
+ /** @return time when the entry was originally created. */
+ public long getTimeMillis() { return mTimeMillis; }
+
+ /** @return flags describing the content returned by @{link #getInputStream()}. */
+ public int getFlags() { return mFlags & ~IS_GZIPPED; } // getInputStream() decompresses.
+
+ /**
+ * @param maxBytes of string to return (will truncate at this length).
+ * @return the uncompressed text contents of the entry, null if the entry is not text.
+ */
+ public String getText(int maxBytes) {
+ if ((mFlags & IS_TEXT) == 0) return null;
+ if (mData != null) return new String(mData, 0, Math.min(maxBytes, mData.length));
+
+ InputStream is = null;
+ try {
+ is = getInputStream();
+ byte[] buf = new byte[maxBytes];
+ return new String(buf, 0, Math.max(0, is.read(buf)));
+ } catch (IOException e) {
+ return null;
+ } finally {
+ try { if (is != null) is.close(); } catch (IOException e) {}
+ }
+ }
+
+ /** @return the uncompressed contents of the entry, or null if the contents were lost */
+ public InputStream getInputStream() throws IOException {
+ InputStream is;
+ if (mData != null) {
+ is = new ByteArrayInputStream(mData);
+ } else if (mFileDescriptor != null) {
+ is = new ParcelFileDescriptor.AutoCloseInputStream(mFileDescriptor);
+ } else {
+ return null;
+ }
+ return (mFlags & IS_GZIPPED) != 0 ? new GZIPInputStream(is) : is;
+ }
+
+ public static final Parcelable.Creator<Entry> CREATOR = new Parcelable.Creator() {
+ public Entry[] newArray(int size) { return new Entry[size]; }
+ public Entry createFromParcel(Parcel in) {
+ return new Entry(
+ in.readString(), in.readLong(), in.readValue(null), in.readInt());
+ }
+ };
+
+ public int describeContents() {
+ return mFileDescriptor != null ? Parcelable.CONTENTS_FILE_DESCRIPTOR : 0;
+ }
+
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeString(mTag);
+ out.writeLong(mTimeMillis);
+ if (mFileDescriptor != null) {
+ out.writeValue(mFileDescriptor);
+ } else {
+ out.writeValue(mData);
+ }
+ out.writeInt(mFlags);
+ }
+ }
+
+ /** {@hide} */
+ public DropBox(IDropBoxService service) { mService = service; }
+
+ /**
+ * Create a dummy instance for testing. All methods will fail unless
+ * overridden with an appropriate mock implementation. To obtain a
+ * functional instance, use {@link android.content.Context#getSystemService}.
+ */
+ protected DropBox() { mService = null; }
+
+ /**
+ * Stores human-readable text. The data may be discarded eventually (or even
+ * immediately) if space is limited, or ignored entirely if the tag has been
+ * blocked (see {@link #isTagEnabled}).
+ *
+ * @param tag describing the type of entry being stored
+ * @param data value to store
+ */
+ public void addText(String tag, String data) {
+ try { mService.add(new Entry(tag, 0, data)); } catch (RemoteException e) {}
+ }
+
+ /**
+ * Stores binary data, which may be ignored or discarded as with {@link #addText}.
+ *
+ * @param tag describing the type of entry being stored
+ * @param data value to store
+ * @param flags describing the data
+ */
+ public void addData(String tag, byte[] data, int flags) {
+ if (data == null) throw new NullPointerException();
+ try { mService.add(new Entry(tag, 0, data, flags)); } catch (RemoteException e) {}
+ }
+
+ /**
+ * Stores data read from a file descriptor. The data may be ignored or
+ * discarded as with {@link #addText}. You must close your
+ * ParcelFileDescriptor object after calling this method!
+ *
+ * @param tag describing the type of entry being stored
+ * @param fd file descriptor to read from
+ * @param flags describing the data
+ */
+ public void addFile(String tag, ParcelFileDescriptor fd, int flags) {
+ if (fd == null) throw new NullPointerException();
+ try { mService.add(new Entry(tag, 0, fd, flags)); } catch (RemoteException e) {}
+ }
+
+ /**
+ * Checks any blacklists (set in system settings) to see whether a certain
+ * tag is allowed. Entries with disabled tags will be dropped immediately,
+ * so you can save the work of actually constructing and sending the data.
+ *
+ * @param tag that would be used in {@link #addText} or {@link #addFile}
+ * @return whether events with that tag would be accepted
+ */
+ public boolean isTagEnabled(String tag) {
+ try { return mService.isTagEnabled(tag); } catch (RemoteException e) { return false; }
+ }
+
+ /**
+ * Gets the next entry from the drop box *after* the specified time.
+ * Requires android.permission.READ_LOGS. You must always call
+ * {@link Entry#close()} on the return value!
+ *
+ * @param tag of entry to look for, null for all tags
+ * @param msec time of the last entry seen
+ * @return the next entry, or null if there are no more entries
+ */
+ public Entry getNextEntry(String tag, long msec) {
+ try { return mService.getNextEntry(tag, msec); } catch (RemoteException e) { return null; }
+ }
+
+ // TODO: It may be useful to have some sort of notification mechanism
+ // when data is added to the dropbox, for demand-driven readers --
+ // for now readers need to poll the dropbox to find new data.
+}
diff --git a/core/java/android/os/DropBoxEntry.java b/core/java/android/os/DropBoxEntry.java
deleted file mode 100644
index e3816a8..0000000
--- a/core/java/android/os/DropBoxEntry.java
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os;
-
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.Reader;
-import java.io.StringReader;
-import java.util.zip.GZIPInputStream;
-
-/**
- * A single entry retrieved from an {@link IDropBox} implementation.
- * This may include a reference to a stream, so you must call
- * {@link #close()} when you are done using it.
- *
- * {@pending}
- */
-public class DropBoxEntry implements Parcelable {
- private final String mTag;
- private final long mTimeMillis;
-
- private final String mText;
- private final ParcelFileDescriptor mFileDescriptor;
- private final int mFlags;
-
- /** Flag value: Entry's content was deleted to save space. */
- public static final int IS_EMPTY = 1;
-
- /** Flag value: Content is human-readable UTF-8 text (possibly compressed). */
- public static final int IS_TEXT = 2;
-
- /** Flag value: Content can been decompressed with {@link GZIPOutputStream}. */
- public static final int IS_GZIPPED = 4;
-
- /** Create a new DropBoxEntry with the specified contents. */
- public DropBoxEntry(String tag, long timeMillis, String text) {
- if (tag == null || text == null) throw new NullPointerException();
- mTag = tag;
- mTimeMillis = timeMillis;
- mText = text;
- mFileDescriptor = null;
- mFlags = IS_TEXT;
- }
-
- /** Create a new DropBoxEntry with the specified contents. */
- public DropBoxEntry(String tag, long millis, File data, int flags) throws IOException {
- if (tag == null) throw new NullPointerException();
- if (((flags & IS_EMPTY) != 0) != (data == null)) throw new IllegalArgumentException();
-
- mTag = tag;
- mTimeMillis = millis;
- mText = null;
- mFlags = flags;
- mFileDescriptor = data == null ? null :
- ParcelFileDescriptor.open(data, ParcelFileDescriptor.MODE_READ_ONLY);
- }
-
- /** Internal constructor for CREATOR.createFromParcel(). */
- private DropBoxEntry(String tag, long millis, Object value, int flags) {
- if (tag == null) throw new NullPointerException();
- if (((flags & IS_EMPTY) != 0) != (value == null)) throw new IllegalArgumentException();
-
- mTag = tag;
- mTimeMillis = millis;
- mFlags = flags;
-
- if (value == null) {
- mText = null;
- mFileDescriptor = null;
- } else if (value instanceof String) {
- if ((flags & IS_TEXT) == 0) throw new IllegalArgumentException();
- mText = (String) value;
- mFileDescriptor = null;
- } else if (value instanceof ParcelFileDescriptor) {
- mText = null;
- mFileDescriptor = (ParcelFileDescriptor) value;
- } else {
- throw new IllegalArgumentException();
- }
- }
-
- /** Close the input stream associated with this entry. */
- public synchronized void close() {
- try { if (mFileDescriptor != null) mFileDescriptor.close(); } catch (IOException e) { }
- }
-
- /** @return the tag originally attached to the entry. */
- public String getTag() { return mTag; }
-
- /** @return time when the entry was originally created. */
- public long getTimeMillis() { return mTimeMillis; }
-
- /** @return flags describing the content returned by @{link #getInputStream()}. */
- public int getFlags() { return mFlags & ~IS_GZIPPED; } // getInputStream() decompresses.
-
- /**
- * @param maxLength of string to return (will truncate at this length).
- * @return the uncompressed text contents of the entry, null if the entry is not text.
- */
- public String getText(int maxLength) {
- if (mText != null) return mText.substring(0, Math.min(maxLength, mText.length()));
- if ((mFlags & IS_TEXT) == 0) return null;
-
- try {
- InputStream stream = getInputStream();
- if (stream == null) return null;
- char[] buf = new char[maxLength];
- InputStreamReader reader = new InputStreamReader(stream);
- return new String(buf, 0, Math.max(0, reader.read(buf)));
- } catch (IOException e) {
- return null;
- }
- }
-
- /** @return the uncompressed contents of the entry, or null if the contents were lost */
- public InputStream getInputStream() throws IOException {
- if (mText != null) return new ByteArrayInputStream(mText.getBytes("UTF8"));
- if (mFileDescriptor == null) return null;
- InputStream is = new ParcelFileDescriptor.AutoCloseInputStream(mFileDescriptor);
- return (mFlags & IS_GZIPPED) != 0 ? new GZIPInputStream(is) : is;
- }
-
- public static final Parcelable.Creator<DropBoxEntry> CREATOR = new Parcelable.Creator() {
- public DropBoxEntry[] newArray(int size) { return new DropBoxEntry[size]; }
- public DropBoxEntry createFromParcel(Parcel in) {
- return new DropBoxEntry(
- in.readString(), in.readLong(), in.readValue(null), in.readInt());
- }
- };
-
- public int describeContents() {
- return mFileDescriptor != null ? Parcelable.CONTENTS_FILE_DESCRIPTOR : 0;
- }
-
- public void writeToParcel(Parcel out, int flags) {
- out.writeString(mTag);
- out.writeLong(mTimeMillis);
- if (mFileDescriptor != null) {
- out.writeValue(mFileDescriptor);
- } else {
- out.writeValue(mText);
- }
- out.writeInt(mFlags);
- }
-}
diff --git a/core/java/android/os/IDropBox.aidl b/core/java/android/os/IDropBox.aidl
deleted file mode 100644
index 26294b6..0000000
--- a/core/java/android/os/IDropBox.aidl
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os;
-
-import android.os.DropBoxEntry;
-import android.os.ParcelFileDescriptor;
-
-/**
- * Enqueues chunks of data (from various sources -- application crashes, kernel
- * log records, etc.). The queue is size bounded and will drop old data if the
- * enqueued data exceeds the maximum size.
- *
- * <p>This interface is implemented by a system service you can access:
- *
- * <pre>IDropBox.Stub.asInterface(ServiceManager.getService("dropbox"));</pre>
- *
- * <p>Other system services and debugging tools may scan the drop box to upload
- * entries for processing.
- *
- * {@pending}
- */
-interface IDropBox {
- /**
- * Stores human-readable text. The data may be discarded eventually (or even
- * immediately) if space is limited, or ignored entirely if the tag has been
- * blocked (see {@link #isTagEnabled}).
- *
- * @param tag describing the type of entry being stored
- * @param data value to store
- */
- void addText(String tag, String data);
-
- /**
- * Stores binary data. The data may be ignored or discarded as with
- * {@link #addText}.
- *
- * @param tag describing the type of entry being stored
- * @param data value to store
- * @param flags describing the data, defined in {@link DropBoxEntry}
- */
- void addData(String tag, in byte[] data, int flags);
-
- /**
- * Stores data read from a file descriptor. The data may be ignored or
- * discarded as with {@link #addText}. You must close your
- * ParcelFileDescriptor object after calling this method!
- *
- * @param tag describing the type of entry being stored
- * @param data file descriptor to read from
- * @param flags describing the data, defined in {@link DropBoxEntry}
- */
- void addFile(String tag, in ParcelFileDescriptor data, int flags);
-
- /**
- * Checks any blacklists (set in system settings) to see whether a certain
- * tag is allowed. Entries with disabled tags will be dropped immediately,
- * so you can save the work of actually constructing and sending the data.
- *
- * @param tag that would be used in {@link #addText} or {@link #addFile}
- * @return whether events with that tag would be accepted
- */
- boolean isTagEnabled(String tag);
-
- /**
- * Gets the next entry from the drop box *after* the specified time.
- * Requires android.permission.READ_LOGS. You must always call
- * {@link DropBoxEntry#close()} on the return value!
- *
- * @param tag of entry to look for, null for all tags
- * @param millis time of the last entry seen
- * @return the next entry, or null if there are no more entries
- */
- DropBoxEntry getNextEntry(String tag, long millis);
-
- // TODO: It may be useful to have some sort of notification mechanism
- // when data is added to the dropbox, for demand-driven readers --
- // for now readers need to poll the dropbox to find new data.
-}
diff --git a/core/java/android/pim/vcard/Constants.java b/core/java/android/pim/vcard/Constants.java
index a1c7e10..052f329 100644
--- a/core/java/android/pim/vcard/Constants.java
+++ b/core/java/android/pim/vcard/Constants.java
@@ -72,6 +72,9 @@
// Phone number for Skype, available as usual phone.
public static final String PROPERTY_X_SKYPE_PSTNNUMBER = "X-SKYPE-PSTNNUMBER";
+ // Property for Android-specific fields.
+ public static final String PROPERTY_X_ANDROID_CUSTOM = "X-ANDROID-CUSTOM";
+
// Properties for DoCoMo vCard.
public static final String PROPERTY_X_CLASS = "X-CLASS";
public static final String PROPERTY_X_REDUCTION = "X-REDUCTION";
@@ -158,6 +161,9 @@
public static final String PROPERTY_X_GOOGLE_TALK_WITH_SPACE = "X-GOOGLE TALK";
}
+ // TODO: Should be in ContactsContract?
+ /* package */ static final int MAX_DATA_COLUMN = 15;
+
private Constants() {
}
}
\ No newline at end of file
diff --git a/core/java/android/pim/vcard/ContactStruct.java b/core/java/android/pim/vcard/ContactStruct.java
index eb9c48a..4069729 100644
--- a/core/java/android/pim/vcard/ContactStruct.java
+++ b/core/java/android/pim/vcard/ContactStruct.java
@@ -442,7 +442,8 @@
private List<ImData> mImList;
private List<PhotoData> mPhotoList;
private List<String> mWebsiteList;
-
+ private List<List<String>> mAndroidCustomPropertyList;
+
private final int mVCardType;
private final Account mAccount;
@@ -479,23 +480,11 @@
}
}
- final String formattedPhoneNumber;
- {
- final String rawPhoneNumber = builder.toString();
- if (VCardConfig.isJapaneseDevice(mVCardType)) {
- // As of 2009-10-07, there's no formatNumber() which accepts
- // the second argument and returns String directly.
- final SpannableStringBuilder tmpBuilder =
- new SpannableStringBuilder(rawPhoneNumber);
- PhoneNumberUtils.formatNumber(tmpBuilder, PhoneNumberUtils.FORMAT_JAPAN);
- formattedPhoneNumber = tmpBuilder.toString();
- } else {
- // There's no information available on vCard side. Depend on the default
- // behavior, which may cause problem in the future when the additional format
- // rule is supported (e.g. PhoneNumberUtils.FORMAT_KLINGON)
- formattedPhoneNumber = PhoneNumberUtils.formatNumber(rawPhoneNumber);
- }
- }
+ // Use NANP in default when there's no information about locale.
+ final int formattingType = (VCardConfig.isJapaneseDevice(mVCardType) ?
+ PhoneNumberUtils.FORMAT_JAPAN : PhoneNumberUtils.FORMAT_NANP);
+ final String formattedPhoneNumber =
+ PhoneNumberUtils.formatNumber(builder.toString(), formattingType);
PhoneData phoneData = new PhoneData(type, formattedPhoneNumber, label, isPrimary);
mPhoneList.add(phoneData);
}
@@ -928,14 +917,19 @@
mWebsiteList = new ArrayList<String>(1);
}
mWebsiteList.add(propValue);
+ } else if (propName.equals(Constants.PROPERTY_BDAY)) {
+ mBirthday = propValue;
} else if (propName.equals(Constants.PROPERTY_X_PHONETIC_FIRST_NAME)) {
mPhoneticGivenName = propValue;
} else if (propName.equals(Constants.PROPERTY_X_PHONETIC_MIDDLE_NAME)) {
mPhoneticMiddleName = propValue;
} else if (propName.equals(Constants.PROPERTY_X_PHONETIC_LAST_NAME)) {
mPhoneticFamilyName = propValue;
- } else if (propName.equals(Constants.PROPERTY_BDAY)) {
- mBirthday = propValue;
+ } else if (propName.equals(Constants.PROPERTY_X_ANDROID_CUSTOM)) {
+ final List<String> customPropertyList =
+ VCardUtils.constructListFromValue(propValue,
+ VCardConfig.isV30(mVCardType));
+ handleAndroidCustomProperty(customPropertyList);
/*} else if (propName.equals("REV")) {
// Revision of this VCard entry. I think we can ignore this.
} else if (propName.equals("UID")) {
@@ -963,6 +957,13 @@
}
}
+ private void handleAndroidCustomProperty(final List<String> customPropertyList) {
+ if (mAndroidCustomPropertyList == null) {
+ mAndroidCustomPropertyList = new ArrayList<List<String>>();
+ }
+ mAndroidCustomPropertyList.add(customPropertyList);
+ }
+
/**
* Construct the display name. The constructed data must not be null.
*/
@@ -1017,7 +1018,7 @@
mDisplayName = "";
}
}
-
+
/**
* Consolidate several fielsds (like mName) using name candidates,
*/
@@ -1028,7 +1029,7 @@
mPhoneticFullName = mPhoneticFullName.trim();
}
}
-
+
// From GoogleSource.java in Contacts app.
private static final String ACCOUNT_TYPE_GOOGLE = "com.google";
private static final String GOOGLE_MY_CONTACTS_GROUP = "System Group: My Contacts";
@@ -1224,6 +1225,36 @@
operationList.add(builder.build());
}
+ if (mAndroidCustomPropertyList != null) {
+ for (List<String> customPropertyList : mAndroidCustomPropertyList) {
+ int size = customPropertyList.size();
+ if (size < 2 || TextUtils.isEmpty(customPropertyList.get(0))) {
+ continue;
+ } else if (size > Constants.MAX_DATA_COLUMN + 1) {
+ size = Constants.MAX_DATA_COLUMN + 1;
+ customPropertyList =
+ customPropertyList.subList(0, Constants.MAX_DATA_COLUMN + 2);
+ }
+
+ int i = 0;
+ for (final String customPropertyValue : customPropertyList) {
+ if (i == 0) {
+ final String mimeType = customPropertyValue;
+ builder = ContentProviderOperation.newInsert(Data.CONTENT_URI);
+ builder.withValueBackReference(GroupMembership.RAW_CONTACT_ID, 0);
+ builder.withValue(Data.MIMETYPE, mimeType);
+ } else { // 1 <= i && i <= MAX_DATA_COLUMNS
+ if (!TextUtils.isEmpty(customPropertyValue)) {
+ builder.withValue("data" + i, customPropertyValue);
+ }
+ }
+
+ operationList.add(builder.build());
+ i++;
+ }
+ }
+ }
+
if (myGroupsId != null) {
builder = ContentProviderOperation.newInsert(Data.CONTENT_URI);
builder.withValueBackReference(GroupMembership.RAW_CONTACT_ID, 0);
diff --git a/core/java/android/pim/vcard/VCardComposer.java b/core/java/android/pim/vcard/VCardComposer.java
index 8eabd4b1..6476e40 100644
--- a/core/java/android/pim/vcard/VCardComposer.java
+++ b/core/java/android/pim/vcard/VCardComposer.java
@@ -1019,11 +1019,11 @@
return;
}
- final String propertyNickname;
+ final boolean useAndroidProperty;
if (mIsV30) {
- propertyNickname = Constants.PROPERTY_NICKNAME;
- /*} else if (mUsesAndroidProperty) {
- propertyNickname = VCARD_PROPERTY_X_NICKNAME;*/
+ useAndroidProperty = false;
+ } else if (mUsesAndroidProperty) {
+ useAndroidProperty = true;
} else {
// There's no way to add this field.
return;
@@ -1034,29 +1034,13 @@
if (TextUtils.isEmpty(nickname)) {
continue;
}
-
- final String encodedNickname;
- final boolean reallyUseQuotedPrintable =
- (mUsesQuotedPrintable &&
- !VCardUtils.containsOnlyNonCrLfPrintableAscii(nickname));
- if (reallyUseQuotedPrintable) {
- encodedNickname = encodeQuotedPrintable(nickname);
+ if (useAndroidProperty) {
+ appendAndroidSpecificProperty(builder, Nickname.CONTENT_ITEM_TYPE,
+ contentValues);
} else {
- encodedNickname = escapeCharacters(nickname);
+ appendVCardLineWithCharsetAndQPDetection(builder,
+ Constants.PROPERTY_NICKNAME, nickname);
}
-
- builder.append(propertyNickname);
- if (shouldAppendCharsetAttribute(propertyNickname)) {
- builder.append(VCARD_ATTR_SEPARATOR);
- builder.append(mVCardAttributeCharset);
- }
- if (reallyUseQuotedPrintable) {
- builder.append(VCARD_ATTR_SEPARATOR);
- builder.append(VCARD_ATTR_ENCODING_QP);
- }
- builder.append(VCARD_DATA_SEPARATOR);
- builder.append(encodedNickname);
- builder.append(VCARD_COL_SEPARATOR);
}
}
@@ -1491,6 +1475,33 @@
}
}
+ private void appendAndroidSpecificProperty(final StringBuilder builder,
+ final String mimeType, ContentValues contentValues) {
+ List<String> rawDataList = new ArrayList<String>();
+ rawDataList.add(mimeType);
+ final List<String> columnNameList;
+ if (Nickname.CONTENT_ITEM_TYPE.equals(mimeType)) {
+
+ } else {
+ // If you add the other field, please check all the columns are able to be
+ // converted to String.
+ //
+ // e.g. BLOB is not what we can handle here now.
+ return;
+ }
+
+ for (int i = 1; i <= Constants.MAX_DATA_COLUMN; i++) {
+ String value = contentValues.getAsString("data" + i);
+ if (value == null) {
+ value = "";
+ }
+ rawDataList.add(value);
+ }
+
+ appendVCardLineWithCharsetAndQPDetection(builder,
+ Constants.PROPERTY_X_ANDROID_CUSTOM, rawDataList);
+ }
+
/**
* Append '\' to the characters which should be escaped. The character set is different
* not only between vCard 2.1 and vCard 3.0 but also among each device.
@@ -1968,6 +1979,8 @@
}
}
+ // appendVCardLine() variants accepting one String.
+
private void appendVCardLineWithCharsetAndQPDetection(final StringBuilder builder,
final String propertyName, final String rawData) {
appendVCardLineWithCharsetAndQPDetection(builder, propertyName, null, rawData);
@@ -2026,6 +2039,87 @@
builder.append(VCARD_COL_SEPARATOR);
}
+ // appendVCardLine() variants accepting List<String>.
+
+ private void appendVCardLineWithCharsetAndQPDetection(final StringBuilder builder,
+ final String propertyName, final List<String> rawDataList) {
+ appendVCardLineWithCharsetAndQPDetection(builder, propertyName, null, rawDataList);
+ }
+
+ private void appendVCardLineWithCharsetAndQPDetection(final StringBuilder builder,
+ final String propertyName,
+ final List<String> attributeList, final List<String> rawDataList) {
+ boolean needCharset = false;
+ boolean reallyUseQuotedPrintable = false;
+ for (String rawData : rawDataList) {
+ if (!needCharset && mUsesQuotedPrintable &&
+ !VCardUtils.containsOnlyPrintableAscii(rawData)) {
+ needCharset = true;
+ }
+ if (!reallyUseQuotedPrintable &&
+ !VCardUtils.containsOnlyNonCrLfPrintableAscii(rawData)) {
+ reallyUseQuotedPrintable = true;
+ }
+ if (needCharset && reallyUseQuotedPrintable) {
+ break;
+ }
+ }
+
+ appendVCardLine(builder, propertyName, attributeList,
+ rawDataList, needCharset, reallyUseQuotedPrintable);
+ }
+
+ /*
+ private void appendVCardLine(final StringBuilder builder,
+ final String propertyName, final List<String> rawDataList) {
+ appendVCardLine(builder, propertyName, rawDataList, false, false);
+ }
+
+ private void appendVCardLine(final StringBuilder builder,
+ final String propertyName, final List<String> rawDataList,
+ final boolean needCharset, boolean needQuotedPrintable) {
+ appendVCardLine(builder, propertyName, null, rawDataList, needCharset, needQuotedPrintable);
+ }*/
+
+ private void appendVCardLine(final StringBuilder builder,
+ final String propertyName,
+ final List<String> attributeList,
+ final List<String> rawDataList, final boolean needCharset,
+ boolean needQuotedPrintable) {
+ builder.append(propertyName);
+ if (attributeList != null && attributeList.size() > 0) {
+ builder.append(VCARD_ATTR_SEPARATOR);
+ appendTypeAttributes(builder, attributeList);
+ }
+ if (needCharset) {
+ builder.append(VCARD_ATTR_SEPARATOR);
+ builder.append(mVCardAttributeCharset);
+ }
+
+ builder.append(VCARD_DATA_SEPARATOR);
+ boolean first = true;
+ for (String rawData : rawDataList) {
+ final String encodedData;
+ if (needQuotedPrintable) {
+ builder.append(VCARD_ATTR_SEPARATOR);
+ builder.append(VCARD_ATTR_ENCODING_QP);
+ encodedData = encodeQuotedPrintable(rawData);
+ } else {
+ // TODO: one line may be too huge, which may be invalid in vCard spec, though
+ // several (even well-known) applications do not care this.
+ encodedData = escapeCharacters(rawData);
+ }
+
+ if (first) {
+ first = false;
+ } else {
+ builder.append(VCARD_ITEM_SEPARATOR);
+ }
+ builder.append(encodedData);
+ }
+ builder.append(VCARD_COL_SEPARATOR);
+ }
+
/**
* VCARD_ATTR_SEPARATOR must be appended before this method being called.
*/
diff --git a/core/java/android/provider/Telephony.java b/core/java/android/provider/Telephony.java
index d8c5a53..9a72d93 100644
--- a/core/java/android/provider/Telephony.java
+++ b/core/java/android/provider/Telephony.java
@@ -152,6 +152,12 @@
* <P>Type: INTEGER (boolean)</P>
*/
public static final String LOCKED = "locked";
+
+ /**
+ * Error code associated with sending or receiving this message
+ * <P>Type: INTEGER</P>
+ */
+ public static final String ERROR_CODE = "error_code";
}
/**
@@ -243,7 +249,7 @@
* @return true if the operation succeeded
*/
public static boolean moveMessageToFolder(Context context,
- Uri uri, int folder) {
+ Uri uri, int folder, int error) {
if (uri == null) {
return false;
}
@@ -266,7 +272,7 @@
return false;
}
- ContentValues values = new ContentValues(2);
+ ContentValues values = new ContentValues(3);
values.put(TYPE, folder);
if (markAsUnread) {
@@ -274,6 +280,7 @@
} else if (markAsRead) {
values.put(READ, Integer.valueOf(1));
}
+ values.put(ERROR_CODE, error);
return 1 == SqliteWrapper.update(context, context.getContentResolver(),
uri, values, null, null);
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 304c927..98a6c2c 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -462,6 +462,7 @@
static final int UPDATE_TEXT_ENTRY_MSG_ID = 15;
static final int WEBCORE_INITIALIZED_MSG_ID = 16;
static final int UPDATE_TEXTFIELD_TEXT_MSG_ID = 17;
+ static final int FIND_AGAIN = 18;
static final int MOVE_OUT_OF_PLUGIN = 19;
static final int CLEAR_TEXT_ENTRY = 20;
static final int UPDATE_TEXT_SELECTION_MSG_ID = 21;
@@ -491,7 +492,7 @@
"UPDATE_TEXT_ENTRY_MSG_ID", // = 15;
"WEBCORE_INITIALIZED_MSG_ID", // = 16;
"UPDATE_TEXTFIELD_TEXT_MSG_ID", // = 17;
- "18", // = 18;
+ "FIND_AGAIN", // = 18;
"MOVE_OUT_OF_PLUGIN", // = 19;
"CLEAR_TEXT_ENTRY", // = 20;
"UPDATE_TEXT_SELECTION_MSG_ID", // = 21;
@@ -2362,6 +2363,7 @@
}
int result = nativeFindAll(find.toLowerCase(), find.toUpperCase());
invalidate();
+ mLastFind = find;
return result;
}
@@ -2369,6 +2371,9 @@
// or not we draw the highlights for matches.
private boolean mFindIsUp;
private int mFindHeight;
+ // Keep track of the last string sent, so we can search again after an
+ // orientation change or the dismissal of the soft keyboard.
+ private String mLastFind;
/**
* Return the first substring consisting of the address of a physical
@@ -5261,6 +5266,13 @@
}
break;
+ case FIND_AGAIN:
+ // Ignore if find has been dismissed.
+ if (mFindIsUp) {
+ findAll(mLastFind);
+ }
+ break;
+
case DRAG_HELD_MOTIONLESS:
mHeldMotionless = MOTIONLESS_TRUE;
invalidate();
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index 6505ee2..b466591 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -2115,6 +2115,13 @@
WebView.CLEAR_TEXT_ENTRY).sendToTarget();
}
+ // called by JNI
+ private void sendFindAgain() {
+ if (mWebView == null) return;
+ Message.obtain(mWebView.mPrivateHandler,
+ WebView.FIND_AGAIN).sendToTarget();
+ }
+
private native void nativeUpdateFrameCacheIfLoading();
/**
diff --git a/core/java/com/android/internal/os/IDropBoxService.aidl b/core/java/com/android/internal/os/IDropBoxService.aidl
new file mode 100644
index 0000000..f940041
--- /dev/null
+++ b/core/java/com/android/internal/os/IDropBoxService.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.os;
+
+import android.os.DropBox;
+import android.os.ParcelFileDescriptor;
+
+/**
+ * "Backend" interface used by {@link android.os.DropBox} to talk to the
+ * DropBoxService that actually implements the drop box functionality.
+ *
+ * @see DropBox
+ * @hide
+ */
+interface IDropBoxService {
+ /**
+ * @see DropBox#addText
+ * @see DropBox#addData
+ * @see DropBox#addFile
+ */
+ void add(in DropBox.Entry entry);
+
+ /** @see DropBox#getNextEntry */
+ boolean isTagEnabled(String tag);
+
+ /** @see DropBox#getNextEntry */
+ DropBox.Entry getNextEntry(String tag, long millis);
+}
diff --git a/core/res/Android.mk b/core/res/Android.mk
index cb5524a..78cb86d 100644
--- a/core/res/Android.mk
+++ b/core/res/Android.mk
@@ -34,3 +34,7 @@
LOCAL_EXPORT_PACKAGE_RESOURCES := true
include $(BUILD_PACKAGE)
+
+# define a global intermediate target that other module may depend on.
+.PHONY: framework-res-package-target
+framework-res-package-target: $(LOCAL_BUILT_MODULE)
diff --git a/data/sounds/ringtones/FreeFlight.ogg b/data/sounds/ringtones/FreeFlight.ogg
new file mode 100644
index 0000000..76dfabe
--- /dev/null
+++ b/data/sounds/ringtones/FreeFlight.ogg
Binary files differ
diff --git a/data/sounds/ringtones/FreeFlight.wav b/data/sounds/ringtones/FreeFlight.wav
new file mode 100644
index 0000000..a4e14aa
--- /dev/null
+++ b/data/sounds/ringtones/FreeFlight.wav
Binary files differ
diff --git a/docs/html/sdk/download.jd b/docs/html/sdk/download.jd
index 76f1213..47505e6 100644
--- a/docs/html/sdk/download.jd
+++ b/docs/html/sdk/download.jd
@@ -58,7 +58,7 @@
<h2>Thank you for downloading the Android SDK!</h2>
<p>Your download should be underway. If not, <a id="click-download">click here to start the download</a>.</p>
<p>To set up your Android development environment, please read the guide to
- <a href="installing.html" class="addVersionPath">Installing the Android SDK</a>.
+ <a href="installing.html">Installing the Android SDK</a>.
Once you have completed the installation, see the
<a href="/guide/index.html">Dev Guide</a> for documentation about
developing Android applications.</p>
diff --git a/include/ui/GraphicBuffer.h b/include/ui/GraphicBuffer.h
index 8897f03..2172536 100644
--- a/include/ui/GraphicBuffer.h
+++ b/include/ui/GraphicBuffer.h
@@ -66,7 +66,11 @@
GraphicBuffer();
// creates w * h buffer
- GraphicBuffer(uint32_t w, uint32_t h, PixelFormat format, uint32_t ssage);
+ GraphicBuffer(uint32_t w, uint32_t h, PixelFormat format, uint32_t usage);
+
+ // create a buffer from an existing handle
+ GraphicBuffer(uint32_t w, uint32_t h, PixelFormat format, uint32_t usage,
+ uint32_t stride, native_handle_t* handle, bool keepOwnership);
// return status
status_t initCheck() const;
@@ -94,9 +98,15 @@
GraphicBuffer(const Parcel& reply);
virtual ~GraphicBuffer();
+ enum {
+ ownNone = 0,
+ ownHandle = 1,
+ ownData = 2,
+ };
+
inline const GraphicBufferMapper& getBufferMapper() const { return mBufferMapper; }
inline GraphicBufferMapper& getBufferMapper() { return mBufferMapper; }
- bool mOwner;
+ uint8_t mOwner;
private:
friend class Surface;
diff --git a/libs/rs/rsContext.cpp b/libs/rs/rsContext.cpp
index cc39dac..eb388af 100644
--- a/libs/rs/rsContext.cpp
+++ b/libs/rs/rsContext.cpp
@@ -30,8 +30,21 @@
pthread_key_t Context::gThreadTLSKey = 0;
uint32_t Context::gThreadTLSKeyCount = 0;
+uint32_t Context::gGLContextCount = 0;
pthread_mutex_t Context::gInitMutex = PTHREAD_MUTEX_INITIALIZER;
+static void checkEglError(const char* op, EGLBoolean returnVal = EGL_TRUE) {
+ if (returnVal != EGL_TRUE) {
+ fprintf(stderr, "%s() returned %d\n", op, returnVal);
+ }
+
+ for (EGLint error = eglGetError(); error != EGL_SUCCESS; error
+ = eglGetError()) {
+ fprintf(stderr, "after %s() eglError %s (0x%x)\n", op, EGLUtils::strerror(error),
+ error);
+ }
+}
+
void Context::initEGL()
{
mEGL.mNumConfigs = -1;
@@ -61,7 +74,10 @@
LOGV("initEGL start");
mEGL.mDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ checkEglError("eglGetDisplay");
+
eglInitialize(mEGL.mDisplay, &mEGL.mMajorVersion, &mEGL.mMinorVersion);
+ checkEglError("eglInitialize");
status_t err = EGLUtils::selectConfigForNativeWindow(mEGL.mDisplay, configAttribs, mWndSurface, &mEGL.mConfig);
if (err) {
@@ -76,9 +92,24 @@
android_createDisplaySurface(),
NULL);
}
+ checkEglError("eglCreateWindowSurface");
+ if (mEGL.mSurface == EGL_NO_SURFACE) {
+ LOGE("eglCreateWindowSurface returned EGL_NO_SURFACE");
+ }
- mEGL.mContext = eglCreateContext(mEGL.mDisplay, mEGL.mConfig, NULL, NULL);
- eglMakeCurrent(mEGL.mDisplay, mEGL.mSurface, mEGL.mSurface, mEGL.mContext);
+ mEGL.mContext = eglCreateContext(mEGL.mDisplay, mEGL.mConfig, EGL_NO_CONTEXT, NULL);
+ checkEglError("eglCreateContext");
+ if (mEGL.mContext == EGL_NO_CONTEXT) {
+ LOGE("eglCreateContext returned EGL_NO_CONTEXT");
+ }
+ gGLContextCount++;
+
+ EGLBoolean ret = eglMakeCurrent(mEGL.mDisplay, mEGL.mSurface, mEGL.mSurface, mEGL.mContext);
+ checkEglError("eglCreateContext", ret);
+ if (mEGL.mContext == EGL_NO_CONTEXT) {
+ LOGE("eglCreateContext returned EGL_NO_CONTEXT");
+ }
+
eglQuerySurface(mEGL.mDisplay, mEGL.mSurface, EGL_WIDTH, &mEGL.mWidth);
eglQuerySurface(mEGL.mDisplay, mEGL.mSurface, EGL_HEIGHT, &mEGL.mHeight);
@@ -101,6 +132,24 @@
}
}
+void Context::deinitEGL()
+{
+ EGLBoolean ret = eglMakeCurrent(mEGL.mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ checkEglError("eglCreateContext", ret);
+ if (mEGL.mContext == EGL_NO_CONTEXT) {
+ LOGE("eglCreateContext returned EGL_NO_CONTEXT");
+ }
+
+ eglDestroyContext(mEGL.mDisplay, mEGL.mContext);
+ checkEglError("eglDestroyContext");
+
+ gGLContextCount--;
+ if (!gGLContextCount) {
+ eglTerminate(mEGL.mDisplay);
+ }
+}
+
+
bool Context::runScript(Script *s, uint32_t launchID)
{
ObjectBaseRef<ProgramFragment> frag(mFragment);
@@ -232,7 +281,9 @@
rsc->props.mLogScripts = getProp("debug.rs.script");
rsc->props.mLogObjects = getProp("debug.rs.objects");
+ pthread_mutex_lock(&gInitMutex);
rsc->initEGL();
+ pthread_mutex_unlock(&gInitMutex);
ScriptTLSStruct *tlsStruct = new ScriptTLSStruct;
if (!tlsStruct) {
@@ -294,7 +345,11 @@
glClearColor(0,0,0,0);
glClear(GL_COLOR_BUFFER_BIT);
eglSwapBuffers(rsc->mEGL.mDisplay, rsc->mEGL.mSurface);
- eglTerminate(rsc->mEGL.mDisplay);
+
+ pthread_mutex_lock(&gInitMutex);
+ rsc->deinitEGL();
+ pthread_mutex_unlock(&gInitMutex);
+
rsc->objDestroyOOBRun();
LOGV("RS Thread exited");
return NULL;
diff --git a/libs/rs/rsContext.h b/libs/rs/rsContext.h
index 0dd90ed..c80fd5a 100644
--- a/libs/rs/rsContext.h
+++ b/libs/rs/rsContext.h
@@ -54,6 +54,7 @@
static pthread_key_t gThreadTLSKey;
static uint32_t gThreadTLSKeyCount;
+ static uint32_t gGLContextCount;
static pthread_mutex_t gInitMutex;
struct ScriptTLSStruct {
@@ -215,6 +216,7 @@
Context();
void initEGL();
+ void deinitEGL();
bool runRootScript();
diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
index f84933e..1abfd68 100644
--- a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
+++ b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
@@ -256,12 +256,16 @@
if (strstr(gl_extensions, "GL_OES_draw_texture")) {
mFlags |= DRAW_TEXTURE_EXTENSION;
}
+#ifdef EGL_ANDROID_image_native_buffer
if (strstr( gl_extensions, "GL_OES_EGL_image") &&
(strstr(egl_extensions, "EGL_KHR_image_base") ||
strstr(egl_extensions, "EGL_KHR_image")) &&
strstr(egl_extensions, "EGL_ANDROID_image_native_buffer")) {
mFlags |= DIRECT_TEXTURE;
}
+#else
+#warning "EGL_ANDROID_image_native_buffer not supported"
+#endif
// Unbind the context from this thread
eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
diff --git a/libs/surfaceflinger/Layer.cpp b/libs/surfaceflinger/Layer.cpp
index 2bb1e12..f5a5a0b 100644
--- a/libs/surfaceflinger/Layer.cpp
+++ b/libs/surfaceflinger/Layer.cpp
@@ -130,62 +130,6 @@
return NO_ERROR;
}
-status_t Layer::initializeEglImageLocked(
- const sp<GraphicBuffer>& buffer, Texture* texture)
-{
- status_t err = NO_ERROR;
-
- // we need to recreate the texture
- EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay());
-
- // free the previous image
- if (texture->image != EGL_NO_IMAGE_KHR) {
- eglDestroyImageKHR(dpy, texture->image);
- texture->image = EGL_NO_IMAGE_KHR;
- }
-
- // construct an EGL_NATIVE_BUFFER_ANDROID
- android_native_buffer_t* clientBuf = buffer->getNativeBuffer();
-
- // create the new EGLImageKHR
- const EGLint attrs[] = {
- EGL_IMAGE_PRESERVED_KHR, EGL_TRUE,
- EGL_NONE, EGL_NONE
- };
- texture->image = eglCreateImageKHR(
- dpy, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
- (EGLClientBuffer)clientBuf, attrs);
-
- LOGE_IF(texture->image == EGL_NO_IMAGE_KHR,
- "eglCreateImageKHR() failed. err=0x%4x",
- eglGetError());
-
- if (texture->image != EGL_NO_IMAGE_KHR) {
- glBindTexture(GL_TEXTURE_2D, texture->name);
- glEGLImageTargetTexture2DOES(GL_TEXTURE_2D,
- (GLeglImageOES)texture->image);
- GLint error = glGetError();
- if (UNLIKELY(error != GL_NO_ERROR)) {
- // this failed, for instance, because we don't support NPOT.
- // FIXME: do something!
- LOGE("layer=%p, glEGLImageTargetTexture2DOES(%p) "
- "failed err=0x%04x",
- this, texture->image, error);
- mFlags &= ~DisplayHardware::DIRECT_TEXTURE;
- err = INVALID_OPERATION;
- } else {
- // Everything went okay!
- texture->NPOTAdjust = false;
- texture->dirty = false;
- texture->width = clientBuf->width;
- texture->height = clientBuf->height;
- }
- } else {
- err = INVALID_OPERATION;
- }
- return err;
-}
-
void Layer::reloadTexture(const Region& dirty)
{
Mutex::Autolock _l(mLock);
@@ -199,10 +143,11 @@
mTextures[index].height = 0;
}
+#ifdef EGL_ANDROID_image_native_buffer
if (mFlags & DisplayHardware::DIRECT_TEXTURE) {
if (buffer->usage & GraphicBuffer::USAGE_HW_TEXTURE) {
if (mTextures[index].dirty) {
- initializeEglImageLocked(buffer, &mTextures[index]);
+ initializeEglImage(buffer, &mTextures[index]);
}
} else {
if (mHybridBuffer==0 || (mHybridBuffer->width != buffer->width ||
@@ -212,7 +157,7 @@
buffer->width, buffer->height, buffer->format,
GraphicBuffer::USAGE_SW_WRITE_OFTEN |
GraphicBuffer::USAGE_HW_TEXTURE);
- initializeEglImageLocked(
+ initializeEglImage(
mHybridBuffer, &mTextures[0]);
}
@@ -279,7 +224,9 @@
buffer->unlock();
}
}
- } else {
+ } else
+#endif
+ {
for (size_t i=0 ; i<NUM_BUFFERS ; i++) {
mTextures[i].image = EGL_NO_IMAGE_KHR;
}
diff --git a/libs/surfaceflinger/Layer.h b/libs/surfaceflinger/Layer.h
index 57b3dfa..1310ecc 100644
--- a/libs/surfaceflinger/Layer.h
+++ b/libs/surfaceflinger/Layer.h
@@ -85,8 +85,6 @@
}
void reloadTexture(const Region& dirty);
- status_t initializeEglImageLocked(
- const sp<GraphicBuffer>& buffer, Texture* texture);
uint32_t getEffectiveUsage(uint32_t usage) const;
diff --git a/libs/surfaceflinger/LayerBase.cpp b/libs/surfaceflinger/LayerBase.cpp
index ecc7894..8003d22 100644
--- a/libs/surfaceflinger/LayerBase.cpp
+++ b/libs/surfaceflinger/LayerBase.cpp
@@ -617,6 +617,63 @@
}
}
+status_t LayerBase::initializeEglImage(
+ const sp<GraphicBuffer>& buffer, Texture* texture)
+{
+ status_t err = NO_ERROR;
+
+ // we need to recreate the texture
+ EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay());
+
+ // free the previous image
+ if (texture->image != EGL_NO_IMAGE_KHR) {
+ eglDestroyImageKHR(dpy, texture->image);
+ texture->image = EGL_NO_IMAGE_KHR;
+ }
+
+ // construct an EGL_NATIVE_BUFFER_ANDROID
+ android_native_buffer_t* clientBuf = buffer->getNativeBuffer();
+
+ // create the new EGLImageKHR
+ const EGLint attrs[] = {
+ EGL_IMAGE_PRESERVED_KHR, EGL_TRUE,
+ EGL_NONE, EGL_NONE
+ };
+ texture->image = eglCreateImageKHR(
+ dpy, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
+ (EGLClientBuffer)clientBuf, attrs);
+
+ LOGE_IF(texture->image == EGL_NO_IMAGE_KHR,
+ "eglCreateImageKHR() failed. err=0x%4x",
+ eglGetError());
+
+ if (texture->image != EGL_NO_IMAGE_KHR) {
+ glBindTexture(GL_TEXTURE_2D, texture->name);
+ glEGLImageTargetTexture2DOES(GL_TEXTURE_2D,
+ (GLeglImageOES)texture->image);
+ GLint error = glGetError();
+ if (UNLIKELY(error != GL_NO_ERROR)) {
+ // this failed, for instance, because we don't support NPOT.
+ // FIXME: do something!
+ LOGE("layer=%p, glEGLImageTargetTexture2DOES(%p) "
+ "failed err=0x%04x",
+ this, texture->image, error);
+ mFlags &= ~DisplayHardware::DIRECT_TEXTURE;
+ err = INVALID_OPERATION;
+ } else {
+ // Everything went okay!
+ texture->NPOTAdjust = false;
+ texture->dirty = false;
+ texture->width = clientBuf->width;
+ texture->height = clientBuf->height;
+ }
+ } else {
+ err = INVALID_OPERATION;
+ }
+ return err;
+}
+
+
// ---------------------------------------------------------------------------
int32_t LayerBaseClient::sIdentity = 0;
diff --git a/libs/surfaceflinger/LayerBase.h b/libs/surfaceflinger/LayerBase.h
index efa4f8c..ed07b3f 100644
--- a/libs/surfaceflinger/LayerBase.h
+++ b/libs/surfaceflinger/LayerBase.h
@@ -261,6 +261,8 @@
void drawWithOpenGL(const Region& clip, const Texture& texture) const;
void loadTexture(Texture* texture,
const Region& dirty, const GGLSurface& t) const;
+ status_t initializeEglImage(
+ const sp<GraphicBuffer>& buffer, Texture* texture);
sp<SurfaceFlinger> mFlinger;
diff --git a/libs/surfaceflinger/LayerBuffer.cpp b/libs/surfaceflinger/LayerBuffer.cpp
index 7e27a02..6590503 100644
--- a/libs/surfaceflinger/LayerBuffer.cpp
+++ b/libs/surfaceflinger/LayerBuffer.cpp
@@ -339,12 +339,6 @@
mLayer.setNeedsBlending((info.h_alpha - info.l_alpha) > 0);
mBufferSize = info.getScanlineSize(buffers.hor_stride)*buffers.ver_stride;
mLayer.forceVisibilityTransaction();
-
- hw_module_t const* module;
- mBlitEngine = NULL;
- if (hw_get_module(COPYBIT_HARDWARE_MODULE_ID, &module) == 0) {
- copybit_open(module, &mBlitEngine);
- }
}
LayerBuffer::BufferSource::~BufferSource()
@@ -352,8 +346,9 @@
if (mTexture.name != -1U) {
glDeleteTextures(1, &mTexture.name);
}
- if (mBlitEngine) {
- copybit_close(mBlitEngine);
+ if (mTexture.image != EGL_NO_IMAGE_KHR) {
+ EGLDisplay dpy(mLayer.mFlinger->graphicPlane(0).getEGLDisplay());
+ eglDestroyImageKHR(dpy, mTexture.image);
}
}
@@ -421,122 +416,28 @@
status_t err = NO_ERROR;
NativeBuffer src(ourBuffer->getBuffer());
const Rect transformedBounds(mLayer.getTransformedBounds());
- copybit_device_t* copybit = mBlitEngine;
- if (copybit) {
- const int src_width = src.crop.r - src.crop.l;
- const int src_height = src.crop.b - src.crop.t;
- int W = transformedBounds.width();
- int H = transformedBounds.height();
- if (mLayer.getOrientation() & Transform::ROT_90) {
- int t(W); W=H; H=t;
- }
+ if (UNLIKELY(mTexture.name == -1LU)) {
+ mTexture.name = mLayer.createTexture();
+ }
-#ifdef EGL_ANDROID_get_render_buffer
- EGLDisplay dpy = eglGetCurrentDisplay();
- EGLSurface draw = eglGetCurrentSurface(EGL_DRAW);
- EGLClientBuffer clientBuf = eglGetRenderBufferANDROID(dpy, draw);
- android_native_buffer_t* nb = (android_native_buffer_t*)clientBuf;
- if (nb == 0) {
- err = BAD_VALUE;
- } else {
- copybit_image_t dst;
- dst.w = nb->width;
- dst.h = nb->height;
- dst.format = nb->format;
- dst.base = NULL; // unused by copybit on msm7k
- dst.handle = (native_handle_t *)nb->handle;
+#if defined(EGL_ANDROID_image_native_buffer)
+ if (mLayer.mFlags & DisplayHardware::DIRECT_TEXTURE) {
+ // NOTE: Assume the buffer is allocated with the proper USAGE flags
+ sp<GraphicBuffer> graphicBuffer = new GraphicBuffer(
+ src.crop.r, src.crop.b, src.img.format,
+ GraphicBuffer::USAGE_HW_TEXTURE,
+ src.img.w, src.img.handle, false);
- /* With LayerBuffer, it is likely that we'll have to rescale the
- * surface, because this is often used for video playback or
- * camera-preview. Since we want these operation as fast as possible
- * we make sure we can use the 2D H/W even if it doesn't support
- * the requested scale factor, in which case we perform the scaling
- * in several passes. */
-
- const float min = copybit->get(copybit, COPYBIT_MINIFICATION_LIMIT);
- const float mag = copybit->get(copybit, COPYBIT_MAGNIFICATION_LIMIT);
-
- float xscale = 1.0f;
- if (src_width > W*min) xscale = 1.0f / min;
- else if (src_width*mag < W) xscale = mag;
-
- float yscale = 1.0f;
- if (src_height > H*min) yscale = 1.0f / min;
- else if (src_height*mag < H) yscale = mag;
-
- if (UNLIKELY(xscale!=1.0f || yscale!=1.0f)) {
- const int tmp_w = floorf(src_width * xscale);
- const int tmp_h = floorf(src_height * yscale);
-
- if (mTempBitmap==0 ||
- mTempBitmap->getWidth() < size_t(tmp_w) ||
- mTempBitmap->getHeight() < size_t(tmp_h)) {
- mTempBitmap.clear();
- mTempBitmap = new GraphicBuffer(
- tmp_w, tmp_h, src.img.format,
- GraphicBuffer::USAGE_HW_2D);
- err = mTempBitmap->initCheck();
- }
-
- if (LIKELY(err == NO_ERROR)) {
- NativeBuffer tmp;
- tmp.img.w = tmp_w;
- tmp.img.h = tmp_h;
- tmp.img.format = src.img.format;
- tmp.img.handle = (native_handle_t*)mTempBitmap->getNativeBuffer()->handle;
- tmp.crop.l = 0;
- tmp.crop.t = 0;
- tmp.crop.r = tmp.img.w;
- tmp.crop.b = tmp.img.h;
-
- region_iterator tmp_it(Region(Rect(tmp.crop.r, tmp.crop.b)));
- copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0);
- copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 0xFF);
- copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_DISABLE);
- err = copybit->stretch(copybit,
- &tmp.img, &src.img, &tmp.crop, &src.crop, &tmp_it);
- src = tmp;
- }
- }
-
- const Rect transformedBounds(mLayer.getTransformedBounds());
- const copybit_rect_t& drect =
- reinterpret_cast<const copybit_rect_t&>(transformedBounds);
- const State& s(mLayer.drawingState());
- region_iterator it(clip);
-
- // pick the right orientation for this buffer
- int orientation = mLayer.getOrientation();
- if (UNLIKELY(mBufferHeap.transform)) {
- Transform rot90;
- GraphicPlane::orientationToTransfrom(
- ISurfaceComposer::eOrientation90, 0, 0, &rot90);
- const Transform& planeTransform(mLayer.graphicPlane(0).transform());
- const Layer::State& s(mLayer.drawingState());
- Transform tr(planeTransform * s.transform * rot90);
- orientation = tr.getOrientation();
- }
-
- copybit->set_parameter(copybit, COPYBIT_TRANSFORM, orientation);
- copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, s.alpha);
- copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_ENABLE);
-
- err = copybit->stretch(copybit,
- &dst, &src.img, &drect, &src.crop, &it);
- if (err != NO_ERROR) {
- LOGE("copybit failed (%s)", strerror(err));
- }
- }
+ err = mLayer.initializeEglImage(graphicBuffer, &mTexture);
}
#endif
-
- if (!copybit || err)
- {
+ else {
+ err = INVALID_OPERATION;
+ }
+
+ if (err != NO_ERROR) {
// OpenGL fall-back
- if (UNLIKELY(mTexture.name == -1LU)) {
- mTexture.name = mLayer.createTexture();
- }
GLuint w = 0;
GLuint h = 0;
GGLSurface t;
@@ -549,11 +450,11 @@
t.data = (GGLubyte*)src.img.base;
const Region dirty(Rect(t.width, t.height));
mLayer.loadTexture(&mTexture, dirty, t);
- mTexture.transform = mBufferHeap.transform;
- mLayer.drawWithOpenGL(clip, mTexture);
}
-}
+ mTexture.transform = mBufferHeap.transform;
+ mLayer.drawWithOpenGL(clip, mTexture);
+}
// ---------------------------------------------------------------------------
diff --git a/libs/surfaceflinger/LayerBuffer.h b/libs/surfaceflinger/LayerBuffer.h
index 5eb472c..438b711 100644
--- a/libs/surfaceflinger/LayerBuffer.h
+++ b/libs/surfaceflinger/LayerBuffer.h
@@ -132,7 +132,6 @@
size_t mBufferSize;
mutable sp<GraphicBuffer> mTempBitmap;
mutable LayerBase::Texture mTexture;
- copybit_device_t* mBlitEngine;
};
class OverlaySource : public Source {
diff --git a/libs/surfaceflinger/LayerDim.cpp b/libs/surfaceflinger/LayerDim.cpp
index 538dc77..fd61e30 100644
--- a/libs/surfaceflinger/LayerDim.cpp
+++ b/libs/surfaceflinger/LayerDim.cpp
@@ -55,8 +55,8 @@
sHeight = h;
sUseTexture = false;
-#ifdef DIM_WITH_TEXTURE
-
+#if defined(DIM_WITH_TEXTURE) && defined(EGL_ANDROID_image_native_buffer)
+
#warning "using a texture to implement LayerDim"
/* On some h/w like msm7K, it is faster to use a texture because the
@@ -69,7 +69,6 @@
uint32_t flags = hw.getFlags();
if (LIKELY(flags & DisplayHardware::DIRECT_TEXTURE)) {
- // TODO: api to pass the usage flags
sp<GraphicBuffer> buffer = new GraphicBuffer(w, h, PIXEL_FORMAT_RGB_565,
GraphicBuffer::USAGE_SW_WRITE_OFTEN |
GraphicBuffer::USAGE_HW_TEXTURE);
@@ -123,7 +122,7 @@
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glColor4x(0, 0, 0, alpha);
-#ifdef DIM_WITH_TEXTURE
+#if defined(DIM_WITH_TEXTURE) && defined(EGL_ANDROID_image_native_buffer)
if (sUseTexture) {
glBindTexture(GL_TEXTURE_2D, sTexId);
glEnable(GL_TEXTURE_2D);
diff --git a/libs/surfaceflinger/SurfaceFlinger.h b/libs/surfaceflinger/SurfaceFlinger.h
index 6698e00..f9bfe6c 100644
--- a/libs/surfaceflinger/SurfaceFlinger.h
+++ b/libs/surfaceflinger/SurfaceFlinger.h
@@ -246,8 +246,10 @@
virtual status_t readyToRun();
virtual void onFirstRef();
+public: // hack to work around gcc 4.0.3 bug
const GraphicPlane& graphicPlane(int dpy) const;
GraphicPlane& graphicPlane(int dpy);
+private:
void waitForEvent();
public: // hack to work around gcc 4.0.3 bug
diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp
index 1cf20d7..efe2d78 100644
--- a/libs/ui/GraphicBuffer.cpp
+++ b/libs/ui/GraphicBuffer.cpp
@@ -37,7 +37,7 @@
// ===========================================================================
GraphicBuffer::GraphicBuffer()
- : BASE(), mOwner(false), mBufferMapper(GraphicBufferMapper::get()),
+ : BASE(), mOwner(ownData), mBufferMapper(GraphicBufferMapper::get()),
mInitCheck(NO_ERROR), mVStride(0), mIndex(-1)
{
width =
@@ -50,7 +50,7 @@
GraphicBuffer::GraphicBuffer(uint32_t w, uint32_t h,
PixelFormat reqFormat, uint32_t reqUsage)
- : BASE(), mOwner(false), mBufferMapper(GraphicBufferMapper::get()),
+ : BASE(), mOwner(ownData), mBufferMapper(GraphicBufferMapper::get()),
mInitCheck(NO_ERROR), mVStride(0), mIndex(-1)
{
width =
@@ -62,8 +62,23 @@
mInitCheck = initSize(w, h, reqFormat, reqUsage);
}
+GraphicBuffer::GraphicBuffer(uint32_t w, uint32_t h,
+ PixelFormat inFormat, uint32_t inUsage,
+ uint32_t inStride, native_handle_t* inHandle, bool keepOwnership)
+ : BASE(), mOwner(keepOwnership ? ownHandle : ownNone),
+ mBufferMapper(GraphicBufferMapper::get()),
+ mInitCheck(NO_ERROR), mVStride(0), mIndex(-1)
+{
+ width = w;
+ height = h;
+ stride = inStride;
+ format = inFormat;
+ usage = inUsage;
+ handle = inHandle;
+}
+
GraphicBuffer::GraphicBuffer(const Parcel& data)
- : BASE(), mOwner(true), mBufferMapper(GraphicBufferMapper::get()),
+ : BASE(), mOwner(ownHandle), mBufferMapper(GraphicBufferMapper::get()),
mInitCheck(NO_ERROR), mVStride(0), mIndex(-1)
{
// we own the handle in this case
@@ -83,10 +98,10 @@
GraphicBuffer::~GraphicBuffer()
{
if (handle) {
- if (mOwner) {
+ if (mOwner == ownHandle) {
native_handle_close(handle);
native_handle_delete(const_cast<native_handle*>(handle));
- } else {
+ } else if (mOwner == ownData) {
GraphicBufferAllocator& allocator(GraphicBufferAllocator::get());
allocator.free(handle);
}
@@ -106,6 +121,9 @@
status_t GraphicBuffer::reallocate(uint32_t w, uint32_t h, PixelFormat f,
uint32_t reqUsage)
{
+ if (mOwner != ownData)
+ return INVALID_OPERATION;
+
if (handle) {
GraphicBufferAllocator& allocator(GraphicBufferAllocator::get());
allocator.free(handle);
diff --git a/media/java/android/media/AsyncPlayer.java b/media/java/android/media/AsyncPlayer.java
index 35f0409..e1e09b9 100644
--- a/media/java/android/media/AsyncPlayer.java
+++ b/media/java/android/media/AsyncPlayer.java
@@ -19,10 +19,12 @@
import android.content.Context;
import android.net.Uri;
import android.os.PowerManager;
+import android.os.SystemClock;
import android.util.Log;
import java.io.IOException;
import java.lang.IllegalStateException;
+import java.util.LinkedList;
/**
* Plays a series of audio URIs, but does all the hard work on another thread
@@ -31,14 +33,15 @@
public class AsyncPlayer {
private static final int PLAY = 1;
private static final int STOP = 2;
+ private static final boolean mDebug = false;
private static final class Command {
- Command next;
int code;
Context context;
Uri uri;
boolean looping;
int stream;
+ long requestTime;
public String toString() {
return "{ code=" + code + " looping=" + looping + " stream=" + stream
@@ -46,6 +49,36 @@
}
}
+ private LinkedList<Command> mCmdQueue = new LinkedList();
+
+ private void startSound(Command cmd) {
+ // Preparing can be slow, so if there is something else
+ // is playing, let it continue until we're done, so there
+ // is less of a glitch.
+ try {
+ if (mDebug) Log.d(mTag, "Starting playback");
+ MediaPlayer player = new MediaPlayer();
+ player.setAudioStreamType(cmd.stream);
+ player.setDataSource(cmd.context, cmd.uri);
+ player.setLooping(cmd.looping);
+ player.prepare();
+ player.start();
+ if (mPlayer != null) {
+ mPlayer.release();
+ }
+ mPlayer = player;
+ long delay = SystemClock.uptimeMillis() - cmd.requestTime;
+ if (delay > 1000) {
+ Log.w(mTag, "Notification sound delayed by " + delay + "msecs");
+ }
+ }
+ catch (IOException e) {
+ Log.w(mTag, "error loading sound for " + cmd.uri, e);
+ } catch (IllegalStateException e) {
+ Log.w(mTag, "IllegalStateException (content provider died?) " + cmd.uri, e);
+ }
+ }
+
private final class Thread extends java.lang.Thread {
Thread() {
super("AsyncPlayer-" + mTag);
@@ -55,41 +88,23 @@
while (true) {
Command cmd = null;
- synchronized (mLock) {
- if (mHead != null) {
- cmd = mHead;
- mHead = cmd.next;
- if (mTail == cmd) {
- mTail = null;
- }
- }
+ synchronized (mCmdQueue) {
+ if (mDebug) Log.d(mTag, "RemoveFirst");
+ cmd = mCmdQueue.removeFirst();
}
switch (cmd.code) {
case PLAY:
- try {
- // Preparing can be slow, so if there is something else
- // is playing, let it continue until we're done, so there
- // is less of a glitch.
- MediaPlayer player = new MediaPlayer();
- player.setAudioStreamType(cmd.stream);
- player.setDataSource(cmd.context, cmd.uri);
- player.setLooping(cmd.looping);
- player.prepare();
- player.start();
- if (mPlayer != null) {
- mPlayer.release();
- }
- mPlayer = player;
- }
- catch (IOException e) {
- Log.w(mTag, "error loading sound for " + cmd.uri, e);
- } catch (IllegalStateException e) {
- Log.w(mTag, "IllegalStateException (content provider died?) " + cmd.uri, e);
- }
+ if (mDebug) Log.d(mTag, "PLAY");
+ startSound(cmd);
break;
case STOP:
+ if (mDebug) Log.d(mTag, "STOP");
if (mPlayer != null) {
+ long delay = SystemClock.uptimeMillis() - cmd.requestTime;
+ if (delay > 1000) {
+ Log.w(mTag, "Notification stop delayed by " + delay + "msecs");
+ }
mPlayer.stop();
mPlayer.release();
mPlayer = null;
@@ -99,8 +114,8 @@
break;
}
- synchronized (mLock) {
- if (mHead == null) {
+ synchronized (mCmdQueue) {
+ if (mCmdQueue.size() == 0) {
// nothing left to do, quit
// doing this check after we're done prevents the case where they
// added it during the operation from spawning two threads and
@@ -115,11 +130,8 @@
}
private String mTag;
- private Command mHead;
- private Command mTail;
private Thread mThread;
private MediaPlayer mPlayer;
- private Object mLock = new Object();
private PowerManager.WakeLock mWakeLock;
// The current state according to the caller. Reality lags behind
@@ -154,12 +166,13 @@
*/
public void play(Context context, Uri uri, boolean looping, int stream) {
Command cmd = new Command();
+ cmd.requestTime = SystemClock.uptimeMillis();
cmd.code = PLAY;
cmd.context = context;
cmd.uri = uri;
cmd.looping = looping;
cmd.stream = stream;
- synchronized (mLock) {
+ synchronized (mCmdQueue) {
enqueueLocked(cmd);
mState = PLAY;
}
@@ -170,11 +183,12 @@
* at this point. Calling this multiple times has no ill effects.
*/
public void stop() {
- synchronized (mLock) {
+ synchronized (mCmdQueue) {
// This check allows stop to be called multiple times without starting
// a thread that ends up doing nothing.
if (mState != STOP) {
Command cmd = new Command();
+ cmd.requestTime = SystemClock.uptimeMillis();
cmd.code = STOP;
enqueueLocked(cmd);
mState = STOP;
@@ -183,12 +197,7 @@
}
private void enqueueLocked(Command cmd) {
- if (mTail == null) {
- mHead = cmd;
- } else {
- mTail.next = cmd;
- }
- mTail = cmd;
+ mCmdQueue.add(cmd);
if (mThread == null) {
acquireWakeLock();
mThread = new Thread();
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index d90871e..58a0bba 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -959,10 +959,10 @@
///////////////////////////////////////////////////////////////////////////
public class VolumeStreamState {
- private final String mVolumeIndexSettingName;
- private final String mLastAudibleVolumeIndexSettingName;
private final int mStreamType;
+ private String mVolumeIndexSettingName;
+ private String mLastAudibleVolumeIndexSettingName;
private int mIndexMax;
private int mIndex;
private int mLastAudibleIndex;
@@ -970,8 +970,7 @@
private VolumeStreamState(String settingName, int streamType) {
- mVolumeIndexSettingName = settingName;
- mLastAudibleVolumeIndexSettingName = settingName + System.APPEND_FOR_LAST_AUDIBLE;
+ setVolumeIndexSettingName(settingName);
mStreamType = streamType;
@@ -991,6 +990,11 @@
mDeathHandlers = new ArrayList<VolumeDeathHandler>();
}
+ public void setVolumeIndexSettingName(String settingName) {
+ mVolumeIndexSettingName = settingName;
+ mLastAudibleVolumeIndexSettingName = settingName + System.APPEND_FOR_LAST_AUDIBLE;
+ }
+
public boolean adjustIndex(int deltaIndex) {
return setIndex(mIndex + deltaIndex * 10, true);
}
@@ -1370,11 +1374,17 @@
mNotificationsUseRingVolume = notificationsUseRingVolume;
if (mNotificationsUseRingVolume == 1) {
STREAM_VOLUME_ALIAS[AudioSystem.STREAM_NOTIFICATION] = AudioSystem.STREAM_RING;
+ mStreamStates[AudioSystem.STREAM_NOTIFICATION].setVolumeIndexSettingName(
+ System.VOLUME_SETTINGS[AudioSystem.STREAM_RING]);
} else {
STREAM_VOLUME_ALIAS[AudioSystem.STREAM_NOTIFICATION] = AudioSystem.STREAM_NOTIFICATION;
+ mStreamStates[AudioSystem.STREAM_NOTIFICATION].setVolumeIndexSettingName(
+ System.VOLUME_SETTINGS[AudioSystem.STREAM_NOTIFICATION]);
// Persist notification volume volume as it was not persisted while aliased to ring volume
+ // and persist with no delay as there might be registered observers of the persisted
+ // notification volume.
sendMsg(mAudioHandler, MSG_PERSIST_VOLUME, AudioSystem.STREAM_NOTIFICATION,
- SENDMSG_REPLACE, 0, 0, mStreamStates[AudioSystem.STREAM_NOTIFICATION], PERSIST_DELAY);
+ SENDMSG_REPLACE, 0, 0, mStreamStates[AudioSystem.STREAM_NOTIFICATION], 0);
}
}
}
diff --git a/media/libmediaplayerservice/TestPlayerStub.cpp b/media/libmediaplayerservice/TestPlayerStub.cpp
index 8627708..aa49429 100644
--- a/media/libmediaplayerservice/TestPlayerStub.cpp
+++ b/media/libmediaplayerservice/TestPlayerStub.cpp
@@ -176,7 +176,7 @@
mContentUrl = NULL;
if (mPlayer) {
- LOG_ASSERT(mDeletePlayer != NULL);
+ LOG_ASSERT(mDeletePlayer != NULL, "mDeletePlayer is null");
(*mDeletePlayer)(mPlayer);
mPlayer = NULL;
}
diff --git a/opengl/libagl/Android.mk b/opengl/libagl/Android.mk
index 2522656..9837845 100644
--- a/opengl/libagl/Android.mk
+++ b/opengl/libagl/Android.mk
@@ -25,6 +25,13 @@
primitives.cpp.arm \
vertex.cpp.arm
+LOCAL_CFLAGS += -DLOG_TAG=\"libagl\"
+LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
+LOCAL_CFLAGS += -fvisibility=hidden
+
+LOCAL_SHARED_LIBRARIES := libcutils libhardware libutils libpixelflinger
+LOCAL_LDLIBS := -lpthread -ldl
+
ifeq ($(TARGET_ARCH),arm)
LOCAL_SRC_FILES += fixed_asm.S iterators.S
LOCAL_CFLAGS += -fstrict-aliasing
@@ -38,15 +45,9 @@
ifeq ($(LIBAGL_USE_GRALLOC_COPYBITS),1)
LOCAL_CFLAGS += -DLIBAGL_USE_GRALLOC_COPYBITS
LOCAL_SRC_FILES += copybit.cpp
+ LOCAL_SHARED_LIBRARIES += libui
endif
-LOCAL_CFLAGS += -DLOG_TAG=\"libagl\"
-LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
-
-LOCAL_SHARED_LIBRARIES := libcutils libhardware libutils libpixelflinger
-LOCAL_CFLAGS += -fvisibility=hidden
-
-LOCAL_LDLIBS := -lpthread -ldl
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/egl
LOCAL_MODULE:= libGLES_android
diff --git a/opengl/libagl/copybit.cpp b/opengl/libagl/copybit.cpp
index 73b2355..0c3d0ee 100644
--- a/opengl/libagl/copybit.cpp
+++ b/opengl/libagl/copybit.cpp
@@ -33,6 +33,10 @@
#include <hardware/copybit.h>
#include <private/ui/android_natives_priv.h>
+#include <ui/GraphicBuffer.h>
+#include <ui/Region.h>
+#include <ui/Rect.h>
+
#define DEBUG_COPYBIT true
@@ -175,16 +179,6 @@
dtdy /= screen_h;
}
dtdy = -dtdy; // see equation of dtdy above
- if (dsdx < c->copybits.minScale || dsdx > c->copybits.maxScale
- || dtdy < c->copybits.minScale || dtdy > c->copybits.maxScale) {
- // The requested scale is out of the range the hardware
- // can support.
- LOGD_IF(DEBUG_COPYBIT,
- "scale out of range dsdx=%08x (Wcr=%d / w=%d), "
- "dtdy=%08x (Hcr=%d / h=%d), Ucr=%d, Vcr=%d",
- dsdx, Wcr, w, dtdy, Hcr, h, Ucr, Vcr);
- return false;
- }
// copybit doesn't say anything about filtering, so we can't
// discriminate. On msm7k, copybit will always filter.
@@ -278,21 +272,93 @@
return false;
}
-
- // LOGW("calling copybits");
-
copybit_device_t* copybit = c->copybits.blitEngine;
+ copybit_image_t src;
+ buffer_handle_t source_hnd = textureObject->buffer->handle;
+ textureToCopyBitImage(&textureObject->surface, opFormat, source_hnd, &src);
+ copybit_rect_t srect = { Ucr, Vcr + Hcr, Ucr + Wcr, Vcr };
+
+ /*
+ * Below we perform extra passes needed to emulate things the h/w
+ * cannot do.
+ */
+
+ const GLfixed minScaleInv = gglDivQ(0x10000, c->copybits.minScale, 16);
+ const GLfixed maxScaleInv = gglDivQ(0x10000, c->copybits.maxScale, 16);
+
+ sp<GraphicBuffer> tempBitmap;
+
+ if (dsdx < maxScaleInv || dsdx > minScaleInv ||
+ dtdy < maxScaleInv || dtdy > minScaleInv)
+ {
+ // The requested scale is out of the range the hardware
+ // can support.
+ LOGD_IF(DEBUG_COPYBIT,
+ "scale out of range dsdx=%08x (Wcr=%d / w=%d), "
+ "dtdy=%08x (Hcr=%d / h=%d), Ucr=%d, Vcr=%d",
+ dsdx, Wcr, w, dtdy, Hcr, h, Ucr, Vcr);
+
+ int32_t xscale=0x10000, yscale=0x10000;
+ if (dsdx > minScaleInv) xscale = c->copybits.minScale;
+ else if (dsdx < maxScaleInv) xscale = c->copybits.maxScale;
+ if (dtdy > minScaleInv) yscale = c->copybits.minScale;
+ else if (dtdy < maxScaleInv) yscale = c->copybits.maxScale;
+ dsdx = gglMulx(dsdx, xscale);
+ dtdy = gglMulx(dtdy, yscale);
+
+ /* we handle only one step of resizing below. Handling an arbitrary
+ * number is relatively easy (replace "if" above by "while"), but requires
+ * two intermediate buffers and so far we never had the need.
+ */
+
+ if (dsdx < maxScaleInv || dsdx > minScaleInv ||
+ dtdy < maxScaleInv || dtdy > minScaleInv) {
+ LOGD_IF(DEBUG_COPYBIT,
+ "scale out of range dsdx=%08x (Wcr=%d / w=%d), "
+ "dtdy=%08x (Hcr=%d / h=%d), Ucr=%d, Vcr=%d",
+ dsdx, Wcr, w, dtdy, Hcr, h, Ucr, Vcr);
+ return false;
+ }
+
+ const int tmp_w = gglMulx(srect.r - srect.l, xscale, 16);
+ const int tmp_h = gglMulx(srect.b - srect.t, yscale, 16);
+
+ LOGD_IF(DEBUG_COPYBIT,
+ "xscale=%08x, yscale=%08x, dsdx=%08x, dtdy=%08x, tmp_w=%d, tmp_h=%d",
+ xscale, yscale, dsdx, dtdy, tmp_w, tmp_h);
+
+ tempBitmap = new GraphicBuffer(
+ tmp_w, tmp_h, src.format,
+ GraphicBuffer::USAGE_HW_2D);
+
+ status_t err = tempBitmap->initCheck();
+ if (err == NO_ERROR) {
+ copybit_image_t tmp_dst;
+ copybit_rect_t tmp_rect;
+ tmp_dst.w = tmp_w;
+ tmp_dst.h = tmp_h;
+ tmp_dst.format = src.format;
+ tmp_dst.handle = (native_handle_t*)tempBitmap->getNativeBuffer()->handle;
+ tmp_rect.l = 0;
+ tmp_rect.t = 0;
+ tmp_rect.r = tmp_dst.w;
+ tmp_rect.b = tmp_dst.h;
+ region_iterator tmp_it(Region(Rect(tmp_rect.r, tmp_rect.b)));
+ copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0);
+ copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 0xFF);
+ copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_DISABLE);
+ err = copybit->stretch(copybit,
+ &tmp_dst, &src, &tmp_rect, &srect, &tmp_it);
+ src = tmp_dst;
+ srect = tmp_rect;
+ }
+ }
copybit_image_t dst;
buffer_handle_t target_hnd = c->copybits.drawSurfaceBuffer;
textureToCopyBitImage(&cbSurface, cbSurface.format, target_hnd, &dst);
copybit_rect_t drect = {x, y, x+w, y+h};
- copybit_image_t src;
- buffer_handle_t source_hnd = textureObject->buffer->handle;
- textureToCopyBitImage(&textureObject->surface, opFormat, source_hnd, &src);
- copybit_rect_t srect = { Ucr, Vcr + Hcr, Ucr + Wcr, Vcr };
-
copybit->set_parameter(copybit, COPYBIT_TRANSFORM, transform);
copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, planeAlpha);
copybit->set_parameter(copybit, COPYBIT_DITHER,
diff --git a/opengl/tests/linetex/Android.mk b/opengl/tests/linetex/Android.mk
new file mode 100644
index 0000000..6ff248d
--- /dev/null
+++ b/opengl/tests/linetex/Android.mk
@@ -0,0 +1,17 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ linetex.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+ libcutils \
+ libEGL \
+ libGLESv1_CM \
+ libui
+
+LOCAL_MODULE:= test-opengl-linetex
+
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_EXECUTABLE)
diff --git a/opengl/tests/linetex/linetex.cpp b/opengl/tests/linetex/linetex.cpp
new file mode 100644
index 0000000..e62fe03
--- /dev/null
+++ b/opengl/tests/linetex/linetex.cpp
@@ -0,0 +1,117 @@
+/*
+**
+** Copyright 2006, 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.
+*/
+
+#define LOG_TAG "fillrate"
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <EGL/egl.h>
+#include <GLES/gl.h>
+#include <GLES/glext.h>
+
+#include <utils/StopWatch.h>
+#include <ui/FramebufferNativeWindow.h>
+#include <ui/EGLUtils.h>
+
+using namespace android;
+
+int main(int argc, char** argv)
+{
+ EGLint configAttribs[] = {
+ EGL_DEPTH_SIZE, 0,
+ EGL_NONE
+ };
+
+ EGLint majorVersion;
+ EGLint minorVersion;
+ EGLContext context;
+ EGLConfig config;
+ EGLSurface surface;
+ EGLint w, h;
+ EGLDisplay dpy;
+
+ EGLNativeWindowType window = android_createDisplaySurface();
+
+ dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ eglInitialize(dpy, &majorVersion, &minorVersion);
+
+ status_t err = EGLUtils::selectConfigForNativeWindow(
+ dpy, configAttribs, window, &config);
+ if (err) {
+ fprintf(stderr, "couldn't find an EGLConfig matching the screen format\n");
+ return 0;
+ }
+
+ surface = eglCreateWindowSurface(dpy, config, window, NULL);
+ context = eglCreateContext(dpy, config, NULL, NULL);
+ eglMakeCurrent(dpy, surface, surface, context);
+ eglQuerySurface(dpy, surface, EGL_WIDTH, &w);
+ eglQuerySurface(dpy, surface, EGL_HEIGHT, &h);
+
+ printf("w=%d, h=%d\n", w, h);
+
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+ glDisable(GL_DITHER);
+ glDisable(GL_BLEND);
+ glEnable(GL_TEXTURE_2D);
+ glColor4f(1,1,1,1);
+
+ const uint32_t t32[] = {
+ 0xFFFFFFFF, 0xFF0000FF, 0xFF00FF00, 0xFFFF0000,
+ 0xFFFFFF00, 0xFFFF00FF, 0xFF00FFFF, 0xFF000000
+ };
+
+ const GLfloat vertices[4][2] = {
+ { 0, 0 },
+ { w, h }
+ };
+
+ const GLfloat texCoords[4][2] = {
+ { 0, 0 },
+ { 1, 0 }
+ };
+
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 8, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, t32);
+
+ glViewport(0, 0, w, h);
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glOrthof(0, w, 0, h, 0, 1);
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ glVertexPointer(2, GL_FLOAT, 0, vertices);
+ glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
+
+ glClearColor(0,0,0,0);
+ glClear(GL_COLOR_BUFFER_BIT);
+ glDrawArrays(GL_LINES, 0, 2);
+ eglSwapBuffers(dpy, surface);
+
+ usleep(5*1000000);
+
+ eglTerminate(dpy);
+
+ return 0;
+}
diff --git a/services/java/com/android/server/DropBoxService.java b/services/java/com/android/server/DropBoxService.java
index 6c96a46..f4e5ebc 100644
--- a/services/java/com/android/server/DropBoxService.java
+++ b/services/java/com/android/server/DropBoxService.java
@@ -23,8 +23,7 @@
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.net.Uri;
-import android.os.DropBoxEntry;
-import android.os.IDropBox;
+import android.os.DropBox;
import android.os.ParcelFileDescriptor;
import android.os.StatFs;
import android.os.SystemClock;
@@ -32,11 +31,13 @@
import android.text.format.DateFormat;
import android.util.Log;
+import com.android.internal.os.IDropBoxService;
+
import java.io.File;
import java.io.FileDescriptor;
-import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
+import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
@@ -53,11 +54,12 @@
import java.util.zip.GZIPOutputStream;
/**
- * Implementation of {@link IDropBox} using the filesystem.
+ * Implementation of {@link IDropBoxService} using the filesystem.
+ * Clients use {@link DropBox} to access this service.
*
* {@hide}
*/
-public final class DropBoxService extends IDropBox.Stub {
+public final class DropBoxService extends IDropBoxService.Stub {
private static final String TAG = "DropBoxService";
private static final int DEFAULT_RESERVE_PERCENT = 10;
private static final int DEFAULT_QUOTA_PERCENT = 10;
@@ -129,50 +131,13 @@
mContext.unregisterReceiver(mReceiver);
}
- public void addText(String tag, String data) {
- addData(tag, data.getBytes(), DropBoxEntry.IS_TEXT);
- }
-
- public void addData(String tag, byte[] data, int flags) {
- File temp = null;
- OutputStream out = null;
- try {
- if ((flags & DropBoxEntry.IS_EMPTY) != 0) throw new IllegalArgumentException();
-
- init();
- if (!isTagEnabled(tag)) return;
-
- long max = trimToFit();
- if (data.length > max) {
- Log.w(TAG, "Dropping: " + tag + " (" + data.length + " > " + max + " bytes)");
- // Pass temp = null to createEntry() to leave a tombstone
- } else {
- temp = new File(mDropBoxDir, "drop" + Thread.currentThread().getId() + ".tmp");
- out = new FileOutputStream(temp);
- if (data.length > mBlockSize && ((flags & DropBoxEntry.IS_GZIPPED) == 0)) {
- flags = flags | DropBoxEntry.IS_GZIPPED;
- out = new GZIPOutputStream(out);
- }
- out.write(data);
- out.close();
- out = null;
- }
-
- createEntry(temp, tag, flags);
- temp = null;
- } catch (IOException e) {
- Log.e(TAG, "Can't write: " + tag, e);
- } finally {
- try { if (out != null) out.close(); } catch (IOException e) {}
- if (temp != null) temp.delete();
- }
- }
-
- public void addFile(String tag, ParcelFileDescriptor data, int flags) {
+ public void add(DropBox.Entry entry) {
File temp = null;
OutputStream output = null;
+ final String tag = entry.getTag();
try {
- if ((flags & DropBoxEntry.IS_EMPTY) != 0) throw new IllegalArgumentException();
+ int flags = entry.getFlags();
+ if ((flags & DropBox.IS_EMPTY) != 0) throw new IllegalArgumentException();
init();
if (!isTagEnabled(tag)) return;
@@ -180,7 +145,7 @@
long lastTrim = System.currentTimeMillis();
byte[] buffer = new byte[mBlockSize];
- FileInputStream input = new FileInputStream(data.getFileDescriptor());
+ InputStream input = entry.getInputStream();
// First, accumulate up to one block worth of data in memory before
// deciding whether to compress the data or not.
@@ -197,9 +162,9 @@
temp = new File(mDropBoxDir, "drop" + Thread.currentThread().getId() + ".tmp");
output = new FileOutputStream(temp);
- if (read == buffer.length && ((flags & DropBoxEntry.IS_GZIPPED) == 0)) {
+ if (read == buffer.length && ((flags & DropBox.IS_GZIPPED) == 0)) {
output = new GZIPOutputStream(output);
- flags = flags | DropBoxEntry.IS_GZIPPED;
+ flags = flags | DropBox.IS_GZIPPED;
}
do {
@@ -234,7 +199,7 @@
Log.e(TAG, "Can't write: " + tag, e);
} finally {
try { if (output != null) output.close(); } catch (IOException e) {}
- try { data.close(); } catch (IOException e) {}
+ entry.close();
if (temp != null) temp.delete();
}
}
@@ -244,7 +209,7 @@
mContentResolver, Settings.Gservices.DROPBOX_TAG_PREFIX + tag));
}
- public synchronized DropBoxEntry getNextEntry(String tag, long millis) {
+ public synchronized DropBox.Entry getNextEntry(String tag, long millis) {
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.READ_LOGS)
!= PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("READ_LOGS permission required");
@@ -262,9 +227,11 @@
for (EntryFile entry : list.contents.tailSet(new EntryFile(millis + 1))) {
if (entry.tag == null) continue;
+ if ((entry.flags & DropBox.IS_EMPTY) != 0) {
+ return new DropBox.Entry(entry.tag, entry.timestampMillis);
+ }
try {
- File file = (entry.flags & DropBoxEntry.IS_EMPTY) != 0 ? null : entry.file;
- return new DropBoxEntry(entry.tag, entry.timestampMillis, file, entry.flags);
+ return new DropBox.Entry(entry.tag, entry.timestampMillis, entry.file, entry.flags);
} catch (IOException e) {
Log.e(TAG, "Can't read: " + entry.file, e);
// Continue to next file
@@ -331,25 +298,25 @@
if (entry.file == null) {
pw.println(" (no file)");
continue;
- } else if ((entry.flags & DropBoxEntry.IS_EMPTY) != 0) {
+ } else if ((entry.flags & DropBox.IS_EMPTY) != 0) {
pw.println(" (contents lost)");
continue;
} else {
- pw.print((entry.flags & DropBoxEntry.IS_GZIPPED) != 0 ? " (comopressed " : " (");
- pw.print((entry.flags & DropBoxEntry.IS_TEXT) != 0 ? "text" : "data");
+ pw.print((entry.flags & DropBox.IS_GZIPPED) != 0 ? " (comopressed " : " (");
+ pw.print((entry.flags & DropBox.IS_TEXT) != 0 ? "text" : "data");
pw.format(", %d bytes)", entry.file.length());
pw.println();
}
- if (doFile || (doPrint && (entry.flags & DropBoxEntry.IS_TEXT) == 0)) {
+ if (doFile || (doPrint && (entry.flags & DropBox.IS_TEXT) == 0)) {
if (!doPrint) pw.print(" ");
pw.println(entry.file.getPath());
}
- if ((entry.flags & DropBoxEntry.IS_TEXT) != 0 && (doPrint || !doFile)) {
- DropBoxEntry dbe = null;
+ if ((entry.flags & DropBox.IS_TEXT) != 0 && (doPrint || !doFile)) {
+ DropBox.Entry dbe = null;
try {
- dbe = new DropBoxEntry(
+ dbe = new DropBox.Entry(
entry.tag, entry.timestampMillis, entry.file, entry.flags);
if (doPrint) {
@@ -435,20 +402,20 @@
* @param dir to store file in
* @param tag to use for new log file name
* @param timestampMillis of log entry
- * @param flags for the entry data (from {@link DropBoxEntry})
+ * @param flags for the entry data
* @param blockSize to use for space accounting
* @throws IOException if the file can't be moved
*/
public EntryFile(File temp, File dir, String tag,long timestampMillis,
int flags, int blockSize) throws IOException {
- if ((flags & DropBoxEntry.IS_EMPTY) != 0) throw new IllegalArgumentException();
+ if ((flags & DropBox.IS_EMPTY) != 0) throw new IllegalArgumentException();
this.tag = tag;
this.timestampMillis = timestampMillis;
this.flags = flags;
this.file = new File(dir, Uri.encode(tag) + "@" + timestampMillis +
- ((flags & DropBoxEntry.IS_TEXT) != 0 ? ".txt" : ".dat") +
- ((flags & DropBoxEntry.IS_GZIPPED) != 0 ? ".gz" : ""));
+ ((flags & DropBox.IS_TEXT) != 0 ? ".txt" : ".dat") +
+ ((flags & DropBox.IS_GZIPPED) != 0 ? ".gz" : ""));
if (!temp.renameTo(this.file)) {
throw new IOException("Can't rename " + temp + " to " + this.file);
@@ -466,7 +433,7 @@
public EntryFile(File dir, String tag, long timestampMillis) throws IOException {
this.tag = tag;
this.timestampMillis = timestampMillis;
- this.flags = DropBoxEntry.IS_EMPTY;
+ this.flags = DropBox.IS_EMPTY;
this.file = new File(dir, Uri.encode(tag) + "@" + timestampMillis + ".lost");
this.blocks = 0;
new FileOutputStream(this.file).close();
@@ -486,26 +453,26 @@
if (at < 0) {
this.tag = null;
this.timestampMillis = 0;
- this.flags = DropBoxEntry.IS_EMPTY;
+ this.flags = DropBox.IS_EMPTY;
return;
}
int flags = 0;
this.tag = Uri.decode(name.substring(0, at));
if (name.endsWith(".gz")) {
- flags |= DropBoxEntry.IS_GZIPPED;
+ flags |= DropBox.IS_GZIPPED;
name = name.substring(0, name.length() - 3);
}
if (name.endsWith(".lost")) {
- flags |= DropBoxEntry.IS_EMPTY;
+ flags |= DropBox.IS_EMPTY;
name = name.substring(at + 1, name.length() - 5);
} else if (name.endsWith(".txt")) {
- flags |= DropBoxEntry.IS_TEXT;
+ flags |= DropBox.IS_TEXT;
name = name.substring(at + 1, name.length() - 4);
} else if (name.endsWith(".dat")) {
name = name.substring(at + 1, name.length() - 4);
} else {
- this.flags = DropBoxEntry.IS_EMPTY;
+ this.flags = DropBox.IS_EMPTY;
this.timestampMillis = 0;
return;
}
@@ -523,7 +490,7 @@
public EntryFile(long millis) {
this.tag = null;
this.timestampMillis = millis;
- this.flags = DropBoxEntry.IS_EMPTY;
+ this.flags = DropBox.IS_EMPTY;
this.file = null;
this.blocks = 0;
}
@@ -618,7 +585,7 @@
mAllFiles.blocks -= late.blocks;
FileList tagFiles = mFilesByTag.get(late.tag);
if (tagFiles.contents.remove(late)) tagFiles.blocks -= late.blocks;
- if ((late.flags & DropBoxEntry.IS_EMPTY) == 0) {
+ if ((late.flags & DropBox.IS_EMPTY) == 0) {
enrollEntry(new EntryFile(
late.file, mDropBoxDir, late.tag, t++, late.flags, mBlockSize));
} else {
diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java
index 5c4aa79..4bf606d 100644
--- a/services/java/com/android/server/PowerManagerService.java
+++ b/services/java/com/android/server/PowerManagerService.java
@@ -131,6 +131,8 @@
static final boolean ANIMATE_KEYBOARD_LIGHTS = false;
static final int ANIM_STEPS = 60/4;
+ // Slower animation for autobrightness changes
+ static final int AUTOBRIGHTNESS_ANIM_STEPS = 60;
// These magic numbers are the initial state of the LEDs at boot. Ideally
// we should read them from the driver, but our current hardware returns 0
@@ -156,7 +158,6 @@
private int mProximityCount = 0;
private int mPowerState;
private boolean mOffBecauseOfUser;
- private boolean mAnimatingScreenOff;
private int mUserState;
private boolean mKeyboardVisible = false;
private boolean mUserActivityAllowed = true;
@@ -224,7 +225,7 @@
// could be either static or controllable at runtime
private static final boolean mSpew = false;
- private static final boolean mDebugLightSensor = false;
+ private static final boolean mDebugLightSensor = (false || mSpew);
/*
static PrintStream mLog;
@@ -1230,7 +1231,6 @@
Log.d(TAG,
"preventScreenOn: turning on after a prior preventScreenOn(true)!");
}
- mAnimatingScreenOff = false;
int err = setScreenStateLocked(true);
if (err != 0) {
Log.w(TAG, "preventScreenOn: error from setScreenStateLocked(): " + err);
@@ -1392,7 +1392,6 @@
reallyTurnScreenOn = false;
}
if (reallyTurnScreenOn) {
- mAnimatingScreenOff = false;
err = setScreenStateLocked(true);
long identity = Binder.clearCallingIdentity();
try {
@@ -1434,7 +1433,6 @@
if (!mScreenBrightness.animating) {
err = screenOffFinishedAnimatingLocked(becauseOfUser);
} else {
- mAnimatingScreenOff = true;
mOffBecauseOfUser = becauseOfUser;
err = 0;
mLastTouchDown = 0;
@@ -1452,7 +1450,6 @@
mTotalTouchDownTime, mTouchCycles);
mLastTouchDown = 0;
int err = setScreenStateLocked(false);
- mAnimatingScreenOff = false;
if (mScreenOnStartTime != 0) {
mScreenOnTime += SystemClock.elapsedRealtime() - mScreenOnStartTime;
mScreenOnStartTime = 0;
@@ -1825,9 +1822,6 @@
return;
}
- if (mAnimatingScreenOff) {
- return;
- }
if (false) {
if (((mPokey & POKE_LOCK_IGNORE_CHEEK_EVENTS) != 0)) {
Log.d(TAG, "userActivity !!!");//, new RuntimeException());
@@ -1845,6 +1839,11 @@
+ " mProximitySensorActive=" + mProximitySensorActive
+ " force=" + force);
}
+ // ignore user activity if we are in the process of turning off the screen
+ if (mScreenBrightness.animating && mScreenBrightness.targetValue == 0) {
+ Log.d(TAG, "ignoring user activity while turning off screen");
+ return;
+ }
if (mLastEventTime <= time || force) {
mLastEventTime = time;
if ((mUserActivityAllowed && !mProximitySensorActive) || force) {
@@ -1925,27 +1924,45 @@
Log.d(TAG, "keyboardValue " + keyboardValue);
}
+ boolean startAnimation = false;
if (mScreenBrightnessOverride < 0) {
- mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_BACKLIGHT,
- lcdValue);
- }
- mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_BUTTONS,
- buttonValue);
- mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_KEYBOARD,
- keyboardValue);
-
- // update our animation state
- if (ANIMATE_SCREEN_LIGHTS) {
- mScreenBrightness.curValue = lcdValue;
- mScreenBrightness.animating = false;
+ if (ANIMATE_SCREEN_LIGHTS) {
+ if (mScreenBrightness.setTargetLocked(lcdValue,
+ AUTOBRIGHTNESS_ANIM_STEPS, INITIAL_SCREEN_BRIGHTNESS,
+ (int)mScreenBrightness.curValue)) {
+ startAnimation = true;
+ }
+ } else {
+ mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_BACKLIGHT,
+ lcdValue);
+ }
}
if (ANIMATE_BUTTON_LIGHTS) {
- mButtonBrightness.curValue = buttonValue;
- mButtonBrightness.animating = false;
+ if (mButtonBrightness.setTargetLocked(buttonValue,
+ AUTOBRIGHTNESS_ANIM_STEPS, INITIAL_BUTTON_BRIGHTNESS,
+ (int)mButtonBrightness.curValue)) {
+ startAnimation = true;
+ }
+ } else {
+ mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_BUTTONS,
+ buttonValue);
}
if (ANIMATE_KEYBOARD_LIGHTS) {
- mKeyboardBrightness.curValue = keyboardValue;
- mKeyboardBrightness.animating = false;
+ if (mKeyboardBrightness.setTargetLocked(keyboardValue,
+ AUTOBRIGHTNESS_ANIM_STEPS, INITIAL_BUTTON_BRIGHTNESS,
+ (int)mKeyboardBrightness.curValue)) {
+ startAnimation = true;
+ }
+ } else {
+ mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_KEYBOARD,
+ keyboardValue);
+ }
+ if (startAnimation) {
+ if (mDebugLightSensor) {
+ Log.i(TAG, "lightSensorChangedLocked scheduling light animator");
+ }
+ mHandler.removeCallbacks(mLightAnimator);
+ mHandler.post(mLightAnimator);
}
}
}
@@ -2041,6 +2058,7 @@
if (mAutoBrightessEnabled != enabled) {
mAutoBrightessEnabled = enabled;
// reset computed brightness
+ mLightSensorValue = -1;
mLightSensorBrightness = -1;
if (mHasHardwareAutoBrightness) {
@@ -2263,14 +2281,17 @@
if (ANIMATE_SCREEN_LIGHTS) {
mScreenBrightness.curValue = brightness;
mScreenBrightness.animating = false;
+ mScreenBrightness.targetValue = -1;
}
if (ANIMATE_KEYBOARD_LIGHTS) {
mKeyboardBrightness.curValue = brightness;
mKeyboardBrightness.animating = false;
+ mKeyboardBrightness.targetValue = -1;
}
if (ANIMATE_BUTTON_LIGHTS) {
mButtonBrightness.curValue = brightness;
mButtonBrightness.animating = false;
+ mButtonBrightness.targetValue = -1;
}
}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 1a7416a..5f30710 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -296,7 +296,7 @@
try {
Log.i(TAG, "DropBox Service");
- ServiceManager.addService("dropbox",
+ ServiceManager.addService(Context.DROPBOX_SERVICE,
new DropBoxService(context, new File("/data/system/dropbox")));
} catch (Throwable e) {
Log.e(TAG, "Failure starting DropBox Service", e);
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index ad1926e..56270f4 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -2705,13 +2705,31 @@
// Have the window manager re-evaluate the orientation of
// the screen based on the new activity order.
- Configuration config = mWindowManager.updateOrientationFromAppTokens(
- mConfiguration,
- next.mayFreezeScreenLocked(next.app) ? next : null);
- if (config != null) {
- next.frozenBeforeDestroy = true;
+ boolean updated;
+ synchronized (this) {
+ Configuration config = mWindowManager.updateOrientationFromAppTokens(
+ mConfiguration,
+ next.mayFreezeScreenLocked(next.app) ? next : null);
+ if (config != null) {
+ /*
+ * Explicitly restore the locale to the one from the
+ * old configuration, since the one that comes back from
+ * the window manager has the default (boot) locale.
+ *
+ * It looks like previously the locale picker only worked
+ * by coincidence: usually it would do its setting of
+ * the locale after the activity transition, so it didn't
+ * matter that this lost it. With the synchronized
+ * block now keeping them from happening at the same time,
+ * this one always would happen second and undo what the
+ * locale picker had just done.
+ */
+ config.locale = mConfiguration.locale;
+ next.frozenBeforeDestroy = true;
+ }
+ updated = updateConfigurationLocked(config, next);
}
- if (!updateConfigurationLocked(config, next)) {
+ if (!updated) {
// The configuration update wasn't able to keep the existing
// instance of the activity, and instead started a new one.
// We should be all done, but let's just make sure our activity
diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java
index 6b33f52aa..586f63f 100644
--- a/telephony/java/android/telephony/PhoneNumberUtils.java
+++ b/telephony/java/android/telephony/PhoneNumberUtils.java
@@ -1060,8 +1060,8 @@
* Breaks the given number down and formats it according to the rules
* for the country the number is from.
*
- * @param source the phone number to format
- * @return a locally acceptable formatting of the input, or the raw input if
+ * @param source The phone number to format
+ * @return A locally acceptable formatting of the input, or the raw input if
* formatting rules aren't known for the number
*/
public static String formatNumber(String source) {
@@ -1071,10 +1071,27 @@
}
/**
+ * Formats the given number with the given formatting type. Currently
+ * {@link #FORMAT_NANP} and {@link #FORMAT_JAPAN} are supported as a formating type.
+ *
+ * @param source the phone number to format
+ * @param defaultFormattingType The default formatting rules to apply if the number does
+ * not begin with +<country_code>
+ * @return The phone number formatted with the given formatting type.
+ *
+ * @hide TODO:Shuold be unhidden.
+ */
+ public static String formatNumber(String source, int defaultFormattingType) {
+ SpannableStringBuilder text = new SpannableStringBuilder(source);
+ formatNumber(text, defaultFormattingType);
+ return text.toString();
+ }
+
+ /**
* Returns the phone number formatting type for the given locale.
*
* @param locale The locale of interest, usually {@link Locale#getDefault()}
- * @return the formatting type for the given locale, or FORMAT_UNKNOWN if the formatting
+ * @return The formatting type for the given locale, or FORMAT_UNKNOWN if the formatting
* rules are not known for the given locale
*/
public static int getFormatTypeForLocale(Locale locale) {
@@ -1084,7 +1101,8 @@
}
/**
- * Formats a phone number in-place. Currently only supports NANP formatting.
+ * Formats a phone number in-place. Currently {@link #FORMAT_JAPAN} and {@link #FORMAT_NANP}
+ * is supported as a second argument.
*
* @param text The number to be formatted, will be modified with the formatting
* @param defaultFormattingType The default formatting rules to apply if the number does
diff --git a/tests/AndroidTests/src/com/android/unit_tests/DropBoxTest.java b/tests/AndroidTests/src/com/android/unit_tests/DropBoxTest.java
index 439e0d8..286f702 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/DropBoxTest.java
+++ b/tests/AndroidTests/src/com/android/unit_tests/DropBoxTest.java
@@ -19,8 +19,7 @@
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
-import android.os.DropBoxEntry;
-import android.os.IDropBox;
+import android.os.DropBox;
import android.os.ParcelFileDescriptor;
import android.os.ServiceManager;
import android.os.StatFs;
@@ -36,7 +35,7 @@
import java.util.Random;
import java.util.zip.GZIPOutputStream;
-/** Test {@link IDropBox} functionality. */
+/** Test {@link DropBox} functionality. */
public class DropBoxTest extends AndroidTestCase {
public void tearDown() throws Exception {
Intent override = new Intent(Settings.Gservices.OVERRIDE_ACTION);
@@ -47,7 +46,7 @@
}
public void testAddText() throws Exception {
- IDropBox dropbox = IDropBox.Stub.asInterface(ServiceManager.getService("dropbox"));
+ DropBox dropbox = (DropBox) getContext().getSystemService(Context.DROPBOX_SERVICE);
long before = System.currentTimeMillis();
Thread.sleep(5);
dropbox.addText("DropBoxTest", "TEST0");
@@ -59,9 +58,9 @@
Thread.sleep(5);
long after = System.currentTimeMillis();
- DropBoxEntry e0 = dropbox.getNextEntry("DropBoxTest", before);
- DropBoxEntry e1 = dropbox.getNextEntry("DropBoxTest", e0.getTimeMillis());
- DropBoxEntry e2 = dropbox.getNextEntry("DropBoxTest", e1.getTimeMillis());
+ DropBox.Entry e0 = dropbox.getNextEntry("DropBoxTest", before);
+ DropBox.Entry e1 = dropbox.getNextEntry("DropBoxTest", e0.getTimeMillis());
+ DropBox.Entry e2 = dropbox.getNextEntry("DropBoxTest", e1.getTimeMillis());
assertTrue(null == dropbox.getNextEntry("DropBoxTest", e2.getTimeMillis()));
assertTrue(e0.getTimeMillis() > before);
@@ -80,12 +79,12 @@
}
public void testAddData() throws Exception {
- IDropBox dropbox = IDropBox.Stub.asInterface(ServiceManager.getService("dropbox"));
+ DropBox dropbox = (DropBox) getContext().getSystemService(Context.DROPBOX_SERVICE);
long before = System.currentTimeMillis();
dropbox.addData("DropBoxTest", "TEST".getBytes(), 0);
long after = System.currentTimeMillis();
- DropBoxEntry e = dropbox.getNextEntry("DropBoxTest", before);
+ DropBox.Entry e = dropbox.getNextEntry("DropBoxTest", before);
assertTrue(null == dropbox.getNextEntry("DropBoxTest", e.getTimeMillis()));
assertEquals("DropBoxTest", e.getTag());
@@ -123,7 +122,7 @@
os2.close();
gz3.close();
- IDropBox dropbox = IDropBox.Stub.asInterface(ServiceManager.getService("dropbox"));
+ DropBox dropbox = (DropBox) getContext().getSystemService(Context.DROPBOX_SERVICE);
int mode = ParcelFileDescriptor.MODE_READ_ONLY;
ParcelFileDescriptor pfd0 = ParcelFileDescriptor.open(f0, mode);
@@ -131,20 +130,20 @@
ParcelFileDescriptor pfd2 = ParcelFileDescriptor.open(f2, mode);
ParcelFileDescriptor pfd3 = ParcelFileDescriptor.open(f3, mode);
- dropbox.addFile("DropBoxTest", pfd0, DropBoxEntry.IS_TEXT);
- dropbox.addFile("DropBoxTest", pfd1, DropBoxEntry.IS_TEXT | DropBoxEntry.IS_GZIPPED);
+ dropbox.addFile("DropBoxTest", pfd0, DropBox.IS_TEXT);
+ dropbox.addFile("DropBoxTest", pfd1, DropBox.IS_TEXT | DropBox.IS_GZIPPED);
dropbox.addFile("DropBoxTest", pfd2, 0);
- dropbox.addFile("DropBoxTest", pfd3, DropBoxEntry.IS_GZIPPED);
+ dropbox.addFile("DropBoxTest", pfd3, DropBox.IS_GZIPPED);
pfd0.close();
pfd1.close();
pfd2.close();
pfd3.close();
- DropBoxEntry e0 = dropbox.getNextEntry("DropBoxTest", before);
- DropBoxEntry e1 = dropbox.getNextEntry("DropBoxTest", e0.getTimeMillis());
- DropBoxEntry e2 = dropbox.getNextEntry("DropBoxTest", e1.getTimeMillis());
- DropBoxEntry e3 = dropbox.getNextEntry("DropBoxTest", e2.getTimeMillis());
+ DropBox.Entry e0 = dropbox.getNextEntry("DropBoxTest", before);
+ DropBox.Entry e1 = dropbox.getNextEntry("DropBoxTest", e0.getTimeMillis());
+ DropBox.Entry e2 = dropbox.getNextEntry("DropBoxTest", e1.getTimeMillis());
+ DropBox.Entry e3 = dropbox.getNextEntry("DropBoxTest", e2.getTimeMillis());
assertTrue(null == dropbox.getNextEntry("DropBoxTest", e3.getTimeMillis()));
assertTrue(e0.getTimeMillis() > before);
@@ -152,8 +151,8 @@
assertTrue(e2.getTimeMillis() > e1.getTimeMillis());
assertTrue(e3.getTimeMillis() > e2.getTimeMillis());
- assertEquals(DropBoxEntry.IS_TEXT, e0.getFlags());
- assertEquals(DropBoxEntry.IS_TEXT, e1.getFlags());
+ assertEquals(DropBox.IS_TEXT, e0.getFlags());
+ assertEquals(DropBox.IS_TEXT, e1.getFlags());
assertEquals(0, e2.getFlags());
assertEquals(0, e3.getFlags());
@@ -199,13 +198,14 @@
// Tombstone in the far future
new FileOutputStream(new File(dir, "DropBoxTest@" + (before + 100002) + ".lost")).close();
- DropBoxService dropbox = new DropBoxService(getContext(), dir);
+ DropBoxService service = new DropBoxService(getContext(), dir);
+ DropBox dropbox = new DropBox(service);
// Until a write, the timestamps are taken at face value
- DropBoxEntry e0 = dropbox.getNextEntry(null, before);
- DropBoxEntry e1 = dropbox.getNextEntry(null, e0.getTimeMillis());
- DropBoxEntry e2 = dropbox.getNextEntry(null, e1.getTimeMillis());
- DropBoxEntry e3 = dropbox.getNextEntry(null, e2.getTimeMillis());
+ DropBox.Entry e0 = dropbox.getNextEntry(null, before);
+ DropBox.Entry e1 = dropbox.getNextEntry(null, e0.getTimeMillis());
+ DropBox.Entry e2 = dropbox.getNextEntry(null, e1.getTimeMillis());
+ DropBox.Entry e3 = dropbox.getNextEntry(null, e2.getTimeMillis());
assertTrue(null == dropbox.getNextEntry(null, e3.getTimeMillis()));
assertEquals("FUTURE0", e0.getText(80));
@@ -245,11 +245,11 @@
e1.close();
e2.close();
e3.close();
- dropbox.stop();
+ service.stop();
}
public void testIsTagEnabled() throws Exception {
- IDropBox dropbox = IDropBox.Stub.asInterface(ServiceManager.getService("dropbox"));
+ DropBox dropbox = (DropBox) getContext().getSystemService(Context.DROPBOX_SERVICE);
long before = System.currentTimeMillis();
dropbox.addText("DropBoxTest", "TEST-ENABLED");
assertTrue(dropbox.isTagEnabled("DropBoxTest"));
@@ -268,8 +268,8 @@
dropbox.addText("DropBoxTest", "TEST-ENABLED-AGAIN");
assertTrue(dropbox.isTagEnabled("DropBoxTest"));
- DropBoxEntry e0 = dropbox.getNextEntry("DropBoxTest", before);
- DropBoxEntry e1 = dropbox.getNextEntry("DropBoxTest", e0.getTimeMillis());
+ DropBox.Entry e0 = dropbox.getNextEntry("DropBoxTest", before);
+ DropBox.Entry e1 = dropbox.getNextEntry("DropBoxTest", e0.getTimeMillis());
assertTrue(null == dropbox.getNextEntry("DropBoxTest", e1.getTimeMillis()));
assertEquals("TEST-ENABLED", e0.getText(80));
@@ -281,23 +281,24 @@
public void testGetNextEntry() throws Exception {
File dir = getEmptyDir("testGetNextEntry");
- DropBoxService dropbox = new DropBoxService(getContext(), dir);
+ DropBoxService service = new DropBoxService(getContext(), dir);
+ DropBox dropbox = new DropBox(service);
long before = System.currentTimeMillis();
dropbox.addText("DropBoxTest.A", "A0");
dropbox.addText("DropBoxTest.B", "B0");
dropbox.addText("DropBoxTest.A", "A1");
- DropBoxEntry a0 = dropbox.getNextEntry("DropBoxTest.A", before);
- DropBoxEntry a1 = dropbox.getNextEntry("DropBoxTest.A", a0.getTimeMillis());
+ DropBox.Entry a0 = dropbox.getNextEntry("DropBoxTest.A", before);
+ DropBox.Entry a1 = dropbox.getNextEntry("DropBoxTest.A", a0.getTimeMillis());
assertTrue(null == dropbox.getNextEntry("DropBoxTest.A", a1.getTimeMillis()));
- DropBoxEntry b0 = dropbox.getNextEntry("DropBoxTest.B", before);
+ DropBox.Entry b0 = dropbox.getNextEntry("DropBoxTest.B", before);
assertTrue(null == dropbox.getNextEntry("DropBoxTest.B", b0.getTimeMillis()));
- DropBoxEntry x0 = dropbox.getNextEntry(null, before);
- DropBoxEntry x1 = dropbox.getNextEntry(null, x0.getTimeMillis());
- DropBoxEntry x2 = dropbox.getNextEntry(null, x1.getTimeMillis());
+ DropBox.Entry x0 = dropbox.getNextEntry(null, before);
+ DropBox.Entry x1 = dropbox.getNextEntry(null, x0.getTimeMillis());
+ DropBox.Entry x2 = dropbox.getNextEntry(null, x1.getTimeMillis());
assertTrue(null == dropbox.getNextEntry(null, x2.getTimeMillis()));
assertEquals("DropBoxTest.A", a0.getTag());
@@ -321,7 +322,7 @@
x0.close();
x1.close();
x2.close();
- dropbox.stop();
+ service.stop();
}
public void testSizeLimits() throws Exception {
@@ -344,7 +345,9 @@
final int overhead = 64;
long before = System.currentTimeMillis();
- DropBoxService dropbox = new DropBoxService(getContext(), dir);
+ DropBoxService service = new DropBoxService(getContext(), dir);
+ DropBox dropbox = new DropBox(service);
+
addRandomEntry(dropbox, "DropBoxTest0", blockSize - overhead);
addRandomEntry(dropbox, "DropBoxTest0", blockSize - overhead);
@@ -358,16 +361,16 @@
addRandomEntry(dropbox, "DropBoxTest2", blockSize - overhead);
addRandomEntry(dropbox, "DropBoxTest2", blockSize - overhead);
- DropBoxEntry e0 = dropbox.getNextEntry(null, before);
- DropBoxEntry e1 = dropbox.getNextEntry(null, e0.getTimeMillis());
- DropBoxEntry e2 = dropbox.getNextEntry(null, e1.getTimeMillis());
- DropBoxEntry e3 = dropbox.getNextEntry(null, e2.getTimeMillis());
- DropBoxEntry e4 = dropbox.getNextEntry(null, e3.getTimeMillis());
- DropBoxEntry e5 = dropbox.getNextEntry(null, e4.getTimeMillis());
- DropBoxEntry e6 = dropbox.getNextEntry(null, e5.getTimeMillis());
- DropBoxEntry e7 = dropbox.getNextEntry(null, e6.getTimeMillis());
- DropBoxEntry e8 = dropbox.getNextEntry(null, e7.getTimeMillis());
- DropBoxEntry e9 = dropbox.getNextEntry(null, e8.getTimeMillis());
+ DropBox.Entry e0 = dropbox.getNextEntry(null, before);
+ DropBox.Entry e1 = dropbox.getNextEntry(null, e0.getTimeMillis());
+ DropBox.Entry e2 = dropbox.getNextEntry(null, e1.getTimeMillis());
+ DropBox.Entry e3 = dropbox.getNextEntry(null, e2.getTimeMillis());
+ DropBox.Entry e4 = dropbox.getNextEntry(null, e3.getTimeMillis());
+ DropBox.Entry e5 = dropbox.getNextEntry(null, e4.getTimeMillis());
+ DropBox.Entry e6 = dropbox.getNextEntry(null, e5.getTimeMillis());
+ DropBox.Entry e7 = dropbox.getNextEntry(null, e6.getTimeMillis());
+ DropBox.Entry e8 = dropbox.getNextEntry(null, e7.getTimeMillis());
+ DropBox.Entry e9 = dropbox.getNextEntry(null, e8.getTimeMillis());
assertTrue(null == dropbox.getNextEntry(null, e9.getTimeMillis()));
assertEquals("DropBoxTest0", e0.getTag());
@@ -406,9 +409,9 @@
// Specifying a tag name skips tombstone records.
- DropBoxEntry t0 = dropbox.getNextEntry("DropBoxTest1", before);
- DropBoxEntry t1 = dropbox.getNextEntry("DropBoxTest1", t0.getTimeMillis());
- DropBoxEntry t2 = dropbox.getNextEntry("DropBoxTest1", t1.getTimeMillis());
+ DropBox.Entry t0 = dropbox.getNextEntry("DropBoxTest1", before);
+ DropBox.Entry t1 = dropbox.getNextEntry("DropBoxTest1", t0.getTimeMillis());
+ DropBox.Entry t2 = dropbox.getNextEntry("DropBoxTest1", t1.getTimeMillis());
assertTrue(null == dropbox.getNextEntry("DropBoxTest1", t2.getTimeMillis()));
assertEquals("DropBoxTest1", t0.getTag());
@@ -422,7 +425,7 @@
t0.close();
t1.close();
t2.close();
- dropbox.stop();
+ service.stop();
}
public void testAgeLimits() throws Exception {
@@ -438,13 +441,15 @@
// Write one normal entry and another so big that it is instantly tombstoned
long before = System.currentTimeMillis();
- DropBoxService dropbox = new DropBoxService(getContext(), dir);
+ DropBoxService service = new DropBoxService(getContext(), dir);
+ DropBox dropbox = new DropBox(service);
+
dropbox.addText("DropBoxTest", "TEST");
addRandomEntry(dropbox, "DropBoxTest", blockSize * 20);
// Verify that things are as expected
- DropBoxEntry e0 = dropbox.getNextEntry(null, before);
- DropBoxEntry e1 = dropbox.getNextEntry(null, e0.getTimeMillis());
+ DropBox.Entry e0 = dropbox.getNextEntry(null, before);
+ DropBox.Entry e1 = dropbox.getNextEntry(null, e0.getTimeMillis());
assertTrue(null == dropbox.getNextEntry(null, e1.getTimeMillis()));
assertEquals("TEST", e0.getText(80));
@@ -471,7 +476,8 @@
File dir = new File(getEmptyDir("testCreateDropBoxWith"), "InvalidDirectory");
new FileOutputStream(dir).close(); // Create an empty file
- DropBoxService dropbox = new DropBoxService(getContext(), dir);
+ DropBoxService service = new DropBoxService(getContext(), dir);
+ DropBox dropbox = new DropBox(service);
dropbox.addText("DropBoxTest", "should be ignored");
dropbox.addData("DropBoxTest", "should be ignored".getBytes(), 0);
@@ -479,15 +485,15 @@
dir.delete(); // Remove the file so a directory can be created
dropbox.addText("DropBoxTest", "TEST");
- DropBoxEntry e = dropbox.getNextEntry("DropBoxTest", 0);
+ DropBox.Entry e = dropbox.getNextEntry("DropBoxTest", 0);
assertTrue(null == dropbox.getNextEntry("DropBoxTest", e.getTimeMillis()));
assertEquals("DropBoxTest", e.getTag());
assertEquals("TEST", e.getText(80));
e.close();
- dropbox.stop();
+ service.stop();
}
- private void addRandomEntry(IDropBox dropbox, String tag, int size) throws Exception {
+ private void addRandomEntry(DropBox dropbox, String tag, int size) throws Exception {
byte[] bytes = new byte[size];
new Random(System.currentTimeMillis()).nextBytes(bytes);
@@ -501,7 +507,7 @@
fd.close();
}
- private int getEntrySize(DropBoxEntry e) throws Exception {
+ private int getEntrySize(DropBox.Entry e) throws Exception {
InputStream is = e.getInputStream();
if (is == null) return -1;
int length = 0;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/vcard/VCardExporterTests.java b/tests/AndroidTests/src/com/android/unit_tests/vcard/VCardExporterTests.java
index d0097c4..cfa9ab3 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/vcard/VCardExporterTests.java
+++ b/tests/AndroidTests/src/com/android/unit_tests/vcard/VCardExporterTests.java
@@ -643,9 +643,6 @@
testStructuredNameUseSuperPrimaryCommon(V30);
}
- /**
- * There's no property for nickname in vCard 2.1, so we don't have any requirement on it.
- */
public void testNickNameV30() {
ExportTestResolver resolver = new ExportTestResolver();
ContentValues contentValues = resolver.buildData(Nickname.CONTENT_ITEM_TYPE);
@@ -1269,4 +1266,23 @@
verifyOneComposition(resolver, handler, version);
}
+
+ /**
+ * There's no "NICKNAME" property in vCard 2.1, while there is in vCard 3.0.
+ * We use Android-specific "X-ANDROID-CUSTOM" property.
+ * This test verifies the functionality.
+ */
+ public void testNickNameV21() {
+ ExportTestResolver resolver = new ExportTestResolver();
+ ContentValues contentValues = resolver.buildData(Nickname.CONTENT_ITEM_TYPE);
+ contentValues.put(Nickname.NAME, "Nicky");
+
+ VCardVerificationHandler handler = new VCardVerificationHandler(this, V21);
+ handler.addNewVerifierWithEmptyName()
+ .addNodeWithOrder("X-ANDROID-CUSTOM", Nickname.CONTENT_ITEM_TYPE + ";Nicky;;;;;;;;;;;;;;");
+
+ // TODO: also test import part.
+
+ verifyOneComposition(resolver, handler, V21);
+ }
}
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/ReliabilityTest.java b/tests/DumpRenderTree/src/com/android/dumprendertree/ReliabilityTest.java
index 50b7c3f..9bc0962 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/ReliabilityTest.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/ReliabilityTest.java
@@ -74,6 +74,8 @@
Intent intent = new Intent(runner.getContext(), ReliabilityTestActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ ReliabilityTestActivity activity = (ReliabilityTestActivity)runner.startActivitySync(
+ intent);
//read from BufferedReader instead of populating a list in advance,
//this will avoid excessive memory usage in case of a large list
while((url = listReader.readLine()) != null) {
@@ -83,8 +85,6 @@
start = System.currentTimeMillis();
Log.v(LOGTAG, "Testing URL: " + url);
FsUtils.updateTestStatus(TEST_STATUS_FILE, url);
- ReliabilityTestActivity activity = (ReliabilityTestActivity)runner.startActivitySync(
- intent);
activity.reset();
//use message to send new URL to avoid interacting with
//WebView in non-UI thread
@@ -110,11 +110,11 @@
if(runner.mLogtime) {
writeLoadTime(url, activity.getPageLoadTime());
}
- activity.finish();
System.runFinalization();
System.gc();
System.gc();
}
+ activity.finish();
FsUtils.updateTestStatus(TEST_STATUS_FILE, TEST_DONE);
// activity.finish();
listReader.close();