Merge "Phase 2 of test cleanup: moving test files from AndroidTests closer to their sources."
diff --git a/Android.mk b/Android.mk
index 7717c76..369cdfd 100644
--- a/Android.mk
+++ b/Android.mk
@@ -317,7 +317,8 @@
xml/src/main/java/org/w3c
non_base_dirs := \
- ../../external/apache-http/src/org/apache/http
+ ../../external/apache-http/src/org/apache/http \
+ ../../external/oauth/core/src/main/java/net/oauth
# These are relative to frameworks/base
dirs_to_document := \
@@ -399,7 +400,7 @@
## SDK version identifiers used in the published docs
# major[.minor] version for current SDK. (full releases only)
-framework_docs_SDK_VERSION:=2.0.1
+framework_docs_SDK_VERSION:=2.1
# release version (ie "Release x") (full releases only)
framework_docs_SDK_REL_ID:=1
# name of current SDK directory (full releases only)
@@ -548,6 +549,7 @@
ext_dirs := \
../../external/apache-http/src \
+ ../../external/oauth/core/src/main/java \
../../external/tagsoup/src
ext_src_files := $(call all-java-files-under,$(ext_dirs))
diff --git a/api/current.xml b/api/current.xml
index b03f826..3b6e031 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -52371,6 +52371,25 @@
<exception name="SQLException" type="android.database.SQLException">
</exception>
</method>
+<method name="insertWithOnConflict"
+ return="long"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="table" type="java.lang.String">
+</parameter>
+<parameter name="nullColumnHack" type="java.lang.String">
+</parameter>
+<parameter name="initialValues" type="android.content.ContentValues">
+</parameter>
+<parameter name="conflictAlgorithm" type="int">
+</parameter>
+</method>
<method name="isDbLockedByCurrentThread"
return="boolean"
abstract="false"
@@ -52806,6 +52825,27 @@
<parameter name="whereArgs" type="java.lang.String[]">
</parameter>
</method>
+<method name="updateWithOnConflict"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="table" type="java.lang.String">
+</parameter>
+<parameter name="values" type="android.content.ContentValues">
+</parameter>
+<parameter name="whereClause" type="java.lang.String">
+</parameter>
+<parameter name="whereArgs" type="java.lang.String[]">
+</parameter>
+<parameter name="conflictAlgorithm" type="int">
+</parameter>
+</method>
<method name="yieldIfContended"
return="boolean"
abstract="false"
@@ -52897,6 +52937,81 @@
>
</field>
</class>
+<class name="SQLiteDatabase.ConflictAlgorithm"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<field name="ABORT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="FAIL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="IGNORE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="NONE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="REPLACE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="5"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ROLLBACK"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
<interface name="SQLiteDatabase.CursorFactory"
abstract="true"
static="true"
@@ -72158,7 +72273,7 @@
type="float"
transient="false"
volatile="false"
- value="0.001f"
+ value="0.0010f"
static="true"
final="true"
deprecated="not deprecated"
@@ -83660,6 +83775,122 @@
</parameter>
</method>
</class>
+<class name="ThumbnailUtils"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="ThumbnailUtils"
+ type="android.media.ThumbnailUtils"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="createImageThumbnail"
+ return="android.graphics.Bitmap"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="cr" type="android.content.ContentResolver">
+</parameter>
+<parameter name="filePath" type="java.lang.String">
+</parameter>
+<parameter name="uri" type="android.net.Uri">
+</parameter>
+<parameter name="origId" type="long">
+</parameter>
+<parameter name="kind" type="int">
+</parameter>
+<parameter name="saveMini" type="boolean">
+</parameter>
+</method>
+<method name="createVideoThumbnail"
+ return="android.graphics.Bitmap"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="filePath" type="java.lang.String">
+</parameter>
+</method>
+<method name="extractMiniThumb"
+ return="android.graphics.Bitmap"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="source" type="android.graphics.Bitmap">
+</parameter>
+<parameter name="width" type="int">
+</parameter>
+<parameter name="height" type="int">
+</parameter>
+<parameter name="recycle" type="boolean">
+</parameter>
+</method>
+<field name="MINI_THUMB_TARGET_SIZE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="96"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="NO_RECYCLE_INPUT"
+ type="boolean"
+ transient="false"
+ volatile="false"
+ value="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="RECYCLE_INPUT"
+ type="boolean"
+ transient="false"
+ volatile="false"
+ value="true"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="THUMBNAIL_TARGET_SIZE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="320"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
<class name="ToneGenerator"
extends="java.lang.Object"
abstract="false"
@@ -178437,6 +178668,17 @@
visibility="public"
>
</field>
+<field name="FLAG_ALLOW_LOCK_WHILE_SCREEN_ON"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="FLAG_ALT_FOCUSABLE_IM"
type="int"
transient="false"
@@ -209680,7 +209922,7 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="t" type="T">
+<parameter name="arg0" type="T">
</parameter>
</method>
</interface>
diff --git a/core/java/android/app/BackupAgent.java b/core/java/android/app/BackupAgent.java
index 2a58677..35b6fed 100644
--- a/core/java/android/app/BackupAgent.java
+++ b/core/java/android/app/BackupAgent.java
@@ -19,6 +19,7 @@
import android.app.IBackupAgent;
import android.backup.BackupDataInput;
import android.backup.BackupDataOutput;
+import android.backup.IBackupManager;
import android.content.Context;
import android.content.ContextWrapper;
import android.os.Binder;
@@ -94,12 +95,9 @@
// ----- Core implementation -----
-
- /**
- * Returns the private interface called by the backup system. Applications will
- * not typically override this.
- */
- public IBinder onBind() {
+
+ /** @hide */
+ public final IBinder onBind() {
return mBinder;
}
@@ -116,9 +114,10 @@
public void doBackup(ParcelFileDescriptor oldState,
ParcelFileDescriptor data,
- ParcelFileDescriptor newState) throws RemoteException {
+ ParcelFileDescriptor newState,
+ int token, IBackupManager callbackBinder) throws RemoteException {
// Ensure that we're running with the app's normal permission level
- long token = Binder.clearCallingIdentity();
+ long ident = Binder.clearCallingIdentity();
if (DEBUG) Log.v(TAG, "doBackup() invoked");
BackupDataOutput output = new BackupDataOutput(data.getFileDescriptor());
@@ -131,14 +130,20 @@
Log.d(TAG, "onBackup (" + BackupAgent.this.getClass().getName() + ") threw", ex);
throw ex;
} finally {
- Binder.restoreCallingIdentity(token);
+ Binder.restoreCallingIdentity(ident);
+ try {
+ callbackBinder.opComplete(token);
+ } catch (RemoteException e) {
+ // we'll time out anyway, so we're safe
+ }
}
}
public void doRestore(ParcelFileDescriptor data, int appVersionCode,
- ParcelFileDescriptor newState) throws RemoteException {
+ ParcelFileDescriptor newState,
+ int token, IBackupManager callbackBinder) throws RemoteException {
// Ensure that we're running with the app's normal permission level
- long token = Binder.clearCallingIdentity();
+ long ident = Binder.clearCallingIdentity();
if (DEBUG) Log.v(TAG, "doRestore() invoked");
BackupDataInput input = new BackupDataInput(data.getFileDescriptor());
@@ -151,7 +156,12 @@
Log.d(TAG, "onRestore (" + BackupAgent.this.getClass().getName() + ") threw", ex);
throw ex;
} finally {
- Binder.restoreCallingIdentity(token);
+ Binder.restoreCallingIdentity(ident);
+ try {
+ callbackBinder.opComplete(token);
+ } catch (RemoteException e) {
+ // we'll time out anyway, so we're safe
+ }
}
}
}
diff --git a/core/java/android/app/IBackupAgent.aidl b/core/java/android/app/IBackupAgent.aidl
index 9b0550f..0de6ad9 100644
--- a/core/java/android/app/IBackupAgent.aidl
+++ b/core/java/android/app/IBackupAgent.aidl
@@ -16,6 +16,7 @@
package android.app;
+import android.backup.IBackupManager;
import android.os.ParcelFileDescriptor;
/**
@@ -25,7 +26,7 @@
*
* {@hide}
*/
-interface IBackupAgent {
+oneway interface IBackupAgent {
/**
* Request that the app perform an incremental backup.
*
@@ -39,10 +40,18 @@
*
* @param newState Read-write file, empty when onBackup() is called,
* where the new state blob is to be recorded.
+ *
+ * @param token Opaque token identifying this transaction. This must
+ * be echoed back to the backup service binder once the new
+ * data has been written to the data and newState files.
+ *
+ * @param callbackBinder Binder on which to indicate operation completion,
+ * passed here as a convenience to the agent.
*/
void doBackup(in ParcelFileDescriptor oldState,
in ParcelFileDescriptor data,
- in ParcelFileDescriptor newState);
+ in ParcelFileDescriptor newState,
+ int token, IBackupManager callbackBinder);
/**
* Restore an entire data snapshot to the application.
@@ -58,7 +67,15 @@
* @param newState Read-write file, empty when onRestore() is called,
* that is to be written with the state description that holds after
* the restore has been completed.
+ *
+ * @param token Opaque token identifying this transaction. This must
+ * be echoed back to the backup service binder once the agent is
+ * finished restoring the application based on the restore data
+ * contents.
+ *
+ * @param callbackBinder Binder on which to indicate operation completion,
+ * passed here as a convenience to the agent.
*/
void doRestore(in ParcelFileDescriptor data, int appVersionCode,
- in ParcelFileDescriptor newState);
+ in ParcelFileDescriptor newState, int token, IBackupManager callbackBinder);
}
diff --git a/core/java/android/backup/IBackupManager.aidl b/core/java/android/backup/IBackupManager.aidl
index 9d181be..cb775f7 100644
--- a/core/java/android/backup/IBackupManager.aidl
+++ b/core/java/android/backup/IBackupManager.aidl
@@ -130,4 +130,14 @@
* @return An interface to the restore session, or null on error.
*/
IRestoreSession beginRestoreSession(String transportID);
+
+ /**
+ * Notify the backup manager that a BackupAgent has completed the operation
+ * corresponding to the given token.
+ *
+ * @param token The transaction token passed to a BackupAgent's doBackup() or
+ * doRestore() method.
+ * {@hide}
+ */
+ void opComplete(int token);
}
diff --git a/core/java/android/backup/RestoreSession.java b/core/java/android/backup/RestoreSession.java
index 119fc52..a884793 100644
--- a/core/java/android/backup/RestoreSession.java
+++ b/core/java/android/backup/RestoreSession.java
@@ -109,9 +109,7 @@
/*
* We wrap incoming binder calls with a private class implementation that
- * redirects them into main-thread actions. This accomplishes two things:
- * first, it ensures that the app's code is run on their own main thread,
- * never with system Binder identity; and second, it serializes the restore
+ * redirects them into main-thread actions. This serializes the restore
* progress callbacks nicely within the usual main-thread lifecycle pattern.
*/
private class RestoreObserverWrapper extends IRestoreObserver.Stub {
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index bc59c94..d10c8f8 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -27,6 +27,8 @@
import android.content.res.XmlResourceParser;
import android.graphics.drawable.Drawable;
import android.net.Uri;
+import android.os.Environment;
+import android.os.StatFs;
import android.util.AndroidException;
import android.util.DisplayMetrics;
@@ -602,6 +604,89 @@
*/
@SdkConstant(SdkConstantType.FEATURE)
public static final String FEATURE_LIVE_WALLPAPER = "android.software.live_wallpaper";
+
+ // No-installation limit for internal flash: 10% or less space available
+ private static final double LOW_NAND_FLASH_TRESHOLD = 0.1;
+
+ // SD-to-internal app size threshold: currently set to 1 MB
+ private static final long INSTALL_ON_SD_THRESHOLD = (1024 * 1024);
+
+ private static final int INSTALL_ON_INTERNAL_FLASH = 0;
+
+ /**
+ * Determines best place to install an application: either SD or internal FLASH.
+ * Tweak the algorithm for best results.
+ * @param tmpPackageFile APK file containing the application to install.
+ * @return <code>PKG_INSTALL_INTERNAL</code> if it is best to install package on internal
+ * storage, <code>PKG_INSTALL_ON_SD</code> if it is best to install package on SD card,
+ * and <code>PKG_CANNOT_FIT</code> if insufficient space to safely install the app.
+ * This response does not take into account the package's own flags.
+ * @hide
+ */
+ public static int recommendAppInstallLocation(ApplicationInfo appInfo, Uri packageURI) {
+ // Initial implementation:
+ // Package size = code size + cache size + data size
+ // If code size > 1 MB, install on SD card.
+ // Else install on internal NAND flash, unless space on NAND is less than 5%
+ // 0 = install on internal FLASH
+ // 1 = install on SD card
+ // (-1) = insufficient space - package cannot be installed.
+
+ if ((packageURI == null) || (appInfo == null)) {
+ return (-1);
+ }
+
+ StatFs internalFlashStats = new StatFs(Environment.getDataDirectory().getPath());
+ StatFs sdcardStats = new StatFs(Environment.getExternalStorageDirectory().getPath());
+
+ long totalInternalFlashSize = (long)internalFlashStats.getBlockCount() *
+ (long)internalFlashStats.getBlockSize();
+ long availInternalFlashSize = (long)internalFlashStats.getAvailableBlocks() *
+ (long)internalFlashStats.getBlockSize();
+ long availSDSize = (long)sdcardStats.getAvailableBlocks() *
+ (long)sdcardStats.getBlockSize();
+
+ double pctNandFree = (double)availInternalFlashSize / (double)totalInternalFlashSize;
+
+ final String archiveFilePath = packageURI.getPath();
+ File apkFile = new File(archiveFilePath);
+ long pkgLen = apkFile.length();
+
+ // Consider application flags preferences as well...
+ boolean installOnlyOnSD = ((appInfo.flags & PackageManager.INSTALL_ON_SDCARD) != 0);
+
+ // These are not very precise measures, but I guess it is hard to estimate sizes
+ // before installing the package.
+ // As a shortcut, I am assuming that the package fits on NAND flash if the available
+ // space is three times that of the APK size. For SD, we only worry about the APK size.
+ // Since packages are downloaded into SD, this might not even be necessary.
+ boolean fitsOnSD = (pkgLen < availSDSize) && ((2 * pkgLen) < availInternalFlashSize);
+ boolean fitsOnInternalFlash = ((pkgLen * 3) < availInternalFlashSize);
+
+ // Does not fit, recommend no installation.
+ if (!fitsOnSD && !fitsOnInternalFlash) {
+ return (-1);
+ }
+
+ if (pkgLen < (INSTALL_ON_SD_THRESHOLD) && fitsOnInternalFlash && !(installOnlyOnSD)) {
+ // recommend internal NAND likely
+ if (pctNandFree < LOW_NAND_FLASH_TRESHOLD) {
+ // Low space on NAND (<10%) - install on SD
+ return INSTALL_ON_SDCARD;
+ }
+ return INSTALL_ON_INTERNAL_FLASH;
+ } else {
+ if (fitsOnSD) {
+ // Recommend SD card
+ return INSTALL_ON_SDCARD;
+ } else if (fitsOnInternalFlash && (pctNandFree >= LOW_NAND_FLASH_TRESHOLD) &&
+ !(installOnlyOnSD)) {
+ return INSTALL_ON_INTERNAL_FLASH;
+ } else {
+ return (-1);
+ }
+ }
+ }
/**
* Retrieve overall information about an application package that is
diff --git a/core/java/android/database/sqlite/SQLiteDatabase.java b/core/java/android/database/sqlite/SQLiteDatabase.java
index 82490bb..e3c25ec 100644
--- a/core/java/android/database/sqlite/SQLiteDatabase.java
+++ b/core/java/android/database/sqlite/SQLiteDatabase.java
@@ -65,9 +65,8 @@
/**
* Algorithms used in ON CONFLICT clause
* http://www.sqlite.org/lang_conflict.html
- * @hide
*/
- public enum ConflictAlgorithm {
+ public static final class ConflictAlgorithm {
/**
* When a constraint violation occurs, an immediate ROLLBACK occurs,
* thus ending the current transaction, and the command aborts with a
@@ -75,14 +74,14 @@
* (other than the implied transaction that is created on every command)
* then this algorithm works the same as ABORT.
*/
- ROLLBACK("ROLLBACK"),
+ public static final int ROLLBACK = 1;
/**
* When a constraint violation occurs,no ROLLBACK is executed
* so changes from prior commands within the same transaction
* are preserved. This is the default behavior.
*/
- ABORT("ABORT"),
+ public static final int ABORT = 2;
/**
* When a constraint violation occurs, the command aborts with a return
@@ -90,7 +89,7 @@
* the command made prior to encountering the constraint violation
* are preserved and are not backed out.
*/
- FAIL("FAIL"),
+ public static final int FAIL = 3;
/**
* When a constraint violation occurs, the one row that contains
@@ -99,7 +98,7 @@
* after the row that contained the constraint violation continue to be
* inserted or updated normally. No error is returned.
*/
- IGNORE("IGNORE"),
+ public static final int IGNORE = 4;
/**
* When a UNIQUE constraint violation occurs, the pre-existing rows that
@@ -114,15 +113,16 @@
* it does not invoke delete triggers on those rows.
* This behavior might change in a future release.
*/
- REPLACE("REPLACE");
+ public static final int REPLACE = 5;
- private final String mValue;
- ConflictAlgorithm(String value) {
- mValue = value;
- }
- public String value() {
- return mValue;
- }
+ /**
+ * use the following when no conflict action is specified.
+ */
+ public static final int NONE = 0;
+ private static final String[] VALUES = new String[]
+ {"", " OR ROLLBACK ", " OR ABORT ", " OR FAIL ", " OR IGNORE ", " OR REPLACE "};
+
+ private ConflictAlgorithm() {} // disable instantiation of this class
}
/**
@@ -1334,7 +1334,7 @@
*/
public long insert(String table, String nullColumnHack, ContentValues values) {
try {
- return insertWithOnConflict(table, nullColumnHack, values, null);
+ return insertWithOnConflict(table, nullColumnHack, values, ConflictAlgorithm.NONE);
} catch (SQLException e) {
Log.e(TAG, "Error inserting " + values, e);
return -1;
@@ -1356,7 +1356,7 @@
*/
public long insertOrThrow(String table, String nullColumnHack, ContentValues values)
throws SQLException {
- return insertWithOnConflict(table, nullColumnHack, values, null);
+ return insertWithOnConflict(table, nullColumnHack, values, ConflictAlgorithm.NONE);
}
/**
@@ -1408,12 +1408,14 @@
* @param initialValues this map contains the initial column values for the
* row. The keys should be the column names and the values the
* column values
- * @param algorithm {@link ConflictAlgorithm} for insert conflict resolver
- * @return the row ID of the newly inserted row, or -1 if an error occurred
- * @hide
+ * @param conflictAlgorithm {@link ConflictAlgorithm} for insert conflict resolver
+ * @return the row ID of the newly inserted row
+ * OR the primary key of the existing row if the input param 'conflictAlgorithm' =
+ * {@link ConflictAlgorithm#IGNORE}
+ * OR -1 if any error
*/
public long insertWithOnConflict(String table, String nullColumnHack,
- ContentValues initialValues, ConflictAlgorithm algorithm) {
+ ContentValues initialValues, int conflictAlgorithm) {
if (!isOpen()) {
throw new IllegalStateException("database not open");
}
@@ -1421,10 +1423,7 @@
// Measurements show most sql lengths <= 152
StringBuilder sql = new StringBuilder(152);
sql.append("INSERT");
- if (algorithm != null) {
- sql.append(" OR ");
- sql.append(algorithm.value());
- }
+ sql.append(ConflictAlgorithm.VALUES[conflictAlgorithm]);
sql.append(" INTO ");
sql.append(table);
// Measurements show most values lengths < 40
@@ -1548,7 +1547,7 @@
* @return the number of rows affected
*/
public int update(String table, ContentValues values, String whereClause, String[] whereArgs) {
- return updateWithOnConflict(table, values, whereClause, whereArgs, null);
+ return updateWithOnConflict(table, values, whereClause, whereArgs, ConflictAlgorithm.NONE);
}
/**
@@ -1559,12 +1558,11 @@
* valid value that will be translated to NULL.
* @param whereClause the optional WHERE clause to apply when updating.
* Passing null will update all rows.
- * @param algorithm {@link ConflictAlgorithm} for update conflict resolver
+ * @param conflictAlgorithm {@link ConflictAlgorithm} for update conflict resolver
* @return the number of rows affected
- * @hide
*/
public int updateWithOnConflict(String table, ContentValues values,
- String whereClause, String[] whereArgs, ConflictAlgorithm algorithm) {
+ String whereClause, String[] whereArgs, int conflictAlgorithm) {
if (!isOpen()) {
throw new IllegalStateException("database not open");
}
@@ -1575,12 +1573,7 @@
StringBuilder sql = new StringBuilder(120);
sql.append("UPDATE ");
- if (algorithm != null) {
- sql.append("OR ");
- sql.append(algorithm.value());
- sql.append(" ");
- }
-
+ sql.append(ConflictAlgorithm.VALUES[conflictAlgorithm]);
sql.append(table);
sql.append(" SET ");
diff --git a/core/java/android/ddm/DdmHandleHeap.java b/core/java/android/ddm/DdmHandleHeap.java
index 95fa0a2..fa0fbbf 100644
--- a/core/java/android/ddm/DdmHandleHeap.java
+++ b/core/java/android/ddm/DdmHandleHeap.java
@@ -34,6 +34,7 @@
public static final int CHUNK_HPIF = type("HPIF");
public static final int CHUNK_HPSG = type("HPSG");
public static final int CHUNK_HPDU = type("HPDU");
+ public static final int CHUNK_HPDS = type("HPDS");
public static final int CHUNK_NHSG = type("NHSG");
public static final int CHUNK_HPGC = type("HPGC");
public static final int CHUNK_REAE = type("REAE");
@@ -53,6 +54,7 @@
DdmServer.registerHandler(CHUNK_HPIF, mInstance);
DdmServer.registerHandler(CHUNK_HPSG, mInstance);
DdmServer.registerHandler(CHUNK_HPDU, mInstance);
+ DdmServer.registerHandler(CHUNK_HPDS, mInstance);
DdmServer.registerHandler(CHUNK_NHSG, mInstance);
DdmServer.registerHandler(CHUNK_HPGC, mInstance);
DdmServer.registerHandler(CHUNK_REAE, mInstance);
@@ -86,6 +88,8 @@
return handleHPSGNHSG(request, false);
} else if (type == CHUNK_HPDU) {
return handleHPDU(request);
+ } else if (type == CHUNK_HPDS) {
+ return handleHPDS(request);
} else if (type == CHUNK_NHSG) {
return handleHPSGNHSG(request, true);
} else if (type == CHUNK_HPGC) {
@@ -167,7 +171,7 @@
result = -1;
} catch (IOException ioe) {
result = -1;
- } catch (RuntimeException ioe) {
+ } catch (RuntimeException re) {
result = -1;
}
@@ -177,6 +181,38 @@
}
/*
+ * Handle a "HeaP Dump Streaming" request.
+ *
+ * This tells the VM to create a heap dump and send it directly to
+ * DDMS. The dumps are large enough that we don't want to copy the
+ * data into a byte[] and send it from here.
+ */
+ private Chunk handleHPDS(Chunk request) {
+ ByteBuffer in = wrapChunk(request);
+ byte result;
+
+ /* get the filename for the output file */
+ if (Config.LOGD)
+ Log.d("ddm-heap", "Heap dump: [DDMS]");
+
+ String failMsg = null;
+ try {
+ Debug.dumpHprofDataDdms();
+ } catch (UnsupportedOperationException uoe) {
+ failMsg = "hprof dumps not supported in this VM";
+ } catch (RuntimeException re) {
+ failMsg = "Exception: " + re.getMessage();
+ }
+
+ if (failMsg != null) {
+ Log.w("ddm-heap", failMsg);
+ return createFailChunk(1, failMsg);
+ } else {
+ return null;
+ }
+ }
+
+ /*
* Handle a "HeaP Garbage Collection" request.
*/
private Chunk handleHPGC(Chunk request) {
diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java
index 8e9b11b..9ee251e 100644
--- a/core/java/android/os/Debug.java
+++ b/core/java/android/os/Debug.java
@@ -726,6 +726,18 @@
}
/**
+ * Collect "hprof" and send it to DDMS. This will cause a GC.
+ *
+ * @throws UnsupportedOperationException if the VM was built without
+ * HPROF support.
+ *
+ * @hide
+ */
+ public static void dumpHprofDataDdms() {
+ VMDebug.dumpHprofDataDdms();
+ }
+
+ /**
* Returns the number of sent transactions from this process.
* @return The number of sent transactions or -1 if it could not read t.
*/
diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java
index 1b938ee..211bc0a 100644
--- a/core/java/android/provider/MediaStore.java
+++ b/core/java/android/provider/MediaStore.java
@@ -28,7 +28,7 @@
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.media.MiniThumbFile;
-import android.media.ThumbnailUtil;
+import android.media.ThumbnailUtils;
import android.net.Uri;
import android.os.Environment;
import android.os.ParcelFileDescriptor;
@@ -381,15 +381,15 @@
filePath = c.getString(1);
}
if (isVideo) {
- bitmap = ThumbnailUtil.createVideoThumbnail(filePath);
+ bitmap = ThumbnailUtils.createVideoThumbnail(filePath);
if (kind == MICRO_KIND && bitmap != null) {
- bitmap = ThumbnailUtil.extractMiniThumb(bitmap,
- ThumbnailUtil.MINI_THUMB_TARGET_SIZE,
- ThumbnailUtil.MINI_THUMB_TARGET_SIZE,
- ThumbnailUtil.RECYCLE_INPUT);
+ bitmap = ThumbnailUtils.extractMiniThumb(bitmap,
+ ThumbnailUtils.MINI_THUMB_TARGET_SIZE,
+ ThumbnailUtils.MINI_THUMB_TARGET_SIZE,
+ ThumbnailUtils.RECYCLE_INPUT);
}
} else {
- bitmap = ThumbnailUtil.createImageThumbnail(cr, filePath, uri, origId,
+ bitmap = ThumbnailUtils.createImageThumbnail(cr, filePath, uri, origId,
kind, false);
}
}
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 8e15f89..0af31f0 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -369,6 +369,12 @@
*/
public int flags;
+ /** Window flag: as long as this window is visible to the user, allow
+ * the lock screen to activate while the screen is on.
+ * This can be used independently, or in combination with
+ * {@link #FLAG_KEEP_SCREEN_ON} and/or {@link #FLAG_SHOW_WHEN_LOCKED} */
+ public static final int FLAG_ALLOW_LOCK_WHILE_SCREEN_ON = 0x00000001;
+
/** Window flag: everything behind this window will be dimmed.
* Use {@link #dimAmount} to control the amount of dim. */
public static final int FLAG_DIM_BEHIND = 0x00000002;
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index 21577bf..7bc5cce 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -827,6 +827,12 @@
public void systemReady();
/**
+ * Called when userActivity is signalled in the power manager.
+ * This is safe to call from any thread, with any window manager locks held or not.
+ */
+ public void userActivity();
+
+ /**
* Called when we have finished booting and can now display the home
* screen to the user. This wilWl happen after systemReady(), and at
* this point the display is active.
diff --git a/core/java/com/android/internal/backup/IBackupTransport.aidl b/core/java/com/android/internal/backup/IBackupTransport.aidl
index a830ebd..9da1066 100644
--- a/core/java/com/android/internal/backup/IBackupTransport.aidl
+++ b/core/java/com/android/internal/backup/IBackupTransport.aidl
@@ -102,7 +102,7 @@
int finishBackup();
/**
- * Get the set of backups currently available over this transport.
+ * Get the set of all backups currently available over this transport.
*
* @return Descriptions of the set of restore images available for this device,
* or null if an error occurred (the attempt should be rescheduled).
@@ -110,11 +110,22 @@
RestoreSet[] getAvailableRestoreSets();
/**
+ * Get the identifying token of the backup set currently being stored from
+ * this device. This is used in the case of applications wishing to restore
+ * their last-known-good data.
+ *
+ * @return A token that can be passed to {@link #startRestore}, or 0 if there
+ * is no backup set available corresponding to the current device state.
+ */
+ long getCurrentRestoreSet();
+
+ /**
* Start restoring application data from backup. After calling this function,
* alternate calls to {@link #nextRestorePackage} and {@link #nextRestoreData}
* to walk through the actual application data.
*
- * @param token A backup token as returned by {@link #getAvailableRestoreSets}.
+ * @param token A backup token as returned by {@link #getAvailableRestoreSets}
+ * or {@link #getCurrentRestoreSet}.
* @param packages List of applications to restore (if data is available).
* Application data will be restored in the order given.
* @return One of {@link BackupConstants#TRANSPORT_OK} (OK so far, call
diff --git a/core/java/com/android/internal/backup/LocalTransport.java b/core/java/com/android/internal/backup/LocalTransport.java
index 12bc5a8..23ec647 100644
--- a/core/java/com/android/internal/backup/LocalTransport.java
+++ b/core/java/com/android/internal/backup/LocalTransport.java
@@ -33,6 +33,9 @@
private static final String TRANSPORT_DIR_NAME
= "com.android.internal.backup.LocalTransport";
+ // The single hardcoded restore set always has the same (nonzero!) token
+ private static final long RESTORE_TOKEN = 1;
+
private Context mContext;
private PackageManager mPackageManager;
private File mDataDir = new File(Environment.getDownloadCacheDirectory(), "backup");
@@ -149,11 +152,16 @@
// Restore handling
public RestoreSet[] getAvailableRestoreSets() throws android.os.RemoteException {
// one hardcoded restore set
- RestoreSet set = new RestoreSet("Local disk image", "flash", 0);
+ RestoreSet set = new RestoreSet("Local disk image", "flash", RESTORE_TOKEN);
RestoreSet[] array = { set };
return array;
}
+ public long getCurrentRestoreSet() {
+ // The hardcoded restore set always has the same token
+ return RESTORE_TOKEN;
+ }
+
public int startRestore(long token, PackageInfo[] packages) {
if (DEBUG) Log.v(TAG, "start restore " + token);
mRestorePackages = packages;
diff --git a/core/jni/CursorWindow.cpp b/core/jni/CursorWindow.cpp
index 7864189..694514e 100644
--- a/core/jni/CursorWindow.cpp
+++ b/core/jni/CursorWindow.cpp
@@ -60,7 +60,7 @@
{
//TODO Use a non-memory dealer mmap region for localOnly
- mHeap = new MemoryDealer(new SharedHeap(mMaxSize, 0, "CursorWindow"));
+ mHeap = new MemoryDealer(mMaxSize, "CursorWindow");
if (mHeap != NULL) {
mMemory = mHeap->allocate(mMaxSize);
if (mMemory != NULL) {
diff --git a/core/jni/com_google_android_gles_jni_GLImpl.cpp b/core/jni/com_google_android_gles_jni_GLImpl.cpp
index 93e4d2b..bf613e1 100644
--- a/core/jni/com_google_android_gles_jni_GLImpl.cpp
+++ b/core/jni/com_google_android_gles_jni_GLImpl.cpp
@@ -24,6 +24,23 @@
#include <GLES/gl.h>
#include <GLES/glext.h>
+// Work around differences between the generated name and the actual name.
+
+#define glBlendEquation glBlendEquationOES
+#define glBlendEquationSeparate glBlendEquationSeparateOES
+#define glBlendFuncSeparate glBlendFuncSeparateOES
+#define glGetTexGenfv glGetTexGenfvOES
+#define glGetTexGeniv glGetTexGenivOES
+#define glGetTexGenxv glGetTexGenxvOES
+#define glTexGenf glTexGenfOES
+#define glTexGenfv glTexGenfvOES
+#define glTexGeni glTexGeniOES
+#define glTexGeniv glTexGenivOES
+#define glTexGenx glTexGenxOES
+#define glTexGenxv glTexGenxvOES
+
+
+
/* special calls implemented in Android's GLES wrapper used to more
* efficiently bound-check passed arrays */
extern "C" {
@@ -59,6 +76,11 @@
static jfieldID positionID;
static jfieldID limitID;
static jfieldID elementSizeShiftID;
+static jfieldID haveCheckedExtensionsID;
+static jfieldID have_OES_blend_equation_separateID;
+static jfieldID have_OES_blend_subtractID;
+static jfieldID have_OES_framebuffer_objectID;
+static jfieldID have_OES_texture_cube_mapID;
/* Cache method IDs each time the class is loaded. */
@@ -73,6 +95,11 @@
jclass g11impClassLocal = _env->FindClass("com/google/android/gles_jni/GLImpl");
G11ImplClass = (jclass) _env->NewGlobalRef(g11impClassLocal);
+ haveCheckedExtensionsID = _env->GetFieldID(G11ImplClass, "haveCheckedExtensions", "Z");
+ have_OES_blend_equation_separateID = _env->GetFieldID(G11ImplClass, "have_OES_blend_equation_separate", "Z");
+ have_OES_blend_subtractID = _env->GetFieldID(G11ImplClass, "have_OES_blend_subtract", "Z");
+ have_OES_framebuffer_objectID = _env->GetFieldID(G11ImplClass, "have_OES_framebuffer_object", "Z");
+ have_OES_texture_cube_mapID = _env->GetFieldID(G11ImplClass, "have_OES_texture_cube_map", "Z");
getBasePointerID = _env->GetStaticMethodID(nioAccessClass,
"getBasePointer", "(Ljava/nio/Buffer;)J");
@@ -194,6 +221,64 @@
return numCompressedTextureFormats;
}
+// Check if the extension at the head of pExtensions is pExtension. Note that pExtensions is
+// terminated by either 0 or space, while pExtension is terminated by 0.
+
+static bool
+extensionEqual(const GLubyte* pExtensions, const GLubyte* pExtension) {
+ while (true) {
+ char a = *pExtensions++;
+ char b = *pExtension++;
+ bool aEnd = a == '\0' || a == ' ';
+ bool bEnd = b == '\0';
+ if ( aEnd || bEnd) {
+ return aEnd == bEnd;
+ }
+ if ( a != b ) {
+ return false;
+ }
+ }
+}
+
+static const GLubyte*
+nextExtension(const GLubyte* pExtensions) {
+ while (true) {
+ char a = *pExtensions++;
+ if ( a == '\0') {
+ return pExtensions-1;
+ } else if ( a == ' ') {
+ return pExtensions;
+ }
+ }
+}
+
+static bool
+checkForExtension(const GLubyte* pExtensions, const GLubyte* pExtension) {
+ for (;*pExtensions != '\0'; pExtensions = nextExtension(pExtensions)) {
+ if (extensionEqual(pExtensions, pExtension)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+static bool
+supportsExtension(JNIEnv *_env, jobject impl, jfieldID fieldId) {
+ if (!_env->GetBooleanField(impl, haveCheckedExtensionsID)) {
+ _env->SetBooleanField(impl, haveCheckedExtensionsID, true);
+ const GLubyte* sExtensions = glGetString(GL_EXTENSIONS);
+ _env->SetBooleanField(impl, have_OES_blend_equation_separateID,
+ checkForExtension(sExtensions, (const GLubyte*) "GL_OES_blend_equation_separate"));
+ _env->SetBooleanField(impl, have_OES_blend_subtractID,
+ checkForExtension(sExtensions, (const GLubyte*) "GL_OES_blend_subtract"));
+ _env->SetBooleanField(impl, have_OES_framebuffer_objectID,
+ checkForExtension(sExtensions, (const GLubyte*) "GL_OES_framebuffer_object"));
+ _env->SetBooleanField(impl, have_OES_texture_cube_mapID,
+ checkForExtension(sExtensions, (const GLubyte*) "GL_OES_texture_cube_map"));
+ }
+ return _env->GetBooleanField(impl, fieldId);
+}
+
// --------------------------------------------------------------------------
/* void glActiveTexture ( GLenum texture ) */
@@ -6137,315 +6222,1084 @@
static void
android_glBindFramebufferOES__II
(JNIEnv *_env, jobject _this, jint target, jint framebuffer) {
- _env->ThrowNew(UOEClass,
- "glBindFramebufferOES");
+ if (! supportsExtension(_env, _this, have_OES_framebuffer_objectID)) {
+ _env->ThrowNew(UOEClass,
+ "glBindFramebufferOES");
+ return;
+ }
+ glBindFramebufferOES(
+ (GLint)target,
+ (GLint)framebuffer
+ );
}
/* void glBindRenderbufferOES ( GLint target, GLint renderbuffer ) */
static void
android_glBindRenderbufferOES__II
(JNIEnv *_env, jobject _this, jint target, jint renderbuffer) {
- _env->ThrowNew(UOEClass,
- "glBindRenderbufferOES");
+ if (! supportsExtension(_env, _this, have_OES_framebuffer_objectID)) {
+ _env->ThrowNew(UOEClass,
+ "glBindRenderbufferOES");
+ return;
+ }
+ glBindRenderbufferOES(
+ (GLint)target,
+ (GLint)renderbuffer
+ );
}
/* void glBlendEquation ( GLint mode ) */
static void
android_glBlendEquation__I
(JNIEnv *_env, jobject _this, jint mode) {
- _env->ThrowNew(UOEClass,
- "glBlendEquation");
+ if (! supportsExtension(_env, _this, have_OES_blend_subtractID)) {
+ _env->ThrowNew(UOEClass,
+ "glBlendEquation");
+ return;
+ }
+ glBlendEquation(
+ (GLint)mode
+ );
}
/* void glBlendEquationSeparate ( GLint modeRGB, GLint modeAlpha ) */
static void
android_glBlendEquationSeparate__II
(JNIEnv *_env, jobject _this, jint modeRGB, jint modeAlpha) {
- _env->ThrowNew(UOEClass,
- "glBlendEquationSeparate");
+ if (! supportsExtension(_env, _this, have_OES_blend_equation_separateID)) {
+ _env->ThrowNew(UOEClass,
+ "glBlendEquationSeparate");
+ return;
+ }
+ glBlendEquationSeparate(
+ (GLint)modeRGB,
+ (GLint)modeAlpha
+ );
}
/* void glBlendFuncSeparate ( GLint srcRGB, GLint dstRGB, GLint srcAlpha, GLint dstAlpha ) */
static void
android_glBlendFuncSeparate__IIII
(JNIEnv *_env, jobject _this, jint srcRGB, jint dstRGB, jint srcAlpha, jint dstAlpha) {
- _env->ThrowNew(UOEClass,
- "glBlendFuncSeparate");
+ if (! supportsExtension(_env, _this, have_OES_blend_equation_separateID)) {
+ _env->ThrowNew(UOEClass,
+ "glBlendFuncSeparate");
+ return;
+ }
+ glBlendFuncSeparate(
+ (GLint)srcRGB,
+ (GLint)dstRGB,
+ (GLint)srcAlpha,
+ (GLint)dstAlpha
+ );
}
/* GLint glCheckFramebufferStatusOES ( GLint target ) */
static jint
android_glCheckFramebufferStatusOES__I
(JNIEnv *_env, jobject _this, jint target) {
- _env->ThrowNew(UOEClass,
- "glCheckFramebufferStatusOES");
- return 0;
+ if (! supportsExtension(_env, _this, have_OES_framebuffer_objectID)) {
+ _env->ThrowNew(UOEClass,
+ "glCheckFramebufferStatusOES");
+ return 0;
+ }
+ GLint _returnValue = 0;
+ _returnValue = glCheckFramebufferStatusOES(
+ (GLint)target
+ );
+ return _returnValue;
}
-/* void glDeleteFramebuffersOES ( GLint n, GLint *framebuffers ) */
+/* void glDeleteFramebuffersOES ( GLint n, GLuint *framebuffers ) */
static void
android_glDeleteFramebuffersOES__I_3II
(JNIEnv *_env, jobject _this, jint n, jintArray framebuffers_ref, jint offset) {
- _env->ThrowNew(UOEClass,
- "glDeleteFramebuffersOES");
+ if (! supportsExtension(_env, _this, have_OES_framebuffer_objectID)) {
+ _env->ThrowNew(UOEClass,
+ "glDeleteFramebuffersOES");
+ return;
+ }
+ jint _exception = 0;
+ GLuint *framebuffers_base = (GLuint *) 0;
+ jint _remaining;
+ GLuint *framebuffers = (GLuint *) 0;
+
+ if (!framebuffers_ref) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "framebuffers == null");
+ goto exit;
+ }
+ if (offset < 0) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "offset < 0");
+ goto exit;
+ }
+ _remaining = _env->GetArrayLength(framebuffers_ref) - offset;
+ if (_remaining < n) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "length - offset < n");
+ goto exit;
+ }
+ framebuffers_base = (GLuint *)
+ _env->GetPrimitiveArrayCritical(framebuffers_ref, (jboolean *)0);
+ framebuffers = framebuffers_base + offset;
+
+ glDeleteFramebuffersOES(
+ (GLint)n,
+ (GLuint *)framebuffers
+ );
+
+exit:
+ if (framebuffers_base) {
+ _env->ReleasePrimitiveArrayCritical(framebuffers_ref, framebuffers_base,
+ _exception ? JNI_ABORT: 0);
+ }
}
-/* void glDeleteFramebuffersOES ( GLint n, GLint *framebuffers ) */
+/* void glDeleteFramebuffersOES ( GLint n, GLuint *framebuffers ) */
static void
android_glDeleteFramebuffersOES__ILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint n, jobject framebuffers_buf) {
- _env->ThrowNew(UOEClass,
- "glDeleteFramebuffersOES");
+ if (! supportsExtension(_env, _this, have_OES_framebuffer_objectID)) {
+ _env->ThrowNew(UOEClass,
+ "glDeleteFramebuffersOES");
+ return;
+ }
+ jint _exception = 0;
+ jarray _array = (jarray) 0;
+ jint _remaining;
+ GLuint *framebuffers = (GLuint *) 0;
+
+ framebuffers = (GLuint *)getPointer(_env, framebuffers_buf, &_array, &_remaining);
+ if (_remaining < n) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "remaining() < n");
+ goto exit;
+ }
+ glDeleteFramebuffersOES(
+ (GLint)n,
+ (GLuint *)framebuffers
+ );
+
+exit:
+ if (_array) {
+ releasePointer(_env, _array, framebuffers, _exception ? JNI_FALSE : JNI_TRUE);
+ }
}
-/* void glDeleteRenderbuffersOES ( GLint n, GLint *renderbuffers ) */
+/* void glDeleteRenderbuffersOES ( GLint n, GLuint *renderbuffers ) */
static void
android_glDeleteRenderbuffersOES__I_3II
(JNIEnv *_env, jobject _this, jint n, jintArray renderbuffers_ref, jint offset) {
- _env->ThrowNew(UOEClass,
- "glDeleteRenderbuffersOES");
+ if (! supportsExtension(_env, _this, have_OES_framebuffer_objectID)) {
+ _env->ThrowNew(UOEClass,
+ "glDeleteRenderbuffersOES");
+ return;
+ }
+ jint _exception = 0;
+ GLuint *renderbuffers_base = (GLuint *) 0;
+ jint _remaining;
+ GLuint *renderbuffers = (GLuint *) 0;
+
+ if (!renderbuffers_ref) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "renderbuffers == null");
+ goto exit;
+ }
+ if (offset < 0) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "offset < 0");
+ goto exit;
+ }
+ _remaining = _env->GetArrayLength(renderbuffers_ref) - offset;
+ if (_remaining < n) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "length - offset < n");
+ goto exit;
+ }
+ renderbuffers_base = (GLuint *)
+ _env->GetPrimitiveArrayCritical(renderbuffers_ref, (jboolean *)0);
+ renderbuffers = renderbuffers_base + offset;
+
+ glDeleteRenderbuffersOES(
+ (GLint)n,
+ (GLuint *)renderbuffers
+ );
+
+exit:
+ if (renderbuffers_base) {
+ _env->ReleasePrimitiveArrayCritical(renderbuffers_ref, renderbuffers_base,
+ _exception ? JNI_ABORT: 0);
+ }
}
-/* void glDeleteRenderbuffersOES ( GLint n, GLint *renderbuffers ) */
+/* void glDeleteRenderbuffersOES ( GLint n, GLuint *renderbuffers ) */
static void
android_glDeleteRenderbuffersOES__ILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint n, jobject renderbuffers_buf) {
- _env->ThrowNew(UOEClass,
- "glDeleteRenderbuffersOES");
+ if (! supportsExtension(_env, _this, have_OES_framebuffer_objectID)) {
+ _env->ThrowNew(UOEClass,
+ "glDeleteRenderbuffersOES");
+ return;
+ }
+ jint _exception = 0;
+ jarray _array = (jarray) 0;
+ jint _remaining;
+ GLuint *renderbuffers = (GLuint *) 0;
+
+ renderbuffers = (GLuint *)getPointer(_env, renderbuffers_buf, &_array, &_remaining);
+ if (_remaining < n) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "remaining() < n");
+ goto exit;
+ }
+ glDeleteRenderbuffersOES(
+ (GLint)n,
+ (GLuint *)renderbuffers
+ );
+
+exit:
+ if (_array) {
+ releasePointer(_env, _array, renderbuffers, _exception ? JNI_FALSE : JNI_TRUE);
+ }
}
/* void glFramebufferRenderbufferOES ( GLint target, GLint attachment, GLint renderbuffertarget, GLint renderbuffer ) */
static void
android_glFramebufferRenderbufferOES__IIII
(JNIEnv *_env, jobject _this, jint target, jint attachment, jint renderbuffertarget, jint renderbuffer) {
- _env->ThrowNew(UOEClass,
- "glFramebufferRenderbufferOES");
+ if (! supportsExtension(_env, _this, have_OES_framebuffer_objectID)) {
+ _env->ThrowNew(UOEClass,
+ "glFramebufferRenderbufferOES");
+ return;
+ }
+ glFramebufferRenderbufferOES(
+ (GLint)target,
+ (GLint)attachment,
+ (GLint)renderbuffertarget,
+ (GLint)renderbuffer
+ );
}
/* void glFramebufferTexture2DOES ( GLint target, GLint attachment, GLint textarget, GLint texture, GLint level ) */
static void
android_glFramebufferTexture2DOES__IIIII
(JNIEnv *_env, jobject _this, jint target, jint attachment, jint textarget, jint texture, jint level) {
- _env->ThrowNew(UOEClass,
- "glFramebufferTexture2DOES");
+ if (! supportsExtension(_env, _this, have_OES_framebuffer_objectID)) {
+ _env->ThrowNew(UOEClass,
+ "glFramebufferTexture2DOES");
+ return;
+ }
+ glFramebufferTexture2DOES(
+ (GLint)target,
+ (GLint)attachment,
+ (GLint)textarget,
+ (GLint)texture,
+ (GLint)level
+ );
}
/* void glGenerateMipmapOES ( GLint target ) */
static void
android_glGenerateMipmapOES__I
(JNIEnv *_env, jobject _this, jint target) {
- _env->ThrowNew(UOEClass,
- "glGenerateMipmapOES");
+ if (! supportsExtension(_env, _this, have_OES_framebuffer_objectID)) {
+ _env->ThrowNew(UOEClass,
+ "glGenerateMipmapOES");
+ return;
+ }
+ glGenerateMipmapOES(
+ (GLint)target
+ );
}
-/* void glGenFramebuffersOES ( GLint n, GLint *framebuffers ) */
+/* void glGenFramebuffersOES ( GLint n, GLuint *framebuffers ) */
static void
android_glGenFramebuffersOES__I_3II
(JNIEnv *_env, jobject _this, jint n, jintArray framebuffers_ref, jint offset) {
- _env->ThrowNew(UOEClass,
- "glGenFramebuffersOES");
+ if (! supportsExtension(_env, _this, have_OES_framebuffer_objectID)) {
+ _env->ThrowNew(UOEClass,
+ "glGenFramebuffersOES");
+ return;
+ }
+ jint _exception = 0;
+ GLuint *framebuffers_base = (GLuint *) 0;
+ jint _remaining;
+ GLuint *framebuffers = (GLuint *) 0;
+
+ if (!framebuffers_ref) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "framebuffers == null");
+ goto exit;
+ }
+ if (offset < 0) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "offset < 0");
+ goto exit;
+ }
+ _remaining = _env->GetArrayLength(framebuffers_ref) - offset;
+ if (_remaining < n) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "length - offset < n");
+ goto exit;
+ }
+ framebuffers_base = (GLuint *)
+ _env->GetPrimitiveArrayCritical(framebuffers_ref, (jboolean *)0);
+ framebuffers = framebuffers_base + offset;
+
+ glGenFramebuffersOES(
+ (GLint)n,
+ (GLuint *)framebuffers
+ );
+
+exit:
+ if (framebuffers_base) {
+ _env->ReleasePrimitiveArrayCritical(framebuffers_ref, framebuffers_base,
+ _exception ? JNI_ABORT: 0);
+ }
}
-/* void glGenFramebuffersOES ( GLint n, GLint *framebuffers ) */
+/* void glGenFramebuffersOES ( GLint n, GLuint *framebuffers ) */
static void
android_glGenFramebuffersOES__ILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint n, jobject framebuffers_buf) {
- _env->ThrowNew(UOEClass,
- "glGenFramebuffersOES");
+ if (! supportsExtension(_env, _this, have_OES_framebuffer_objectID)) {
+ _env->ThrowNew(UOEClass,
+ "glGenFramebuffersOES");
+ return;
+ }
+ jint _exception = 0;
+ jarray _array = (jarray) 0;
+ jint _remaining;
+ GLuint *framebuffers = (GLuint *) 0;
+
+ framebuffers = (GLuint *)getPointer(_env, framebuffers_buf, &_array, &_remaining);
+ if (_remaining < n) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "remaining() < n");
+ goto exit;
+ }
+ glGenFramebuffersOES(
+ (GLint)n,
+ (GLuint *)framebuffers
+ );
+
+exit:
+ if (_array) {
+ releasePointer(_env, _array, framebuffers, _exception ? JNI_FALSE : JNI_TRUE);
+ }
}
-/* void glGenRenderbuffersOES ( GLint n, GLint *renderbuffers ) */
+/* void glGenRenderbuffersOES ( GLint n, GLuint *renderbuffers ) */
static void
android_glGenRenderbuffersOES__I_3II
(JNIEnv *_env, jobject _this, jint n, jintArray renderbuffers_ref, jint offset) {
- _env->ThrowNew(UOEClass,
- "glGenRenderbuffersOES");
+ if (! supportsExtension(_env, _this, have_OES_framebuffer_objectID)) {
+ _env->ThrowNew(UOEClass,
+ "glGenRenderbuffersOES");
+ return;
+ }
+ jint _exception = 0;
+ GLuint *renderbuffers_base = (GLuint *) 0;
+ jint _remaining;
+ GLuint *renderbuffers = (GLuint *) 0;
+
+ if (!renderbuffers_ref) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "renderbuffers == null");
+ goto exit;
+ }
+ if (offset < 0) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "offset < 0");
+ goto exit;
+ }
+ _remaining = _env->GetArrayLength(renderbuffers_ref) - offset;
+ if (_remaining < n) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "length - offset < n");
+ goto exit;
+ }
+ renderbuffers_base = (GLuint *)
+ _env->GetPrimitiveArrayCritical(renderbuffers_ref, (jboolean *)0);
+ renderbuffers = renderbuffers_base + offset;
+
+ glGenRenderbuffersOES(
+ (GLint)n,
+ (GLuint *)renderbuffers
+ );
+
+exit:
+ if (renderbuffers_base) {
+ _env->ReleasePrimitiveArrayCritical(renderbuffers_ref, renderbuffers_base,
+ _exception ? JNI_ABORT: 0);
+ }
}
-/* void glGenRenderbuffersOES ( GLint n, GLint *renderbuffers ) */
+/* void glGenRenderbuffersOES ( GLint n, GLuint *renderbuffers ) */
static void
android_glGenRenderbuffersOES__ILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint n, jobject renderbuffers_buf) {
- _env->ThrowNew(UOEClass,
- "glGenRenderbuffersOES");
+ if (! supportsExtension(_env, _this, have_OES_framebuffer_objectID)) {
+ _env->ThrowNew(UOEClass,
+ "glGenRenderbuffersOES");
+ return;
+ }
+ jint _exception = 0;
+ jarray _array = (jarray) 0;
+ jint _remaining;
+ GLuint *renderbuffers = (GLuint *) 0;
+
+ renderbuffers = (GLuint *)getPointer(_env, renderbuffers_buf, &_array, &_remaining);
+ if (_remaining < n) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "remaining() < n");
+ goto exit;
+ }
+ glGenRenderbuffersOES(
+ (GLint)n,
+ (GLuint *)renderbuffers
+ );
+
+exit:
+ if (_array) {
+ releasePointer(_env, _array, renderbuffers, _exception ? JNI_FALSE : JNI_TRUE);
+ }
}
/* void glGetFramebufferAttachmentParameterivOES ( GLint target, GLint attachment, GLint pname, GLint *params ) */
static void
android_glGetFramebufferAttachmentParameterivOES__III_3II
(JNIEnv *_env, jobject _this, jint target, jint attachment, jint pname, jintArray params_ref, jint offset) {
- _env->ThrowNew(UOEClass,
- "glGetFramebufferAttachmentParameterivOES");
+ if (! supportsExtension(_env, _this, have_OES_framebuffer_objectID)) {
+ _env->ThrowNew(UOEClass,
+ "glGetFramebufferAttachmentParameterivOES");
+ return;
+ }
+ jint _exception = 0;
+ GLint *params_base = (GLint *) 0;
+ jint _remaining;
+ GLint *params = (GLint *) 0;
+
+ if (!params_ref) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "params == null");
+ goto exit;
+ }
+ if (offset < 0) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "offset < 0");
+ goto exit;
+ }
+ _remaining = _env->GetArrayLength(params_ref) - offset;
+ params_base = (GLint *)
+ _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+ params = params_base + offset;
+
+ glGetFramebufferAttachmentParameterivOES(
+ (GLint)target,
+ (GLint)attachment,
+ (GLint)pname,
+ (GLint *)params
+ );
+
+exit:
+ if (params_base) {
+ _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+ _exception ? JNI_ABORT: 0);
+ }
}
/* void glGetFramebufferAttachmentParameterivOES ( GLint target, GLint attachment, GLint pname, GLint *params ) */
static void
android_glGetFramebufferAttachmentParameterivOES__IIILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint target, jint attachment, jint pname, jobject params_buf) {
- _env->ThrowNew(UOEClass,
- "glGetFramebufferAttachmentParameterivOES");
+ if (! supportsExtension(_env, _this, have_OES_framebuffer_objectID)) {
+ _env->ThrowNew(UOEClass,
+ "glGetFramebufferAttachmentParameterivOES");
+ return;
+ }
+ jint _exception = 0;
+ jarray _array = (jarray) 0;
+ jint _remaining;
+ GLint *params = (GLint *) 0;
+
+ params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+ glGetFramebufferAttachmentParameterivOES(
+ (GLint)target,
+ (GLint)attachment,
+ (GLint)pname,
+ (GLint *)params
+ );
+ if (_array) {
+ releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+ }
}
/* void glGetRenderbufferParameterivOES ( GLint target, GLint pname, GLint *params ) */
static void
android_glGetRenderbufferParameterivOES__II_3II
(JNIEnv *_env, jobject _this, jint target, jint pname, jintArray params_ref, jint offset) {
- _env->ThrowNew(UOEClass,
- "glGetRenderbufferParameterivOES");
+ if (! supportsExtension(_env, _this, have_OES_framebuffer_objectID)) {
+ _env->ThrowNew(UOEClass,
+ "glGetRenderbufferParameterivOES");
+ return;
+ }
+ jint _exception = 0;
+ GLint *params_base = (GLint *) 0;
+ jint _remaining;
+ GLint *params = (GLint *) 0;
+
+ if (!params_ref) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "params == null");
+ goto exit;
+ }
+ if (offset < 0) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "offset < 0");
+ goto exit;
+ }
+ _remaining = _env->GetArrayLength(params_ref) - offset;
+ params_base = (GLint *)
+ _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+ params = params_base + offset;
+
+ glGetRenderbufferParameterivOES(
+ (GLint)target,
+ (GLint)pname,
+ (GLint *)params
+ );
+
+exit:
+ if (params_base) {
+ _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+ _exception ? JNI_ABORT: 0);
+ }
}
/* void glGetRenderbufferParameterivOES ( GLint target, GLint pname, GLint *params ) */
static void
android_glGetRenderbufferParameterivOES__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
- _env->ThrowNew(UOEClass,
- "glGetRenderbufferParameterivOES");
+ if (! supportsExtension(_env, _this, have_OES_framebuffer_objectID)) {
+ _env->ThrowNew(UOEClass,
+ "glGetRenderbufferParameterivOES");
+ return;
+ }
+ jint _exception = 0;
+ jarray _array = (jarray) 0;
+ jint _remaining;
+ GLint *params = (GLint *) 0;
+
+ params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+ glGetRenderbufferParameterivOES(
+ (GLint)target,
+ (GLint)pname,
+ (GLint *)params
+ );
+ if (_array) {
+ releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+ }
}
/* void glGetTexGenfv ( GLint coord, GLint pname, GLfloat *params ) */
static void
android_glGetTexGenfv__II_3FI
(JNIEnv *_env, jobject _this, jint coord, jint pname, jfloatArray params_ref, jint offset) {
- _env->ThrowNew(UOEClass,
- "glGetTexGenfv");
+ if (! supportsExtension(_env, _this, have_OES_texture_cube_mapID)) {
+ _env->ThrowNew(UOEClass,
+ "glGetTexGenfv");
+ return;
+ }
+ jint _exception = 0;
+ GLfloat *params_base = (GLfloat *) 0;
+ jint _remaining;
+ GLfloat *params = (GLfloat *) 0;
+
+ if (!params_ref) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "params == null");
+ goto exit;
+ }
+ if (offset < 0) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "offset < 0");
+ goto exit;
+ }
+ _remaining = _env->GetArrayLength(params_ref) - offset;
+ params_base = (GLfloat *)
+ _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+ params = params_base + offset;
+
+ glGetTexGenfv(
+ (GLint)coord,
+ (GLint)pname,
+ (GLfloat *)params
+ );
+
+exit:
+ if (params_base) {
+ _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+ _exception ? JNI_ABORT: 0);
+ }
}
/* void glGetTexGenfv ( GLint coord, GLint pname, GLfloat *params ) */
static void
android_glGetTexGenfv__IILjava_nio_FloatBuffer_2
(JNIEnv *_env, jobject _this, jint coord, jint pname, jobject params_buf) {
- _env->ThrowNew(UOEClass,
- "glGetTexGenfv");
+ if (! supportsExtension(_env, _this, have_OES_texture_cube_mapID)) {
+ _env->ThrowNew(UOEClass,
+ "glGetTexGenfv");
+ return;
+ }
+ jint _exception = 0;
+ jarray _array = (jarray) 0;
+ jint _remaining;
+ GLfloat *params = (GLfloat *) 0;
+
+ params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+ glGetTexGenfv(
+ (GLint)coord,
+ (GLint)pname,
+ (GLfloat *)params
+ );
+ if (_array) {
+ releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+ }
}
/* void glGetTexGeniv ( GLint coord, GLint pname, GLint *params ) */
static void
android_glGetTexGeniv__II_3II
(JNIEnv *_env, jobject _this, jint coord, jint pname, jintArray params_ref, jint offset) {
- _env->ThrowNew(UOEClass,
- "glGetTexGeniv");
+ if (! supportsExtension(_env, _this, have_OES_texture_cube_mapID)) {
+ _env->ThrowNew(UOEClass,
+ "glGetTexGeniv");
+ return;
+ }
+ jint _exception = 0;
+ GLint *params_base = (GLint *) 0;
+ jint _remaining;
+ GLint *params = (GLint *) 0;
+
+ if (!params_ref) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "params == null");
+ goto exit;
+ }
+ if (offset < 0) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "offset < 0");
+ goto exit;
+ }
+ _remaining = _env->GetArrayLength(params_ref) - offset;
+ params_base = (GLint *)
+ _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+ params = params_base + offset;
+
+ glGetTexGeniv(
+ (GLint)coord,
+ (GLint)pname,
+ (GLint *)params
+ );
+
+exit:
+ if (params_base) {
+ _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+ _exception ? JNI_ABORT: 0);
+ }
}
/* void glGetTexGeniv ( GLint coord, GLint pname, GLint *params ) */
static void
android_glGetTexGeniv__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint coord, jint pname, jobject params_buf) {
- _env->ThrowNew(UOEClass,
- "glGetTexGeniv");
+ if (! supportsExtension(_env, _this, have_OES_texture_cube_mapID)) {
+ _env->ThrowNew(UOEClass,
+ "glGetTexGeniv");
+ return;
+ }
+ jint _exception = 0;
+ jarray _array = (jarray) 0;
+ jint _remaining;
+ GLint *params = (GLint *) 0;
+
+ params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+ glGetTexGeniv(
+ (GLint)coord,
+ (GLint)pname,
+ (GLint *)params
+ );
+ if (_array) {
+ releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+ }
}
/* void glGetTexGenxv ( GLint coord, GLint pname, GLint *params ) */
static void
android_glGetTexGenxv__II_3II
(JNIEnv *_env, jobject _this, jint coord, jint pname, jintArray params_ref, jint offset) {
- _env->ThrowNew(UOEClass,
- "glGetTexGenxv");
+ if (! supportsExtension(_env, _this, have_OES_texture_cube_mapID)) {
+ _env->ThrowNew(UOEClass,
+ "glGetTexGenxv");
+ return;
+ }
+ jint _exception = 0;
+ GLint *params_base = (GLint *) 0;
+ jint _remaining;
+ GLint *params = (GLint *) 0;
+
+ if (!params_ref) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "params == null");
+ goto exit;
+ }
+ if (offset < 0) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "offset < 0");
+ goto exit;
+ }
+ _remaining = _env->GetArrayLength(params_ref) - offset;
+ params_base = (GLint *)
+ _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+ params = params_base + offset;
+
+ glGetTexGenxv(
+ (GLint)coord,
+ (GLint)pname,
+ (GLint *)params
+ );
+
+exit:
+ if (params_base) {
+ _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+ _exception ? JNI_ABORT: 0);
+ }
}
/* void glGetTexGenxv ( GLint coord, GLint pname, GLint *params ) */
static void
android_glGetTexGenxv__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint coord, jint pname, jobject params_buf) {
- _env->ThrowNew(UOEClass,
- "glGetTexGenxv");
+ if (! supportsExtension(_env, _this, have_OES_texture_cube_mapID)) {
+ _env->ThrowNew(UOEClass,
+ "glGetTexGenxv");
+ return;
+ }
+ jint _exception = 0;
+ jarray _array = (jarray) 0;
+ jint _remaining;
+ GLint *params = (GLint *) 0;
+
+ params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+ glGetTexGenxv(
+ (GLint)coord,
+ (GLint)pname,
+ (GLint *)params
+ );
+ if (_array) {
+ releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+ }
}
/* GLboolean glIsFramebufferOES ( GLint framebuffer ) */
static jboolean
android_glIsFramebufferOES__I
(JNIEnv *_env, jobject _this, jint framebuffer) {
- _env->ThrowNew(UOEClass,
- "glIsFramebufferOES");
- return JNI_FALSE;
+ if (! supportsExtension(_env, _this, have_OES_framebuffer_objectID)) {
+ _env->ThrowNew(UOEClass,
+ "glIsFramebufferOES");
+ return JNI_FALSE;
+ }
+ GLboolean _returnValue = JNI_FALSE;
+ _returnValue = glIsFramebufferOES(
+ (GLint)framebuffer
+ );
+ return _returnValue;
}
/* GLboolean glIsRenderbufferOES ( GLint renderbuffer ) */
static jboolean
android_glIsRenderbufferOES__I
(JNIEnv *_env, jobject _this, jint renderbuffer) {
- _env->ThrowNew(UOEClass,
- "glIsRenderbufferOES");
- return JNI_FALSE;
+ if (! supportsExtension(_env, _this, have_OES_framebuffer_objectID)) {
+ _env->ThrowNew(UOEClass,
+ "glIsRenderbufferOES");
+ return JNI_FALSE;
+ }
+ GLboolean _returnValue = JNI_FALSE;
+ _returnValue = glIsRenderbufferOES(
+ (GLint)renderbuffer
+ );
+ return _returnValue;
}
/* void glRenderbufferStorageOES ( GLint target, GLint internalformat, GLint width, GLint height ) */
static void
android_glRenderbufferStorageOES__IIII
(JNIEnv *_env, jobject _this, jint target, jint internalformat, jint width, jint height) {
- _env->ThrowNew(UOEClass,
- "glRenderbufferStorageOES");
+ if (! supportsExtension(_env, _this, have_OES_framebuffer_objectID)) {
+ _env->ThrowNew(UOEClass,
+ "glRenderbufferStorageOES");
+ return;
+ }
+ glRenderbufferStorageOES(
+ (GLint)target,
+ (GLint)internalformat,
+ (GLint)width,
+ (GLint)height
+ );
}
/* void glTexGenf ( GLint coord, GLint pname, GLfloat param ) */
static void
android_glTexGenf__IIF
(JNIEnv *_env, jobject _this, jint coord, jint pname, jfloat param) {
- _env->ThrowNew(UOEClass,
- "glTexGenf");
+ if (! supportsExtension(_env, _this, have_OES_texture_cube_mapID)) {
+ _env->ThrowNew(UOEClass,
+ "glTexGenf");
+ return;
+ }
+ glTexGenf(
+ (GLint)coord,
+ (GLint)pname,
+ (GLfloat)param
+ );
}
/* void glTexGenfv ( GLint coord, GLint pname, GLfloat *params ) */
static void
android_glTexGenfv__II_3FI
(JNIEnv *_env, jobject _this, jint coord, jint pname, jfloatArray params_ref, jint offset) {
- _env->ThrowNew(UOEClass,
- "glTexGenfv");
+ if (! supportsExtension(_env, _this, have_OES_texture_cube_mapID)) {
+ _env->ThrowNew(UOEClass,
+ "glTexGenfv");
+ return;
+ }
+ jint _exception = 0;
+ GLfloat *params_base = (GLfloat *) 0;
+ jint _remaining;
+ GLfloat *params = (GLfloat *) 0;
+
+ if (!params_ref) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "params == null");
+ goto exit;
+ }
+ if (offset < 0) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "offset < 0");
+ goto exit;
+ }
+ _remaining = _env->GetArrayLength(params_ref) - offset;
+ params_base = (GLfloat *)
+ _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+ params = params_base + offset;
+
+ glTexGenfv(
+ (GLint)coord,
+ (GLint)pname,
+ (GLfloat *)params
+ );
+
+exit:
+ if (params_base) {
+ _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+ _exception ? JNI_ABORT: 0);
+ }
}
/* void glTexGenfv ( GLint coord, GLint pname, GLfloat *params ) */
static void
android_glTexGenfv__IILjava_nio_FloatBuffer_2
(JNIEnv *_env, jobject _this, jint coord, jint pname, jobject params_buf) {
- _env->ThrowNew(UOEClass,
- "glTexGenfv");
+ if (! supportsExtension(_env, _this, have_OES_texture_cube_mapID)) {
+ _env->ThrowNew(UOEClass,
+ "glTexGenfv");
+ return;
+ }
+ jint _exception = 0;
+ jarray _array = (jarray) 0;
+ jint _remaining;
+ GLfloat *params = (GLfloat *) 0;
+
+ params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
+ glTexGenfv(
+ (GLint)coord,
+ (GLint)pname,
+ (GLfloat *)params
+ );
+ if (_array) {
+ releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+ }
}
/* void glTexGeni ( GLint coord, GLint pname, GLint param ) */
static void
android_glTexGeni__III
(JNIEnv *_env, jobject _this, jint coord, jint pname, jint param) {
- _env->ThrowNew(UOEClass,
- "glTexGeni");
+ if (! supportsExtension(_env, _this, have_OES_texture_cube_mapID)) {
+ _env->ThrowNew(UOEClass,
+ "glTexGeni");
+ return;
+ }
+ glTexGeni(
+ (GLint)coord,
+ (GLint)pname,
+ (GLint)param
+ );
}
/* void glTexGeniv ( GLint coord, GLint pname, GLint *params ) */
static void
android_glTexGeniv__II_3II
(JNIEnv *_env, jobject _this, jint coord, jint pname, jintArray params_ref, jint offset) {
- _env->ThrowNew(UOEClass,
- "glTexGeniv");
+ if (! supportsExtension(_env, _this, have_OES_texture_cube_mapID)) {
+ _env->ThrowNew(UOEClass,
+ "glTexGeniv");
+ return;
+ }
+ jint _exception = 0;
+ GLint *params_base = (GLint *) 0;
+ jint _remaining;
+ GLint *params = (GLint *) 0;
+
+ if (!params_ref) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "params == null");
+ goto exit;
+ }
+ if (offset < 0) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "offset < 0");
+ goto exit;
+ }
+ _remaining = _env->GetArrayLength(params_ref) - offset;
+ params_base = (GLint *)
+ _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+ params = params_base + offset;
+
+ glTexGeniv(
+ (GLint)coord,
+ (GLint)pname,
+ (GLint *)params
+ );
+
+exit:
+ if (params_base) {
+ _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+ _exception ? JNI_ABORT: 0);
+ }
}
/* void glTexGeniv ( GLint coord, GLint pname, GLint *params ) */
static void
android_glTexGeniv__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint coord, jint pname, jobject params_buf) {
- _env->ThrowNew(UOEClass,
- "glTexGeniv");
+ if (! supportsExtension(_env, _this, have_OES_texture_cube_mapID)) {
+ _env->ThrowNew(UOEClass,
+ "glTexGeniv");
+ return;
+ }
+ jint _exception = 0;
+ jarray _array = (jarray) 0;
+ jint _remaining;
+ GLint *params = (GLint *) 0;
+
+ params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+ glTexGeniv(
+ (GLint)coord,
+ (GLint)pname,
+ (GLint *)params
+ );
+ if (_array) {
+ releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+ }
}
/* void glTexGenx ( GLint coord, GLint pname, GLint param ) */
static void
android_glTexGenx__III
(JNIEnv *_env, jobject _this, jint coord, jint pname, jint param) {
- _env->ThrowNew(UOEClass,
- "glTexGenx");
+ if (! supportsExtension(_env, _this, have_OES_texture_cube_mapID)) {
+ _env->ThrowNew(UOEClass,
+ "glTexGenx");
+ return;
+ }
+ glTexGenx(
+ (GLint)coord,
+ (GLint)pname,
+ (GLint)param
+ );
}
/* void glTexGenxv ( GLint coord, GLint pname, GLint *params ) */
static void
android_glTexGenxv__II_3II
(JNIEnv *_env, jobject _this, jint coord, jint pname, jintArray params_ref, jint offset) {
- _env->ThrowNew(UOEClass,
- "glTexGenxv");
+ if (! supportsExtension(_env, _this, have_OES_texture_cube_mapID)) {
+ _env->ThrowNew(UOEClass,
+ "glTexGenxv");
+ return;
+ }
+ jint _exception = 0;
+ GLint *params_base = (GLint *) 0;
+ jint _remaining;
+ GLint *params = (GLint *) 0;
+
+ if (!params_ref) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "params == null");
+ goto exit;
+ }
+ if (offset < 0) {
+ _exception = 1;
+ _env->ThrowNew(IAEClass, "offset < 0");
+ goto exit;
+ }
+ _remaining = _env->GetArrayLength(params_ref) - offset;
+ params_base = (GLint *)
+ _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+ params = params_base + offset;
+
+ glTexGenxv(
+ (GLint)coord,
+ (GLint)pname,
+ (GLint *)params
+ );
+
+exit:
+ if (params_base) {
+ _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+ _exception ? JNI_ABORT: 0);
+ }
}
/* void glTexGenxv ( GLint coord, GLint pname, GLint *params ) */
static void
android_glTexGenxv__IILjava_nio_IntBuffer_2
(JNIEnv *_env, jobject _this, jint coord, jint pname, jobject params_buf) {
- _env->ThrowNew(UOEClass,
- "glTexGenxv");
+ if (! supportsExtension(_env, _this, have_OES_texture_cube_mapID)) {
+ _env->ThrowNew(UOEClass,
+ "glTexGenxv");
+ return;
+ }
+ jint _exception = 0;
+ jarray _array = (jarray) 0;
+ jint _remaining;
+ GLint *params = (GLint *) 0;
+
+ params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
+ glTexGenxv(
+ (GLint)coord,
+ (GLint)pname,
+ (GLint *)params
+ );
+ if (_array) {
+ releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+ }
}
static const char *classPathName = "com/google/android/gles_jni/GLImpl";
diff --git a/docs/html/guide/developing/debug-tasks.jd b/docs/html/guide/developing/debug-tasks.jd
index a980efc..500ef58 100644
--- a/docs/html/guide/developing/debug-tasks.jd
+++ b/docs/html/guide/developing/debug-tasks.jd
@@ -58,8 +58,8 @@
<pre class="no-pretty-print">
I/MyActivity( 1557): MyClass.getView() — get item number 1
</pre>
- <p>Logcat is also the place to look when debugging a web page in the Android browser. All
-browser bugs will be output to logcat with the {@code WebCore} tag.
+ <p>Logcat is also the place to look when debugging a web page in the Android Browser app. See
+<a href="#DebuggingWebPages">Debugging Web Pages</a> below.</p>
</dl>
<p>For more information about all the development tools provided with the Android SDK, see the <a
@@ -148,10 +148,10 @@
<h2 id="DebuggingWebPages">Debugging Web Pages</h2>
-<p>If you're developing a web application for Android devices, you can debug your JavaScript on
-Android using the Console APIs, which will output messages to logcat. If you're familiar
+<p>If you're developing a web application for Android devices, you can debug your JavaScript in the
+Android Browser using the Console APIs, which will output messages to logcat. If you're familiar
debugging web pages with Firefox's FireBug or WebKit's Web Inspector, then you're probably familiar
-with the Console APIs. The Android Browser (and {@link android.webkit.WebChromeClient}) supports
+with the Console APIs. The Android Browser (and the {@link android.webkit.WebChromeClient}) supports
most of the same APIs.</p>
<p>When you call a function from the Console APIs (in the DOM's {@code window.console} object),
@@ -162,19 +162,28 @@
</pre>
<p>Then the logcat output from the Android Browser will look like this:</p>
<pre class="no-pretty-print">
-W/browser ( 202): Console: Hello World :0
+W/browser ( 202): Console: Hello World http://www.example.com/hello.html :82
</pre>
-<p class="note"><strong>Note:</strong> All Console messages from the Android
-Browser are tagged with the name "browser" on Android platforms running API Level 7 or higher and
-tagged with the name "WebCore" for platforms running API Level 6 or lower.</p>
+<p>All Console messages from the Android Browser are tagged with the name "browser" on Android
+platforms running API Level 7 or higher. On platforms running API Level 6 or lower, Browser
+messages are tagged with the name "WebCore". The Android Browser also formats console messages
+with the log message
+preceded by "Console:" and then followed by the address and line number where the
+message occurred. (The format for the address and line number will appear different from the example
+above on platforms running API Level 6 or lower.)</p>
-<p>Not all of the Console APIs available in Firefox or other WebKit browsers are implemented
-on Android. Mostly, you need to depend on basic text logging provided by
-functions like {@code console.log(String)}, {@code console.info(String)}, {@code
-console.warn(String)}, and {@code console.error(String)}. Although other Console functions may not
-be implemented, they will not raise run-time errors, but will simply not behave as you might
-expect.</p>
+<p>The Android Browser (and {@link android.webkit.WebChromeClient}) does not implement all of the
+Console APIs provided by Firefox or other WebKit-based browsers. Primarily, you need to depend
+on the basic text logging functions:</p>
+<ul>
+ <li>{@code console.log(String)}</li>
+ <li>{@code console.info(String)}</li>
+ <li>{@code console.warn(String)}</li>
+ <li>{@code console.error(String)}</li>
+</ul>
+<p>Although the Android Browser may not fully implement other Console functions, they will not raise
+run-time errors, but may not behave the same as they do on other desktop browsers.</p>
<p>If you've implemented a custom {@link android.webkit.WebView} in your application, then in order
to receive messages that are sent through the Console APIs, you must provide a {@link
@@ -185,7 +194,7 @@
<pre>
myWebView.setWebChromeClient(new WebChromeClient() {
public void onConsoleMessage(String message, int lineNumber, String sourceID) {
- Log.d("MyApplication", message);
+ Log.d("MyApplication", message + " -- From line " + lineNumber + " of " + sourceID);
}
});
</pre>
@@ -195,13 +204,14 @@
<p>When the "Hello World" log is executed through your {@link android.webkit.WebView}, it will
now look like this:</p>
<pre class="no-pretty-print">
-D/MyApplication ( 430): Hello World
+D/MyApplication ( 430): Hello World -- From line 82 of http://www.example.com/hello.html
</pre>
<p class="note"><strong>Note:</strong> The {@link
android.webkit.WebChromeClient#onConsoleMessage(String,int,String) onConsoleMessage()} callback
-method was added with API Level 7. If you are targetting platforms running API Level 6 or lower,
-then your Console messages will automatically be sent to logcat with the "WebCore" logging tag.</p>
+method was added with API Level 7. If you are using a custom {@link
+android.webkit.WebView} on a platform running API Level 6 or lower, then your Console messages will
+automatically be sent to logcat with the "WebCore" logging tag.</p>
diff --git a/include/binder/MemoryDealer.h b/include/binder/MemoryDealer.h
index 03ac70a..170f20d 100644
--- a/include/binder/MemoryDealer.h
+++ b/include/binder/MemoryDealer.h
@@ -22,232 +22,35 @@
#include <sys/types.h>
#include <binder/IMemory.h>
-#include <utils/threads.h>
#include <binder/MemoryHeapBase.h>
namespace android {
// ----------------------------------------------------------------------------
-class String8;
-/*
- * interface for implementing a "heap". A heap basically provides
- * the IMemoryHeap interface for cross-process sharing and the
- * ability to map/unmap pages within the heap.
- */
-class HeapInterface : public virtual BnMemoryHeap
-{
-public:
- // all values must be page-aligned
- virtual sp<IMemory> mapMemory(size_t offset, size_t size) = 0;
-
- HeapInterface();
-protected:
- virtual ~HeapInterface();
-};
-
-// ----------------------------------------------------------------------------
-
-/*
- * interface for implementing an allocator. An allocator provides
- * methods for allocating and freeing memory blocks and dumping
- * its state.
- */
-class AllocatorInterface : public RefBase
-{
-public:
- enum {
- PAGE_ALIGNED = 0x00000001
- };
-
- virtual size_t allocate(size_t size, uint32_t flags = 0) = 0;
- virtual status_t deallocate(size_t offset) = 0;
- virtual size_t size() const = 0;
- virtual void dump(const char* what, uint32_t flags = 0) const = 0;
- virtual void dump(String8& res,
- const char* what, uint32_t flags = 0) const = 0;
-
- AllocatorInterface();
-protected:
- virtual ~AllocatorInterface();
-};
-
-// ----------------------------------------------------------------------------
-
-/*
- * concrete implementation of HeapInterface on top of mmap()
- */
-class SharedHeap : public HeapInterface, public MemoryHeapBase
-{
-public:
- SharedHeap();
- SharedHeap(size_t size, uint32_t flags = 0, char const * name = NULL);
- virtual ~SharedHeap();
- virtual sp<IMemory> mapMemory(size_t offset, size_t size);
-};
-
-// ----------------------------------------------------------------------------
-
-/*
- * A simple templatized doubly linked-list implementation
- */
-
-template <typename NODE>
-class LinkedList
-{
- NODE* mFirst;
- NODE* mLast;
-
-public:
- LinkedList() : mFirst(0), mLast(0) { }
- bool isEmpty() const { return mFirst == 0; }
- NODE const* head() const { return mFirst; }
- NODE* head() { return mFirst; }
- NODE const* tail() const { return mLast; }
- NODE* tail() { return mLast; }
-
- void insertAfter(NODE* node, NODE* newNode) {
- newNode->prev = node;
- newNode->next = node->next;
- if (node->next == 0) mLast = newNode;
- else node->next->prev = newNode;
- node->next = newNode;
- }
-
- void insertBefore(NODE* node, NODE* newNode) {
- newNode->prev = node->prev;
- newNode->next = node;
- if (node->prev == 0) mFirst = newNode;
- else node->prev->next = newNode;
- node->prev = newNode;
- }
-
- void insertHead(NODE* newNode) {
- if (mFirst == 0) {
- mFirst = mLast = newNode;
- newNode->prev = newNode->next = 0;
- } else {
- newNode->prev = 0;
- newNode->next = mFirst;
- mFirst->prev = newNode;
- mFirst = newNode;
- }
- }
-
- void insertTail(NODE* newNode) {
- if (mLast == 0) {
- insertHead(newNode);
- } else {
- newNode->prev = mLast;
- newNode->next = 0;
- mLast->next = newNode;
- mLast = newNode;
- }
- }
-
- NODE* remove(NODE* node) {
- if (node->prev == 0) mFirst = node->next;
- else node->prev->next = node->next;
- if (node->next == 0) mLast = node->prev;
- else node->next->prev = node->prev;
- return node;
- }
-};
-
-
-/*
- * concrete implementation of AllocatorInterface using a simple
- * best-fit allocation scheme
- */
-class SimpleBestFitAllocator : public AllocatorInterface
-{
-public:
-
- SimpleBestFitAllocator(size_t size);
- virtual ~SimpleBestFitAllocator();
-
- virtual size_t allocate(size_t size, uint32_t flags = 0);
- virtual status_t deallocate(size_t offset);
- virtual size_t size() const;
- virtual void dump(const char* what, uint32_t flags = 0) const;
- virtual void dump(String8& res,
- const char* what, uint32_t flags = 0) const;
-
-private:
-
- struct chunk_t {
- chunk_t(size_t start, size_t size)
- : start(start), size(size), free(1), prev(0), next(0) {
- }
- size_t start;
- size_t size : 28;
- int free : 4;
- mutable chunk_t* prev;
- mutable chunk_t* next;
- };
-
- ssize_t alloc(size_t size, uint32_t flags);
- chunk_t* dealloc(size_t start);
- void dump_l(const char* what, uint32_t flags = 0) const;
- void dump_l(String8& res, const char* what, uint32_t flags = 0) const;
-
- static const int kMemoryAlign;
- mutable Mutex mLock;
- LinkedList<chunk_t> mList;
- size_t mHeapSize;
-};
+class SimpleBestFitAllocator;
// ----------------------------------------------------------------------------
class MemoryDealer : public RefBase
{
public:
+ MemoryDealer(size_t size, const char* name = 0);
- enum {
- READ_ONLY = MemoryHeapBase::READ_ONLY,
- PAGE_ALIGNED = AllocatorInterface::PAGE_ALIGNED
- };
-
- // creates a memory dealer with the SharedHeap and SimpleBestFitAllocator
- MemoryDealer(size_t size, uint32_t flags = 0, const char* name = 0);
-
- // provide a custom heap but use the SimpleBestFitAllocator
- MemoryDealer(const sp<HeapInterface>& heap);
-
- // provide both custom heap and allocotar
- MemoryDealer(
- const sp<HeapInterface>& heap,
- const sp<AllocatorInterface>& allocator);
-
- virtual sp<IMemory> allocate(size_t size, uint32_t flags = 0);
+ virtual sp<IMemory> allocate(size_t size);
virtual void deallocate(size_t offset);
- virtual void dump(const char* what, uint32_t flags = 0) const;
-
+ virtual void dump(const char* what) const;
sp<IMemoryHeap> getMemoryHeap() const { return heap(); }
- sp<AllocatorInterface> getAllocator() const { return allocator(); }
protected:
virtual ~MemoryDealer();
-private:
- const sp<HeapInterface>& heap() const;
- const sp<AllocatorInterface>& allocator() const;
+private:
+ const sp<IMemoryHeap>& heap() const;
+ SimpleBestFitAllocator* allocator() const;
- class Allocation : public BnMemory {
- public:
- Allocation(const sp<MemoryDealer>& dealer,
- ssize_t offset, size_t size, const sp<IMemory>& memory);
- virtual ~Allocation();
- virtual sp<IMemoryHeap> getMemory(ssize_t* offset, size_t* size) const;
- private:
- sp<MemoryDealer> mDealer;
- ssize_t mOffset;
- size_t mSize;
- sp<IMemory> mMemory;
- };
-
- sp<HeapInterface> mHeap;
- sp<AllocatorInterface> mAllocator;
+ sp<IMemoryHeap> mHeap;
+ SimpleBestFitAllocator* mAllocator;
};
diff --git a/include/binder/MemoryHeapPmem.h b/include/binder/MemoryHeapPmem.h
index dbf26ff..aac164f 100644
--- a/include/binder/MemoryHeapPmem.h
+++ b/include/binder/MemoryHeapPmem.h
@@ -20,10 +20,10 @@
#include <stdlib.h>
#include <stdint.h>
-#include <binder/MemoryDealer.h>
#include <binder/MemoryHeapBase.h>
#include <binder/IMemory.h>
#include <utils/SortedVector.h>
+#include <utils/threads.h>
namespace android {
@@ -31,7 +31,7 @@
// ---------------------------------------------------------------------------
-class MemoryHeapPmem : public HeapInterface, public MemoryHeapBase
+class MemoryHeapPmem : public MemoryHeapBase
{
public:
class MemoryPmem : public BnMemory {
diff --git a/include/media/stagefright/AudioPlayer.h b/include/media/stagefright/AudioPlayer.h
index 71344e6..26fcc95 100644
--- a/include/media/stagefright/AudioPlayer.h
+++ b/include/media/stagefright/AudioPlayer.h
@@ -47,7 +47,7 @@
// Return time in us.
virtual int64_t getRealTimeUs();
- void start();
+ status_t start();
void pause();
void resume();
diff --git a/libs/audioflinger/AudioFlinger.cpp b/libs/audioflinger/AudioFlinger.cpp
index cad420a..9d52882 100644
--- a/libs/audioflinger/AudioFlinger.cpp
+++ b/libs/audioflinger/AudioFlinger.cpp
@@ -2929,7 +2929,7 @@
AudioFlinger::Client::Client(const sp<AudioFlinger>& audioFlinger, pid_t pid)
: RefBase(),
mAudioFlinger(audioFlinger),
- mMemoryDealer(new MemoryDealer(1024*1024)),
+ mMemoryDealer(new MemoryDealer(1024*1024, "AudioFlinger::Client")),
mPid(pid)
{
// 1 MB of address space is good for 32 tracks, 8 buffers each, 4 KB/buffer
diff --git a/libs/binder/MemoryDealer.cpp b/libs/binder/MemoryDealer.cpp
index d5ffe7f..18669f7 100644
--- a/libs/binder/MemoryDealer.cpp
+++ b/libs/binder/MemoryDealer.cpp
@@ -17,12 +17,13 @@
#define LOG_TAG "MemoryDealer"
#include <binder/MemoryDealer.h>
+#include <binder/IPCThreadState.h>
+#include <binder/MemoryBase.h>
#include <utils/Log.h>
-#include <binder/IPCThreadState.h>
#include <utils/SortedVector.h>
#include <utils/String8.h>
-#include <binder/MemoryBase.h>
+#include <utils/threads.h>
#include <stdint.h>
#include <stdio.h>
@@ -40,90 +41,203 @@
namespace android {
// ----------------------------------------------------------------------------
-HeapInterface::HeapInterface() { }
-HeapInterface::~HeapInterface() { }
+/*
+ * A simple templatized doubly linked-list implementation
+ */
-// ----------------------------------------------------------------------------
+template <typename NODE>
+class LinkedList
+{
+ NODE* mFirst;
+ NODE* mLast;
-AllocatorInterface::AllocatorInterface() { }
-AllocatorInterface::~AllocatorInterface() { }
-
-// ----------------------------------------------------------------------------
-
-class SimpleMemory : public MemoryBase {
public:
- SimpleMemory(const sp<IMemoryHeap>& heap, ssize_t offset, size_t size);
- virtual ~SimpleMemory();
+ LinkedList() : mFirst(0), mLast(0) { }
+ bool isEmpty() const { return mFirst == 0; }
+ NODE const* head() const { return mFirst; }
+ NODE* head() { return mFirst; }
+ NODE const* tail() const { return mLast; }
+ NODE* tail() { return mLast; }
+
+ void insertAfter(NODE* node, NODE* newNode) {
+ newNode->prev = node;
+ newNode->next = node->next;
+ if (node->next == 0) mLast = newNode;
+ else node->next->prev = newNode;
+ node->next = newNode;
+ }
+
+ void insertBefore(NODE* node, NODE* newNode) {
+ newNode->prev = node->prev;
+ newNode->next = node;
+ if (node->prev == 0) mFirst = newNode;
+ else node->prev->next = newNode;
+ node->prev = newNode;
+ }
+
+ void insertHead(NODE* newNode) {
+ if (mFirst == 0) {
+ mFirst = mLast = newNode;
+ newNode->prev = newNode->next = 0;
+ } else {
+ newNode->prev = 0;
+ newNode->next = mFirst;
+ mFirst->prev = newNode;
+ mFirst = newNode;
+ }
+ }
+
+ void insertTail(NODE* newNode) {
+ if (mLast == 0) {
+ insertHead(newNode);
+ } else {
+ newNode->prev = mLast;
+ newNode->next = 0;
+ mLast->next = newNode;
+ mLast = newNode;
+ }
+ }
+
+ NODE* remove(NODE* node) {
+ if (node->prev == 0) mFirst = node->next;
+ else node->prev->next = node->next;
+ if (node->next == 0) mLast = node->prev;
+ else node->next->prev = node->prev;
+ return node;
+ }
};
+// ----------------------------------------------------------------------------
+
+class Allocation : public MemoryBase {
+public:
+ Allocation(const sp<MemoryDealer>& dealer,
+ const sp<IMemoryHeap>& heap, ssize_t offset, size_t size);
+ virtual ~Allocation();
+private:
+ sp<MemoryDealer> mDealer;
+};
// ----------------------------------------------------------------------------
-MemoryDealer::Allocation::Allocation(
- const sp<MemoryDealer>& dealer, ssize_t offset, size_t size,
- const sp<IMemory>& memory)
- : mDealer(dealer), mOffset(offset), mSize(size), mMemory(memory)
+class SimpleBestFitAllocator
{
+ enum {
+ PAGE_ALIGNED = 0x00000001
+ };
+public:
+ SimpleBestFitAllocator(size_t size);
+ ~SimpleBestFitAllocator();
+
+ size_t allocate(size_t size, uint32_t flags = 0);
+ status_t deallocate(size_t offset);
+ size_t size() const;
+ void dump(const char* what) const;
+ void dump(String8& res, const char* what) const;
+
+private:
+
+ struct chunk_t {
+ chunk_t(size_t start, size_t size)
+ : start(start), size(size), free(1), prev(0), next(0) {
+ }
+ size_t start;
+ size_t size : 28;
+ int free : 4;
+ mutable chunk_t* prev;
+ mutable chunk_t* next;
+ };
+
+ ssize_t alloc(size_t size, uint32_t flags);
+ chunk_t* dealloc(size_t start);
+ void dump_l(const char* what) const;
+ void dump_l(String8& res, const char* what) const;
+
+ static const int kMemoryAlign;
+ mutable Mutex mLock;
+ LinkedList<chunk_t> mList;
+ size_t mHeapSize;
+};
+
+// ----------------------------------------------------------------------------
+
+Allocation::Allocation(
+ const sp<MemoryDealer>& dealer,
+ const sp<IMemoryHeap>& heap, ssize_t offset, size_t size)
+ : MemoryBase(heap, offset, size), mDealer(dealer)
+{
+#ifndef NDEBUG
+ void* const start_ptr = (void*)(intptr_t(heap->base()) + offset);
+ memset(start_ptr, 0xda, size);
+#endif
}
-MemoryDealer::Allocation::~Allocation()
+Allocation::~Allocation()
{
- if (mSize) {
+ size_t freedOffset = getOffset();
+ size_t freedSize = getSize();
+ if (freedSize) {
/* NOTE: it's VERY important to not free allocations of size 0 because
* they're special as they don't have any record in the allocator
* and could alias some real allocation (their offset is zero). */
- mDealer->deallocate(mOffset);
- }
-}
+ mDealer->deallocate(freedOffset);
-sp<IMemoryHeap> MemoryDealer::Allocation::getMemory(
- ssize_t* offset, size_t* size) const
-{
- return mMemory->getMemory(offset, size);
+ // keep the size to unmap in excess
+ size_t pagesize = getpagesize();
+ size_t start = freedOffset;
+ size_t end = start + freedSize;
+ start &= ~(pagesize-1);
+ end = (end + pagesize-1) & ~(pagesize-1);
+
+ // give back to the kernel the pages we don't need
+ size_t free_start = freedOffset;
+ size_t free_end = free_start + freedSize;
+ if (start < free_start)
+ start = free_start;
+ if (end > free_end)
+ end = free_end;
+ start = (start + pagesize-1) & ~(pagesize-1);
+ end &= ~(pagesize-1);
+
+ if (start < end) {
+ void* const start_ptr = (void*)(intptr_t(getHeap()->base()) + start);
+ size_t size = end-start;
+
+#ifndef NDEBUG
+ memset(start_ptr, 0xdf, size);
+#endif
+
+ // MADV_REMOVE is not defined on Dapper based Goobuntu
+#ifdef MADV_REMOVE
+ if (size) {
+ int err = madvise(start_ptr, size, MADV_REMOVE);
+ LOGW_IF(err, "madvise(%p, %u, MADV_REMOVE) returned %s",
+ start_ptr, size, err<0 ? strerror(errno) : "Ok");
+ }
+#endif
+ }
+ }
}
// ----------------------------------------------------------------------------
-MemoryDealer::MemoryDealer(size_t size, uint32_t flags, const char* name)
- : mHeap(new SharedHeap(size, flags, name)),
+MemoryDealer::MemoryDealer(size_t size, const char* name)
+ : mHeap(new MemoryHeapBase(size, 0, name)),
mAllocator(new SimpleBestFitAllocator(size))
{
}
-MemoryDealer::MemoryDealer(const sp<HeapInterface>& heap)
- : mHeap(heap),
- mAllocator(new SimpleBestFitAllocator(heap->virtualSize()))
-{
-}
-
-MemoryDealer::MemoryDealer( const sp<HeapInterface>& heap,
- const sp<AllocatorInterface>& allocator)
- : mHeap(heap), mAllocator(allocator)
-{
-}
-
MemoryDealer::~MemoryDealer()
{
+ delete mAllocator;
}
-sp<IMemory> MemoryDealer::allocate(size_t size, uint32_t flags)
+sp<IMemory> MemoryDealer::allocate(size_t size)
{
sp<IMemory> memory;
- const ssize_t offset = allocator()->allocate(size, flags);
+ const ssize_t offset = allocator()->allocate(size);
if (offset >= 0) {
- sp<IMemory> new_memory = heap()->mapMemory(offset, size);
- if (new_memory != 0) {
- memory = new Allocation(this, offset, size, new_memory);
- } else {
- LOGE("couldn't map [%8lx, %u]", offset, size);
- if (size) {
- /* NOTE: it's VERY important to not free allocations of size 0
- * because they're special as they don't have any record in the
- * allocator and could alias some real allocation
- * (their offset is zero). */
- allocator()->deallocate(offset);
- }
- }
+ memory = new Allocation(this, heap(), offset, size);
}
return memory;
}
@@ -133,16 +247,16 @@
allocator()->deallocate(offset);
}
-void MemoryDealer::dump(const char* what, uint32_t flags) const
+void MemoryDealer::dump(const char* what) const
{
- allocator()->dump(what, flags);
+ allocator()->dump(what);
}
-const sp<HeapInterface>& MemoryDealer::heap() const {
+const sp<IMemoryHeap>& MemoryDealer::heap() const {
return mHeap;
}
-const sp<AllocatorInterface>& MemoryDealer::allocator() const {
+SimpleBestFitAllocator* MemoryDealer::allocator() const {
return mAllocator;
}
@@ -287,28 +401,28 @@
return 0;
}
-void SimpleBestFitAllocator::dump(const char* what, uint32_t flags) const
+void SimpleBestFitAllocator::dump(const char* what) const
{
Mutex::Autolock _l(mLock);
- dump_l(what, flags);
+ dump_l(what);
}
-void SimpleBestFitAllocator::dump_l(const char* what, uint32_t flags) const
+void SimpleBestFitAllocator::dump_l(const char* what) const
{
String8 result;
- dump_l(result, what, flags);
+ dump_l(result, what);
LOGD("%s", result.string());
}
void SimpleBestFitAllocator::dump(String8& result,
- const char* what, uint32_t flags) const
+ const char* what) const
{
Mutex::Autolock _l(mLock);
- dump_l(result, what, flags);
+ dump_l(result, what);
}
void SimpleBestFitAllocator::dump_l(String8& result,
- const char* what, uint32_t flags) const
+ const char* what) const
{
size_t size = 0;
int32_t i = 0;
@@ -341,81 +455,10 @@
i++;
cur = cur->next;
}
- snprintf(buffer, SIZE, " size allocated: %u (%u KB)\n", int(size), int(size/1024));
+ snprintf(buffer, SIZE,
+ " size allocated: %u (%u KB)\n", int(size), int(size/1024));
result.append(buffer);
}
-
-// ----------------------------------------------------------------------------
-SharedHeap::SharedHeap()
- : HeapInterface(), MemoryHeapBase()
-{
-}
-
-SharedHeap::SharedHeap(size_t size, uint32_t flags, char const * name)
- : MemoryHeapBase(size, flags, name)
-{
-}
-
-SharedHeap::~SharedHeap()
-{
-}
-
-sp<IMemory> SharedHeap::mapMemory(size_t offset, size_t size)
-{
- return new SimpleMemory(this, offset, size);
-}
-
-
-SimpleMemory::SimpleMemory(const sp<IMemoryHeap>& heap,
- ssize_t offset, size_t size)
- : MemoryBase(heap, offset, size)
-{
-#ifndef NDEBUG
- void* const start_ptr = (void*)(intptr_t(heap->base()) + offset);
- memset(start_ptr, 0xda, size);
-#endif
-}
-
-SimpleMemory::~SimpleMemory()
-{
- size_t freedOffset = getOffset();
- size_t freedSize = getSize();
-
- // keep the size to unmap in excess
- size_t pagesize = getpagesize();
- size_t start = freedOffset;
- size_t end = start + freedSize;
- start &= ~(pagesize-1);
- end = (end + pagesize-1) & ~(pagesize-1);
-
- // give back to the kernel the pages we don't need
- size_t free_start = freedOffset;
- size_t free_end = free_start + freedSize;
- if (start < free_start)
- start = free_start;
- if (end > free_end)
- end = free_end;
- start = (start + pagesize-1) & ~(pagesize-1);
- end &= ~(pagesize-1);
-
- if (start < end) {
- void* const start_ptr = (void*)(intptr_t(getHeap()->base()) + start);
- size_t size = end-start;
-
-#ifndef NDEBUG
- memset(start_ptr, 0xdf, size);
-#endif
-
- // MADV_REMOVE is not defined on Dapper based Goobuntu
-#ifdef MADV_REMOVE
- if (size) {
- int err = madvise(start_ptr, size, MADV_REMOVE);
- LOGW_IF(err, "madvise(%p, %u, MADV_REMOVE) returned %s",
- start_ptr, size, err<0 ? strerror(errno) : "Ok");
- }
-#endif
- }
-}
}; // namespace android
diff --git a/libs/binder/MemoryHeapPmem.cpp b/libs/binder/MemoryHeapPmem.cpp
index c660947..16e92f9 100644
--- a/libs/binder/MemoryHeapPmem.cpp
+++ b/libs/binder/MemoryHeapPmem.cpp
@@ -127,7 +127,7 @@
MemoryHeapPmem::MemoryHeapPmem(const sp<MemoryHeapBase>& pmemHeap,
uint32_t flags)
- : HeapInterface(), MemoryHeapBase()
+ : MemoryHeapBase()
{
char const * const device = pmemHeap->getDevice();
#if HAVE_ANDROID_OS
diff --git a/media/java/android/media/MiniThumbFile.java b/media/java/android/media/MiniThumbFile.java
index f6e6317..df141c1 100644
--- a/media/java/android/media/MiniThumbFile.java
+++ b/media/java/android/media/MiniThumbFile.java
@@ -17,7 +17,6 @@
package android.media;
import android.graphics.Bitmap;
-import android.media.ThumbnailUtil;
import android.net.Uri;
import android.os.Environment;
import android.util.Log;
diff --git a/media/java/android/media/ThumbnailUtil.java b/media/java/android/media/ThumbnailUtils.java
similarity index 82%
rename from media/java/android/media/ThumbnailUtil.java
rename to media/java/android/media/ThumbnailUtils.java
index 0cf4e76..225d4b6 100644
--- a/media/java/android/media/ThumbnailUtil.java
+++ b/media/java/android/media/ThumbnailUtils.java
@@ -16,13 +16,6 @@
package android.media;
-import android.net.Uri;
-import android.os.ParcelFileDescriptor;
-import android.provider.BaseColumns;
-import android.provider.MediaStore.Images;
-import android.provider.MediaStore.Images.Thumbnails;
-import android.util.Log;
-
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
@@ -34,47 +27,171 @@
import android.graphics.Rect;
import android.media.MediaMetadataRetriever;
import android.media.MediaFile.MediaFileType;
+import android.net.Uri;
+import android.os.ParcelFileDescriptor;
+import android.provider.BaseColumns;
+import android.provider.MediaStore.Images;
+import android.provider.MediaStore.Images.Thumbnails;
+import android.util.Log;
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.OutputStream;
/**
- * Thumbnail generation routines for media provider. This class should only be used internaly.
- * {@hide} THIS IS NOT FOR PUBLIC API.
+ * Thumbnail generation routines for media provider.
*/
-public class ThumbnailUtil {
- private static final String TAG = "ThumbnailUtil";
- //Whether we should recycle the input (unless the output is the input).
- public static final boolean RECYCLE_INPUT = true;
- public static final boolean NO_RECYCLE_INPUT = false;
- public static final boolean ROTATE_AS_NEEDED = true;
- public static final boolean NO_ROTATE = false;
- public static final boolean USE_NATIVE = true;
- public static final boolean NO_NATIVE = false;
+public class ThumbnailUtils {
+ private static final String TAG = "ThumbnailUtils";
- public static final int THUMBNAIL_TARGET_SIZE = 320;
- public static final int MINI_THUMB_TARGET_SIZE = 96;
- public static final int THUMBNAIL_MAX_NUM_PIXELS = 512 * 384;
- public static final int MINI_THUMB_MAX_NUM_PIXELS = 128 * 128;
- public static final int UNCONSTRAINED = -1;
+ /* Maximum pixels size for created bitmap. */
+ private static final int THUMBNAIL_MAX_NUM_PIXELS = 512 * 384;
+ private static final int MINI_THUMB_MAX_NUM_PIXELS = 128 * 128;
+ private static final int UNCONSTRAINED = -1;
- // Returns Options that set the native alloc flag for Bitmap decode.
- public static BitmapFactory.Options createNativeAllocOptions() {
- BitmapFactory.Options options = new BitmapFactory.Options();
- options.inNativeAlloc = true;
- return options;
- }
+ /* Whether we should rotate the resulting bitmap. */
+ private static final boolean ROTATE_AS_NEEDED = true;
+ private static final boolean NO_ROTATE = false;
+
+ /* Whether we should create bitmap in native memory. */
+ private static final boolean USE_NATIVE = true;
+ private static final boolean NO_NATIVE = false;
+
/**
- * Make a bitmap from a given Uri.
- *
- * @param uri
+ * Constant used to indicate we should recycle the input in
+ * {@link #extractMiniThumb(Bitmap, int, int, boolean)} unless the output is the input.
*/
- public static Bitmap makeBitmap(int minSideLength, int maxNumOfPixels,
- Uri uri, ContentResolver cr) {
- return makeBitmap(minSideLength, maxNumOfPixels, uri, cr,
- NO_NATIVE);
+ public static final boolean RECYCLE_INPUT = true;
+
+ /**
+ * Constant used to indicate we should not recycle the input in
+ * {@link #extractMiniThumb(Bitmap, int, int, boolean)}.
+ */
+ public static final boolean NO_RECYCLE_INPUT = false;
+
+ /**
+ * Constant used to indicate the dimension of normal thumbnail in
+ * {@link #extractMiniThumb(Bitmap, int, int, boolean)}.
+ */
+ public static final int THUMBNAIL_TARGET_SIZE = 320;
+
+ /**
+ * Constant used to indicate the dimension of mini thumbnail in
+ * {@link #extractMiniThumb(Bitmap, int, int, boolean)}.
+ */
+ public static final int MINI_THUMB_TARGET_SIZE = 96;
+
+ /**
+ * This method first examines if the thumbnail embedded in EXIF is bigger than our target
+ * size. If not, then it'll create a thumbnail from original image. Due to efficiency
+ * consideration, we want to let MediaThumbRequest avoid calling this method twice for
+ * both kinds, so it only requests for MICRO_KIND and set saveImage to true.
+ *
+ * This method always returns a "square thumbnail" for MICRO_KIND thumbnail.
+ *
+ * @param cr ContentResolver
+ * @param filePath file path needed by EXIF interface
+ * @param uri URI of original image
+ * @param origId image id
+ * @param kind either MINI_KIND or MICRO_KIND
+ * @param saveMini Whether to save MINI_KIND thumbnail obtained in this method.
+ * @return Bitmap
+ */
+ public static Bitmap createImageThumbnail(ContentResolver cr, String filePath, Uri uri,
+ long origId, int kind, boolean saveMini) {
+ boolean wantMini = (kind == Images.Thumbnails.MINI_KIND || saveMini);
+ int targetSize = wantMini ?
+ THUMBNAIL_TARGET_SIZE : MINI_THUMB_TARGET_SIZE;
+ int maxPixels = wantMini ?
+ THUMBNAIL_MAX_NUM_PIXELS : MINI_THUMB_MAX_NUM_PIXELS;
+ SizedThumbnailBitmap sizedThumbnailBitmap = new SizedThumbnailBitmap();
+ Bitmap bitmap = null;
+ MediaFileType fileType = MediaFile.getFileType(filePath);
+ if (fileType != null && fileType.fileType == MediaFile.FILE_TYPE_JPEG) {
+ createThumbnailFromEXIF(filePath, targetSize, maxPixels, sizedThumbnailBitmap);
+ bitmap = sizedThumbnailBitmap.mBitmap;
+ }
+
+ if (bitmap == null) {
+ bitmap = makeBitmap(targetSize, maxPixels, uri, cr);
+ }
+
+ if (bitmap == null) {
+ return null;
+ }
+
+ if (saveMini) {
+ if (sizedThumbnailBitmap.mThumbnailData != null) {
+ storeThumbnail(cr, origId,
+ sizedThumbnailBitmap.mThumbnailData,
+ sizedThumbnailBitmap.mThumbnailWidth,
+ sizedThumbnailBitmap.mThumbnailHeight);
+ } else {
+ storeThumbnail(cr, origId, bitmap);
+ }
+ }
+
+ if (kind == Images.Thumbnails.MICRO_KIND) {
+ // now we make it a "square thumbnail" for MICRO_KIND thumbnail
+ bitmap = extractMiniThumb(bitmap,
+ MINI_THUMB_TARGET_SIZE,
+ MINI_THUMB_TARGET_SIZE, RECYCLE_INPUT);
+ }
+ return bitmap;
+ }
+
+ /**
+ * Create a video thumbnail for a video. May return null if the video is
+ * corrupt.
+ *
+ * @param filePath
+ */
+ public static Bitmap createVideoThumbnail(String filePath) {
+ Bitmap bitmap = null;
+ MediaMetadataRetriever retriever = new MediaMetadataRetriever();
+ try {
+ retriever.setMode(MediaMetadataRetriever.MODE_CAPTURE_FRAME_ONLY);
+ retriever.setDataSource(filePath);
+ bitmap = retriever.captureFrame();
+ } catch (IllegalArgumentException ex) {
+ // Assume this is a corrupt video file
+ } catch (RuntimeException ex) {
+ // Assume this is a corrupt video file.
+ } finally {
+ try {
+ retriever.release();
+ } catch (RuntimeException ex) {
+ // Ignore failures while cleaning up.
+ }
+ }
+ return bitmap;
+ }
+
+ /**
+ * Creates a centered bitmap of the desired size.
+ *
+ * @param source original bitmap source
+ * @param width targeted width
+ * @param height targeted height
+ * @param recycle whether we want to recycle the input
+ */
+ public static Bitmap extractMiniThumb(
+ Bitmap source, int width, int height, boolean recycle) {
+ if (source == null) {
+ return null;
+ }
+
+ float scale;
+ if (source.getWidth() < source.getHeight()) {
+ scale = width / (float) source.getWidth();
+ } else {
+ scale = height / (float) source.getHeight();
+ }
+ Matrix matrix = new Matrix();
+ matrix.setScale(scale, scale);
+ Bitmap miniThumbnail = transform(matrix, source, width, height, true, recycle);
+ return miniThumbnail;
}
/*
@@ -96,7 +213,7 @@
* For example, BitmapFactory downsamples an image by 2 even though the
* request is 3. So we round up the sample size to avoid OOM.
*/
- public static int computeSampleSize(BitmapFactory.Options options,
+ private static int computeSampleSize(BitmapFactory.Options options,
int minSideLength, int maxNumOfPixels) {
int initialSize = computeInitialSampleSize(options, minSideLength,
maxNumOfPixels);
@@ -140,7 +257,30 @@
}
}
- public static Bitmap makeBitmap(int minSideLength, int maxNumOfPixels,
+ /**
+ * Returns Options that set the native alloc flag for Bitmap decode.
+ */
+ private static BitmapFactory.Options createNativeAllocOptions() {
+ BitmapFactory.Options options = new BitmapFactory.Options();
+ options.inNativeAlloc = true;
+ return options;
+ }
+
+ /**
+ * Make a bitmap from a given Uri, minimal side length, and maximum number of pixels.
+ */
+ private static Bitmap makeBitmap(int minSideLength, int maxNumOfPixels,
+ Uri uri, ContentResolver cr) {
+ return makeBitmap(minSideLength, maxNumOfPixels, uri, cr,
+ NO_NATIVE);
+ }
+
+ /**
+ * Make a bitmap from a given Uri, minimal side length, and maximum number of pixels.
+ * The image data will be read from specified ContentResolver and clients are allowed to specify
+ * whether they want the Bitmap be created in native memory.
+ */
+ private static Bitmap makeBitmap(int minSideLength, int maxNumOfPixels,
Uri uri, ContentResolver cr, boolean useNative) {
ParcelFileDescriptor input = null;
try {
@@ -159,9 +299,52 @@
}
}
- // Rotates the bitmap by the specified degree.
- // If a new bitmap is created, the original bitmap is recycled.
- public static Bitmap rotate(Bitmap b, int degrees) {
+ /**
+ * Make a bitmap from a given Uri, minimal side length, and maximum number of pixels.
+ * The image data will be read from specified pfd if it's not null, otherwise
+ * a new input stream will be created using specified ContentResolver.
+ *
+ * Clients are allowed to pass their own BitmapFactory.Options used for bitmap decoding. A
+ * new BitmapFactory.Options will be created if options is null.
+ */
+ private static Bitmap makeBitmap(int minSideLength, int maxNumOfPixels,
+ Uri uri, ContentResolver cr, ParcelFileDescriptor pfd,
+ BitmapFactory.Options options) {
+ Bitmap b = null;
+ try {
+ if (pfd == null) pfd = makeInputStream(uri, cr);
+ if (pfd == null) return null;
+ if (options == null) options = new BitmapFactory.Options();
+
+ FileDescriptor fd = pfd.getFileDescriptor();
+ options.inSampleSize = 1;
+ options.inJustDecodeBounds = true;
+ BitmapFactory.decodeFileDescriptor(fd, null, options);
+ if (options.mCancel || options.outWidth == -1
+ || options.outHeight == -1) {
+ return null;
+ }
+ options.inSampleSize = computeSampleSize(
+ options, minSideLength, maxNumOfPixels);
+ options.inJustDecodeBounds = false;
+
+ options.inDither = false;
+ options.inPreferredConfig = Bitmap.Config.ARGB_8888;
+ b = BitmapFactory.decodeFileDescriptor(fd, null, options);
+ } catch (OutOfMemoryError ex) {
+ Log.e(TAG, "Got oom exception ", ex);
+ return null;
+ } finally {
+ closeSilently(pfd);
+ }
+ return b;
+ }
+
+ /**
+ * Rotates the bitmap by the specified degree.
+ * If a new bitmap is created, the original bitmap is recycled.
+ */
+ private static Bitmap rotate(Bitmap b, int degrees) {
if (degrees != 0 && b != null) {
Matrix m = new Matrix();
m.setRotate(degrees,
@@ -198,149 +381,10 @@
}
}
- public static Bitmap makeBitmap(int minSideLength, int maxNumOfPixels,
- Uri uri, ContentResolver cr, ParcelFileDescriptor pfd,
- BitmapFactory.Options options) {
- Bitmap b = null;
- try {
- if (pfd == null) pfd = makeInputStream(uri, cr);
- if (pfd == null) return null;
- if (options == null) options = new BitmapFactory.Options();
-
- FileDescriptor fd = pfd.getFileDescriptor();
- options.inSampleSize = 1;
- options.inJustDecodeBounds = true;
- BitmapFactory.decodeFileDescriptor(fd, null, options);
- if (options.mCancel || options.outWidth == -1
- || options.outHeight == -1) {
- return null;
- }
- options.inSampleSize = computeSampleSize(
- options, minSideLength, maxNumOfPixels);
- options.inJustDecodeBounds = false;
-
- options.inDither = false;
- options.inPreferredConfig = Bitmap.Config.ARGB_8888;
- b = BitmapFactory.decodeFileDescriptor(fd, null, options);
- } catch (OutOfMemoryError ex) {
- Log.e(TAG, "Got oom exception ", ex);
- return null;
- } finally {
- closeSilently(pfd);
- }
- return b;
- }
-
/**
- * Creates a centered bitmap of the desired size.
- * @param source
- * @param recycle whether we want to recycle the input
+ * Transform source Bitmap to targeted width and height.
*/
- public static Bitmap extractMiniThumb(
- Bitmap source, int width, int height, boolean recycle) {
- if (source == null) {
- return null;
- }
-
- float scale;
- if (source.getWidth() < source.getHeight()) {
- scale = width / (float) source.getWidth();
- } else {
- scale = height / (float) source.getHeight();
- }
- Matrix matrix = new Matrix();
- matrix.setScale(scale, scale);
- Bitmap miniThumbnail = transform(matrix, source, width, height, true, recycle);
- return miniThumbnail;
- }
-
- /**
- * Create a video thumbnail for a video. May return null if the video is
- * corrupt.
- *
- * @param filePath
- */
- public static Bitmap createVideoThumbnail(String filePath) {
- Bitmap bitmap = null;
- MediaMetadataRetriever retriever = new MediaMetadataRetriever();
- try {
- retriever.setMode(MediaMetadataRetriever.MODE_CAPTURE_FRAME_ONLY);
- retriever.setDataSource(filePath);
- bitmap = retriever.captureFrame();
- } catch (IllegalArgumentException ex) {
- // Assume this is a corrupt video file
- } catch (RuntimeException ex) {
- // Assume this is a corrupt video file.
- } finally {
- try {
- retriever.release();
- } catch (RuntimeException ex) {
- // Ignore failures while cleaning up.
- }
- }
- return bitmap;
- }
-
- /**
- * This method first examines if the thumbnail embedded in EXIF is bigger than our target
- * size. If not, then it'll create a thumbnail from original image. Due to efficiency
- * consideration, we want to let MediaThumbRequest avoid calling this method twice for
- * both kinds, so it only requests for MICRO_KIND and set saveImage to true.
- *
- * This method always returns a "square thumbnail" for MICRO_KIND thumbnail.
- *
- * @param cr ContentResolver
- * @param filePath file path needed by EXIF interface
- * @param uri URI of original image
- * @param origId image id
- * @param kind either MINI_KIND or MICRO_KIND
- * @param saveMini Whether to save MINI_KIND thumbnail obtained in this method.
- * @return Bitmap
- */
- public static Bitmap createImageThumbnail(ContentResolver cr, String filePath, Uri uri,
- long origId, int kind, boolean saveMini) {
- boolean wantMini = (kind == Images.Thumbnails.MINI_KIND || saveMini);
- int targetSize = wantMini ?
- ThumbnailUtil.THUMBNAIL_TARGET_SIZE : ThumbnailUtil.MINI_THUMB_TARGET_SIZE;
- int maxPixels = wantMini ?
- ThumbnailUtil.THUMBNAIL_MAX_NUM_PIXELS : ThumbnailUtil.MINI_THUMB_MAX_NUM_PIXELS;
- SizedThumbnailBitmap sizedThumbnailBitmap = new SizedThumbnailBitmap();
- Bitmap bitmap = null;
- MediaFileType fileType = MediaFile.getFileType(filePath);
- if (fileType != null && fileType.fileType == MediaFile.FILE_TYPE_JPEG) {
- createThumbnailFromEXIF(filePath, targetSize, maxPixels, sizedThumbnailBitmap);
- bitmap = sizedThumbnailBitmap.mBitmap;
- }
-
- if (bitmap == null) {
- bitmap = ThumbnailUtil.makeBitmap(targetSize, maxPixels, uri, cr);
- }
-
- if (bitmap == null) {
- return null;
- }
-
- if (saveMini) {
- if (sizedThumbnailBitmap.mThumbnailData != null) {
- ThumbnailUtil.storeThumbnail(cr, origId,
- sizedThumbnailBitmap.mThumbnailData,
- sizedThumbnailBitmap.mThumbnailWidth,
- sizedThumbnailBitmap.mThumbnailHeight);
- } else {
- ThumbnailUtil.storeThumbnail(cr, origId, bitmap);
- }
- }
-
- if (kind == Images.Thumbnails.MICRO_KIND) {
- // now we make it a "square thumbnail" for MICRO_KIND thumbnail
- bitmap = ThumbnailUtil.extractMiniThumb(bitmap,
- ThumbnailUtil.MINI_THUMB_TARGET_SIZE,
- ThumbnailUtil.MINI_THUMB_TARGET_SIZE, ThumbnailUtil.RECYCLE_INPUT);
- }
- return bitmap;
- }
-
- public static Bitmap transform(Matrix scaler,
+ private static Bitmap transform(Matrix scaler,
Bitmap source,
int targetWidth,
int targetHeight,
@@ -441,10 +485,6 @@
/**
* Look up thumbnail uri by given imageId, it will be automatically created if it's not created
* yet. Most of the time imageId is identical to thumbId, but it's not always true.
- * @param req
- * @param width
- * @param height
- * @return Uri Thumbnail uri
*/
private static Uri getImageThumbnailUri(ContentResolver cr, long origId, int width, int height) {
Uri thumbUri = Images.Thumbnails.EXTERNAL_CONTENT_URI;
@@ -513,10 +553,14 @@
}
}
- // SizedThumbnailBitmap contains the bitmap, which is downsampled either from
- // the thumbnail in exif or the full image.
- // mThumbnailData, mThumbnailWidth and mThumbnailHeight are set together only if mThumbnail is not null.
- // The width/height of the sized bitmap may be different from mThumbnailWidth/mThumbnailHeight.
+ /**
+ * SizedThumbnailBitmap contains the bitmap, which is downsampled either from
+ * the thumbnail in exif or the full image.
+ * mThumbnailData, mThumbnailWidth and mThumbnailHeight are set together only if mThumbnail
+ * is not null.
+ *
+ * The width/height of the sized bitmap may be different from mThumbnailWidth/mThumbnailHeight.
+ */
private static class SizedThumbnailBitmap {
public byte[] mThumbnailData;
public Bitmap mBitmap;
@@ -524,9 +568,11 @@
public int mThumbnailHeight;
}
- // Creates a bitmap by either downsampling from the thumbnail in EXIF or the full image.
- // The functions returns a SizedThumbnailBitmap,
- // which contains a downsampled bitmap and the thumbnail data in EXIF if exists.
+ /**
+ * Creates a bitmap by either downsampling from the thumbnail in EXIF or the full image.
+ * The functions returns a SizedThumbnailBitmap,
+ * which contains a downsampled bitmap and the thumbnail data in EXIF if exists.
+ */
private static void createThumbnailFromEXIF(String filePath, int targetSize,
int maxPixels, SizedThumbnailBitmap sizedThumbBitmap) {
if (filePath == null) return;
diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp
index f4165ff..7bbd0b2 100644
--- a/media/libmedia/AudioRecord.cpp
+++ b/media/libmedia/AudioRecord.cpp
@@ -32,7 +32,6 @@
#include <binder/IServiceManager.h>
#include <utils/Log.h>
-#include <binder/MemoryDealer.h>
#include <binder/Parcel.h>
#include <binder/IPCThreadState.h>
#include <utils/Timers.h>
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index ad0f42e..74852dc 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -32,7 +32,6 @@
#include <media/AudioTrack.h>
#include <utils/Log.h>
-#include <binder/MemoryDealer.h>
#include <binder/Parcel.h>
#include <binder/IPCThreadState.h>
#include <utils/Timers.h>
diff --git a/media/libmediaplayerservice/MetadataRetrieverClient.cpp b/media/libmediaplayerservice/MetadataRetrieverClient.cpp
index 66de2ee..162bebb 100644
--- a/media/libmediaplayerservice/MetadataRetrieverClient.cpp
+++ b/media/libmediaplayerservice/MetadataRetrieverClient.cpp
@@ -253,7 +253,7 @@
return NULL;
}
size_t size = sizeof(VideoFrame) + frame->mSize;
- mThumbnailDealer = new MemoryDealer(size);
+ mThumbnailDealer = new MemoryDealer(size, "MetadataRetrieverClient");
if (mThumbnailDealer == NULL) {
LOGE("failed to create MemoryDealer");
delete frame;
@@ -294,7 +294,7 @@
return NULL;
}
size_t size = sizeof(MediaAlbumArt) + albumArt->mSize;
- mAlbumArtDealer = new MemoryDealer(size);
+ mAlbumArtDealer = new MemoryDealer(size, "MetadataRetrieverClient");
if (mAlbumArtDealer == NULL) {
LOGE("failed to create MemoryDealer object");
delete albumArt;
diff --git a/media/libstagefright/AudioPlayer.cpp b/media/libstagefright/AudioPlayer.cpp
index 14842c0..efe7ebb 100644
--- a/media/libstagefright/AudioPlayer.cpp
+++ b/media/libstagefright/AudioPlayer.cpp
@@ -58,12 +58,15 @@
mSource = source;
}
-void AudioPlayer::start() {
+status_t AudioPlayer::start() {
CHECK(!mStarted);
CHECK(mSource != NULL);
status_t err = mSource->start();
- CHECK_EQ(err, OK);
+
+ if (err != OK) {
+ return err;
+ }
sp<MetaData> format = mSource->getFormat();
const char *mime;
@@ -83,7 +86,11 @@
mSampleRate, numChannels, AudioSystem::PCM_16_BIT,
DEFAULT_AUDIOSINK_BUFFERCOUNT,
&AudioPlayer::AudioSinkCallback, this);
- CHECK_EQ(err, OK);
+ if (err != OK) {
+ mSource->stop();
+
+ return err;
+ }
mLatencyUs = (int64_t)mAudioSink->latency() * 1000;
mFrameSize = mAudioSink->frameSize();
@@ -97,7 +104,14 @@
: AudioSystem::CHANNEL_OUT_MONO,
8192, 0, &AudioCallback, this, 0);
- CHECK_EQ(mAudioTrack->initCheck(), OK);
+ if (mAudioTrack->initCheck() != OK) {
+ delete mAudioTrack;
+ mAudioTrack = NULL;
+
+ mSource->stop();
+
+ return mAudioTrack->initCheck();
+ }
mLatencyUs = (int64_t)mAudioTrack->latency() * 1000;
mFrameSize = mAudioTrack->frameSize();
@@ -106,6 +120,8 @@
}
mStarted = true;
+
+ return OK;
}
void AudioPlayer::pause() {
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index 85019aa..4e7738e 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -378,7 +378,16 @@
&AwesomePlayer::AudioNotify, this);
mAudioPlayer->setSource(mAudioSource);
- mAudioPlayer->start();
+ status_t err = mAudioPlayer->start();
+
+ if (err != OK) {
+ delete mAudioPlayer;
+ mAudioPlayer = NULL;
+
+ mFlags &= ~(PLAYING | FIRST_FRAME);
+
+ return err;
+ }
delete mTimeSource;
mTimeSource = mAudioPlayer;
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index 5370c39..6274a6c 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -28,6 +28,7 @@
#include <string.h>
#include <media/stagefright/DataSource.h>
+#include "include/ESDS.h"
#include <media/stagefright/MediaBuffer.h>
#include <media/stagefright/MediaBufferGroup.h>
#include <media/stagefright/MediaDebug.h>
@@ -898,6 +899,21 @@
mLastTrack->meta->setData(
kKeyESDS, kTypeESDS, &buffer[4], chunk_data_size - 4);
+ if (mPath.size() >= 2
+ && mPath[mPath.size() - 2] == FOURCC('m', 'p', '4', 'a')) {
+ // Information from the ESDS must be relied on for proper
+ // setup of sample rate and channel count for MPEG4 Audio.
+ // The generic header appears to only contain generic
+ // information...
+
+ status_t err = updateAudioTrackInfoFromESDS_MPEG4Audio(
+ &buffer[4], chunk_data_size - 4);
+
+ if (err != OK) {
+ return err;
+ }
+ }
+
*offset += chunk_size;
break;
}
@@ -1121,6 +1137,86 @@
track->meta, mDataSource, track->timescale, track->sampleTable);
}
+status_t MPEG4Extractor::updateAudioTrackInfoFromESDS_MPEG4Audio(
+ const void *esds_data, size_t esds_size) {
+ ESDS esds(esds_data, esds_size);
+ const uint8_t *csd;
+ size_t csd_size;
+ if (esds.getCodecSpecificInfo(
+ (const void **)&csd, &csd_size) != OK) {
+ return ERROR_MALFORMED;
+ }
+
+#if 0
+ printf("ESD of size %d\n", csd_size);
+ hexdump(csd, csd_size);
+#endif
+
+ if (csd_size < 2) {
+ return ERROR_MALFORMED;
+ }
+
+ uint32_t objectType = csd[0] >> 3;
+
+ if (objectType == 31) {
+ return ERROR_UNSUPPORTED;
+ }
+
+ uint32_t freqIndex = (csd[0] & 7) << 1 | (csd[1] >> 7);
+ int32_t sampleRate = 0;
+ int32_t numChannels = 0;
+ if (freqIndex == 15) {
+ if (csd_size < 5) {
+ return ERROR_MALFORMED;
+ }
+
+ sampleRate = (csd[1] & 0x7f) << 17
+ | csd[2] << 9
+ | csd[3] << 1
+ | (csd[4] >> 7);
+
+ numChannels = (csd[4] >> 3) & 15;
+ } else {
+ static uint32_t kSamplingRate[] = {
+ 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
+ 16000, 12000, 11025, 8000, 7350
+ };
+
+ if (freqIndex == 13 || freqIndex == 14) {
+ return ERROR_MALFORMED;
+ }
+
+ sampleRate = kSamplingRate[freqIndex];
+ numChannels = (csd[1] >> 3) & 15;
+ }
+
+ if (numChannels == 0) {
+ return ERROR_UNSUPPORTED;
+ }
+
+ int32_t prevSampleRate;
+ CHECK(mLastTrack->meta->findInt32(kKeySampleRate, &prevSampleRate));
+
+ if (prevSampleRate != sampleRate) {
+ LOGW("mpeg4 audio sample rate different from previous setting. "
+ "was: %d, now: %d", prevSampleRate, sampleRate);
+ }
+
+ mLastTrack->meta->setInt32(kKeySampleRate, sampleRate);
+
+ int32_t prevChannelCount;
+ CHECK(mLastTrack->meta->findInt32(kKeyChannelCount, &prevChannelCount));
+
+ if (prevChannelCount != numChannels) {
+ LOGW("mpeg4 audio channel count different from previous setting. "
+ "was: %d, now: %d", prevChannelCount, numChannels);
+ }
+
+ mLastTrack->meta->setInt32(kKeyChannelCount, numChannels);
+
+ return OK;
+}
+
////////////////////////////////////////////////////////////////////////////////
MPEG4Source::MPEG4Source(
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 986dcb2..e17fbb8 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -1183,7 +1183,7 @@
}
size_t totalSize = def.nBufferCountActual * def.nBufferSize;
- mDealer[portIndex] = new MemoryDealer(totalSize);
+ mDealer[portIndex] = new MemoryDealer(totalSize, "OMXCodec");
for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) {
sp<IMemory> mem = mDealer[portIndex]->allocate(def.nBufferSize);
diff --git a/media/libstagefright/WAVExtractor.cpp b/media/libstagefright/WAVExtractor.cpp
index da8fe79..7365dfa 100644
--- a/media/libstagefright/WAVExtractor.cpp
+++ b/media/libstagefright/WAVExtractor.cpp
@@ -178,7 +178,8 @@
mBitsPerSample = U16_LE_AT(&formatSpec[14]);
- if (mBitsPerSample != 8 && mBitsPerSample != 16) {
+ if (mBitsPerSample != 8 && mBitsPerSample != 16
+ && mBitsPerSample != 24) {
return ERROR_UNSUPPORTED;
}
@@ -329,6 +330,24 @@
buffer->release();
buffer = tmp;
+ } else if (mBitsPerSample == 24) {
+ // Convert 24-bit signed samples to 16-bit signed.
+
+ const uint8_t *src =
+ (const uint8_t *)buffer->data() + buffer->range_offset();
+ int16_t *dst = (int16_t *)src;
+
+ size_t numSamples = buffer->range_length() / 3;
+ for (size_t i = 0; i < numSamples; ++i) {
+ int32_t x = (int32_t)(src[0] | src[1] << 8 | src[2] << 16);
+ x = (x << 8) >> 8; // sign extension
+
+ x = x >> 8;
+ *dst++ = (int16_t)x;
+ src += 3;
+ }
+
+ buffer->set_range(buffer->range_offset(), 2 * numSamples);
}
size_t bytesPerSample = mBitsPerSample >> 3;
diff --git a/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp b/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp
index 36272ea..aa2a3d1 100644
--- a/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp
+++ b/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp
@@ -322,8 +322,10 @@
crop_top = crop_left = 0;
}
- mFormat->setInt32(kKeyWidth, crop_right - crop_left + 1);
- mFormat->setInt32(kKeyHeight, crop_bottom - crop_top + 1);
+ int32_t aligned_width = (crop_right - crop_left + 1 + 15) & ~15;
+ int32_t aligned_height = (crop_bottom - crop_top + 1 + 15) & ~15;
+ mFormat->setInt32(kKeyWidth, aligned_width);
+ mFormat->setInt32(kKeyHeight, aligned_height);
mInputBuffer->release();
mInputBuffer = NULL;
diff --git a/media/libstagefright/include/MPEG4Extractor.h b/media/libstagefright/include/MPEG4Extractor.h
index 1a13446..3a63e88 100644
--- a/media/libstagefright/include/MPEG4Extractor.h
+++ b/media/libstagefright/include/MPEG4Extractor.h
@@ -65,6 +65,9 @@
status_t parseChunk(off_t *offset, int depth);
status_t parseMetaData(off_t offset, size_t size);
+ status_t updateAudioTrackInfoFromESDS_MPEG4Audio(
+ const void *esds_data, size_t esds_size);
+
MPEG4Extractor(const MPEG4Extractor &);
MPEG4Extractor &operator=(const MPEG4Extractor &);
};
diff --git a/media/libstagefright/omx/tests/OMXHarness.cpp b/media/libstagefright/omx/tests/OMXHarness.cpp
index 6c36163..51fcaf5 100644
--- a/media/libstagefright/omx/tests/OMXHarness.cpp
+++ b/media/libstagefright/omx/tests/OMXHarness.cpp
@@ -286,7 +286,7 @@
return OK;
}
- sp<MemoryDealer> dealer = new MemoryDealer(8 * 1024 * 1024);
+ sp<MemoryDealer> dealer = new MemoryDealer(8 * 1024 * 1024, "OMXHarness");
IOMX::node_id node;
status_t err =
diff --git a/opengl/java/com/google/android/gles_jni/GLImpl.java b/opengl/java/com/google/android/gles_jni/GLImpl.java
index 01a9c91..30b9325 100644
--- a/opengl/java/com/google/android/gles_jni/GLImpl.java
+++ b/opengl/java/com/google/android/gles_jni/GLImpl.java
@@ -48,6 +48,12 @@
Buffer _pointSizePointerOES = null;
Buffer _matrixIndexPointerOES = null;
Buffer _weightPointerOES = null;
+
+ private boolean haveCheckedExtensions;
+ private boolean have_OES_blend_equation_separate;
+ private boolean have_OES_blend_subtract;
+ private boolean have_OES_framebuffer_object;
+ private boolean have_OES_texture_cube_map;
public GLImpl() {
}
@@ -1935,7 +1941,7 @@
int target
);
- // C function void glDeleteFramebuffersOES ( GLint n, GLint *framebuffers )
+ // C function void glDeleteFramebuffersOES ( GLint n, GLuint *framebuffers )
public native void glDeleteFramebuffersOES(
int n,
@@ -1943,14 +1949,14 @@
int offset
);
- // C function void glDeleteFramebuffersOES ( GLint n, GLint *framebuffers )
+ // C function void glDeleteFramebuffersOES ( GLint n, GLuint *framebuffers )
public native void glDeleteFramebuffersOES(
int n,
java.nio.IntBuffer framebuffers
);
- // C function void glDeleteRenderbuffersOES ( GLint n, GLint *renderbuffers )
+ // C function void glDeleteRenderbuffersOES ( GLint n, GLuint *renderbuffers )
public native void glDeleteRenderbuffersOES(
int n,
@@ -1958,7 +1964,7 @@
int offset
);
- // C function void glDeleteRenderbuffersOES ( GLint n, GLint *renderbuffers )
+ // C function void glDeleteRenderbuffersOES ( GLint n, GLuint *renderbuffers )
public native void glDeleteRenderbuffersOES(
int n,
@@ -1990,7 +1996,7 @@
int target
);
- // C function void glGenFramebuffersOES ( GLint n, GLint *framebuffers )
+ // C function void glGenFramebuffersOES ( GLint n, GLuint *framebuffers )
public native void glGenFramebuffersOES(
int n,
@@ -1998,14 +2004,14 @@
int offset
);
- // C function void glGenFramebuffersOES ( GLint n, GLint *framebuffers )
+ // C function void glGenFramebuffersOES ( GLint n, GLuint *framebuffers )
public native void glGenFramebuffersOES(
int n,
java.nio.IntBuffer framebuffers
);
- // C function void glGenRenderbuffersOES ( GLint n, GLint *renderbuffers )
+ // C function void glGenRenderbuffersOES ( GLint n, GLuint *renderbuffers )
public native void glGenRenderbuffersOES(
int n,
@@ -2013,7 +2019,7 @@
int offset
);
- // C function void glGenRenderbuffersOES ( GLint n, GLint *renderbuffers )
+ // C function void glGenRenderbuffersOES ( GLint n, GLuint *renderbuffers )
public native void glGenRenderbuffersOES(
int n,
diff --git a/opengl/tools/glgen/specs/jsr239/glspec-1.1extpack b/opengl/tools/glgen/specs/jsr239/glspec-1.1extpack
index ca9e6d2..d6012d9 100644
--- a/opengl/tools/glgen/specs/jsr239/glspec-1.1extpack
+++ b/opengl/tools/glgen/specs/jsr239/glspec-1.1extpack
@@ -7,14 +7,14 @@
GLint glCheckFramebufferStatusOES ( GLint target )
void glCompressedTexImage2D ( GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data )
void glCopyTexImage2D ( GLint target, GLint level, GLint internalformat, GLint x, GLint y, GLint width, GLint height, GLint border )
-void glDeleteFramebuffersOES ( GLint n, GLint *framebuffers )
-void glDeleteRenderbuffersOES ( GLint n, GLint *renderbuffers )
+void glDeleteFramebuffersOES ( GLint n, GLuint *framebuffers )
+void glDeleteRenderbuffersOES ( GLint n, GLuint *renderbuffers )
void glEnable ( GLint cap )
void glFramebufferRenderbufferOES ( GLint target, GLint attachment, GLint renderbuffertarget, GLint renderbuffer )
void glFramebufferTexture2DOES ( GLint target, GLint attachment, GLint textarget, GLint texture, GLint level )
void glGenerateMipmapOES ( GLint target )
-void glGenFramebuffersOES ( GLint n, GLint *framebuffers )
-void glGenRenderbuffersOES ( GLint n, GLint *renderbuffers )
+void glGenFramebuffersOES ( GLint n, GLuint *framebuffers )
+void glGenRenderbuffersOES ( GLint n, GLuint *renderbuffers )
void glGetFramebufferAttachmentParameterivOES ( GLint target, GLint attachment, GLint pname, GLint *params )
void glGetIntegerv ( GLint pname, GLint *params )
void glGetRenderbufferParameterivOES ( GLint target, GLint pname, GLint *params )
diff --git a/opengl/tools/glgen/specs/jsr239/glspec-checks b/opengl/tools/glgen/specs/jsr239/glspec-checks
index c28e403..9f8a793 100644
--- a/opengl/tools/glgen/specs/jsr239/glspec-checks
+++ b/opengl/tools/glgen/specs/jsr239/glspec-checks
@@ -29,28 +29,28 @@
glDrawTexivOES check coords 5
glDrawTexsvOES check coords 5
glDrawTexxvOES check coords 5
-glBindFramebufferOES unsupported
-glBindRenderbufferOES unsupported
-glBlendEquation unsupported
-glBlendEquationSeparate unsupported
-glBlendFuncSeparate unsupported
-glCheckFramebufferStatusOES unsupported return 0
-glDeleteFramebuffersOES unsupported
-glDeleteRenderbuffersOES unsupported
-glFramebufferRenderbufferOES unsupported
-glFramebufferStorageOES unsupported
-glFramebufferTexture2DOES unsupported
-glGenFramebuffersOES unsupported
-glGenRenderbuffersOES unsupported
-glGenerateMipmapOES unsupported
+glBindFramebufferOES requires OES_framebuffer_object
+glBindRenderbufferOES requires OES_framebuffer_object
+glBlendEquation requires OES_blend_subtract
+glBlendEquationSeparate requires OES_blend_equation_separate
+glBlendFuncSeparate requires OES_blend_equation_separate
+glCheckFramebufferStatusOES requires OES_framebuffer_object return 0
+glDeleteFramebuffersOES requires OES_framebuffer_object check framebuffers n
+glDeleteRenderbuffersOES requires OES_framebuffer_object check renderbuffers n
+glFramebufferRenderbufferOES requires OES_framebuffer_object
+glFramebufferStorageOES requires OES_framebuffer_object
+glFramebufferTexture2DOES requires OES_framebuffer_object
+glGenFramebuffersOES requires OES_framebuffer_object check framebuffers n
+glGenRenderbuffersOES requires OES_framebuffer_object check renderbuffers n
+glGenerateMipmapOES requires OES_framebuffer_object
+glGetFramebufferAttachmentParameterivOES requires OES_framebuffer_object
+glGetRenderbufferParameterivOES requires OES_framebuffer_object
+glIsFramebufferOES requires OES_framebuffer_object return JNI_FALSE
+glIsRenderbufferOES requires OES_framebuffer_object return JNI_FALSE
+glRenderbufferStorageOES requires OES_framebuffer_object
+glGetTexGen requires OES_texture_cube_map
+glTexGen requires OES_texture_cube_map
+glTexGenf requires OES_texture_cube_map
+glTexGeni requires OES_texture_cube_map
+glTexGenx requires OES_texture_cube_map
glGetBufferParameter unsupported
-glGetFramebufferAttachmentParameterivOES unsupported
-glGetRenderbufferParameterivOES unsupported
-glGetTexGen unsupported
-glIsFramebufferOES unsupported return JNI_FALSE
-glIsRenderbufferOES unsupported return JNI_FALSE
-glRenderbufferStorageOES unsupported return false
-glTexGen unsupported
-glTexGenf unsupported
-glTexGeni unsupported
-glTexGenx unsupported
diff --git a/opengl/tools/glgen/src/JniCodeEmitter.java b/opengl/tools/glgen/src/JniCodeEmitter.java
index e79170a..2db4e8d 100644
--- a/opengl/tools/glgen/src/JniCodeEmitter.java
+++ b/opengl/tools/glgen/src/JniCodeEmitter.java
@@ -211,6 +211,8 @@
index += 5;
} else if (checks[index].equals("unsupported")) {
index += 1;
+ } else if (checks[index].equals("requires")) {
+ index += 2;
} else if (checks[index].equals("nullAllowed")) {
return true;
} else {
@@ -243,6 +245,8 @@
index += 5;
} else if (checks[index].equals("unsupported")) {
index += 1;
+ } else if (checks[index].equals("requires")) {
+ index += 2;
} else if (checks[index].equals("nullAllowed")) {
index += 1;
} else {
@@ -263,6 +267,8 @@
while (index < checks.length) {
if (checks[index].equals("unsupported")) {
return true;
+ } else if (checks[index].equals("requires")) {
+ index += 2;
} else if (checks[index].equals("return")) {
index += 2;
} else if (checks[index].startsWith("check")) {
@@ -280,7 +286,34 @@
}
return false;
}
-
+
+ String isRequiresFunc(CFunc cfunc) {
+ String[] checks = mChecker.getChecks(cfunc.getName());
+ int index = 1;
+ if (checks != null) {
+ while (index < checks.length) {
+ if (checks[index].equals("unsupported")) {
+ index += 1;
+ } else if (checks[index].equals("requires")) {
+ return checks[index+1];
+ } else if (checks[index].equals("return")) {
+ index += 2;
+ } else if (checks[index].startsWith("check")) {
+ index += 3;
+ } else if (checks[index].equals("ifcheck")) {
+ index += 5;
+ } else if (checks[index].equals("nullAllowed")) {
+ index += 1;
+ } else {
+ System.out.println("Error: unknown keyword \"" +
+ checks[index] + "\"");
+ System.exit(0);
+ }
+ }
+ }
+ return null;
+ }
+
void emitNativeBoundsChecks(CFunc cfunc, String cname, PrintStream out,
boolean isBuffer, boolean emitExceptionCheck, String offset, String remaining, String iii) {
@@ -365,6 +398,9 @@
} else if (checks[index].equals("unsupported")) {
// ignore
index += 1;
+ } else if (checks[index].equals("requires")) {
+ // ignore
+ index += 2;
} else if (checks[index].equals("nullAllowed")) {
// ignore
index += 1;
@@ -776,7 +812,23 @@
out.println();
return;
}
-
+
+ String requiresExtension = isRequiresFunc(cfunc);
+ if (requiresExtension != null) {
+ out.println(indent +
+ "if (! supportsExtension(_env, _this, have_" + requiresExtension + "ID)) {");
+ out.println(indent + indent +
+ "_env->ThrowNew(UOEClass,");
+ out.println(indent + indent +
+ " \"" + cfunc.getName() + "\");");
+ if (isVoid) {
+ out.println(indent + indent + " return;");
+ } else {
+ String retval = getErrorReturnValue(cfunc);
+ out.println(indent + indent + " return " + retval + ";");
+ }
+ out.println(indent + "}");
+ }
if (mUseContextPointer) {
out.println(indent +
"android::gl::ogles_context_t *ctx = getContext(_env, _this);");
diff --git a/opengl/tools/glgen/stubs/jsr239/GLCHeader.cpp b/opengl/tools/glgen/stubs/jsr239/GLCHeader.cpp
index b3d1c6c..c2464b0 100644
--- a/opengl/tools/glgen/stubs/jsr239/GLCHeader.cpp
+++ b/opengl/tools/glgen/stubs/jsr239/GLCHeader.cpp
@@ -23,6 +23,23 @@
#include <GLES/gl.h>
#include <GLES/glext.h>
+// Work around differences between the generated name and the actual name.
+
+#define glBlendEquation glBlendEquationOES
+#define glBlendEquationSeparate glBlendEquationSeparateOES
+#define glBlendFuncSeparate glBlendFuncSeparateOES
+#define glGetTexGenfv glGetTexGenfvOES
+#define glGetTexGeniv glGetTexGenivOES
+#define glGetTexGenxv glGetTexGenxvOES
+#define glTexGenf glTexGenfOES
+#define glTexGenfv glTexGenfvOES
+#define glTexGeni glTexGeniOES
+#define glTexGeniv glTexGenivOES
+#define glTexGenx glTexGenxOES
+#define glTexGenxv glTexGenxvOES
+
+
+
/* special calls implemented in Android's GLES wrapper used to more
* efficiently bound-check passed arrays */
extern "C" {
@@ -58,6 +75,11 @@
static jfieldID positionID;
static jfieldID limitID;
static jfieldID elementSizeShiftID;
+static jfieldID haveCheckedExtensionsID;
+static jfieldID have_OES_blend_equation_separateID;
+static jfieldID have_OES_blend_subtractID;
+static jfieldID have_OES_framebuffer_objectID;
+static jfieldID have_OES_texture_cube_mapID;
/* Cache method IDs each time the class is loaded. */
@@ -72,6 +94,11 @@
jclass g11impClassLocal = _env->FindClass("com/google/android/gles_jni/GLImpl");
G11ImplClass = (jclass) _env->NewGlobalRef(g11impClassLocal);
+ haveCheckedExtensionsID = _env->GetFieldID(G11ImplClass, "haveCheckedExtensions", "Z");
+ have_OES_blend_equation_separateID = _env->GetFieldID(G11ImplClass, "have_OES_blend_equation_separate", "Z");
+ have_OES_blend_subtractID = _env->GetFieldID(G11ImplClass, "have_OES_blend_subtract", "Z");
+ have_OES_framebuffer_objectID = _env->GetFieldID(G11ImplClass, "have_OES_framebuffer_object", "Z");
+ have_OES_texture_cube_mapID = _env->GetFieldID(G11ImplClass, "have_OES_texture_cube_map", "Z");
getBasePointerID = _env->GetStaticMethodID(nioAccessClass,
"getBasePointer", "(Ljava/nio/Buffer;)J");
@@ -193,5 +220,63 @@
return numCompressedTextureFormats;
}
+// Check if the extension at the head of pExtensions is pExtension. Note that pExtensions is
+// terminated by either 0 or space, while pExtension is terminated by 0.
+
+static bool
+extensionEqual(const GLubyte* pExtensions, const GLubyte* pExtension) {
+ while (true) {
+ char a = *pExtensions++;
+ char b = *pExtension++;
+ bool aEnd = a == '\0' || a == ' ';
+ bool bEnd = b == '\0';
+ if ( aEnd || bEnd) {
+ return aEnd == bEnd;
+ }
+ if ( a != b ) {
+ return false;
+ }
+ }
+}
+
+static const GLubyte*
+nextExtension(const GLubyte* pExtensions) {
+ while (true) {
+ char a = *pExtensions++;
+ if ( a == '\0') {
+ return pExtensions-1;
+ } else if ( a == ' ') {
+ return pExtensions;
+ }
+ }
+}
+
+static bool
+checkForExtension(const GLubyte* pExtensions, const GLubyte* pExtension) {
+ for (;*pExtensions != '\0'; pExtensions = nextExtension(pExtensions)) {
+ if (extensionEqual(pExtensions, pExtension)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+static bool
+supportsExtension(JNIEnv *_env, jobject impl, jfieldID fieldId) {
+ if (!_env->GetBooleanField(impl, haveCheckedExtensionsID)) {
+ _env->SetBooleanField(impl, haveCheckedExtensionsID, true);
+ const GLubyte* sExtensions = glGetString(GL_EXTENSIONS);
+ _env->SetBooleanField(impl, have_OES_blend_equation_separateID,
+ checkForExtension(sExtensions, (const GLubyte*) "GL_OES_blend_equation_separate"));
+ _env->SetBooleanField(impl, have_OES_blend_subtractID,
+ checkForExtension(sExtensions, (const GLubyte*) "GL_OES_blend_subtract"));
+ _env->SetBooleanField(impl, have_OES_framebuffer_objectID,
+ checkForExtension(sExtensions, (const GLubyte*) "GL_OES_framebuffer_object"));
+ _env->SetBooleanField(impl, have_OES_texture_cube_mapID,
+ checkForExtension(sExtensions, (const GLubyte*) "GL_OES_texture_cube_map"));
+ }
+ return _env->GetBooleanField(impl, fieldId);
+}
+
// --------------------------------------------------------------------------
diff --git a/opengl/tools/glgen/stubs/jsr239/GLImplHeader.java-impl b/opengl/tools/glgen/stubs/jsr239/GLImplHeader.java-impl
index 76fea3f..3727106 100644
--- a/opengl/tools/glgen/stubs/jsr239/GLImplHeader.java-impl
+++ b/opengl/tools/glgen/stubs/jsr239/GLImplHeader.java-impl
@@ -47,6 +47,12 @@
Buffer _pointSizePointerOES = null;
Buffer _matrixIndexPointerOES = null;
Buffer _weightPointerOES = null;
+
+ private boolean haveCheckedExtensions;
+ private boolean have_OES_blend_equation_separate;
+ private boolean have_OES_blend_subtract;
+ private boolean have_OES_framebuffer_object;
+ private boolean have_OES_texture_cube_map;
public GLImpl() {
}
diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java
index 72e26f8..62dcb08 100644
--- a/services/java/com/android/server/BackupManagerService.java
+++ b/services/java/com/android/server/BackupManagerService.java
@@ -43,18 +43,20 @@
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
+import android.os.HandlerThread;
import android.os.IBinder;
+import android.os.Looper;
import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.os.PowerManager;
import android.os.Process;
import android.os.RemoteException;
import android.os.SystemClock;
-import android.os.SystemProperties;
import android.provider.Settings;
import android.util.EventLog;
import android.util.Log;
import android.util.SparseArray;
+import android.util.SparseIntArray;
import com.android.internal.backup.BackupConstants;
import com.android.internal.backup.IBackupTransport;
@@ -98,20 +100,27 @@
private static final int MSG_RUN_RESTORE = 3;
private static final int MSG_RUN_CLEAR = 4;
private static final int MSG_RUN_INITIALIZE = 5;
+ private static final int MSG_TIMEOUT = 6;
// Timeout interval for deciding that a bind or clear-data has taken too long
static final long TIMEOUT_INTERVAL = 10 * 1000;
+ // Timeout intervals for agent backup & restore operations
+ static final long TIMEOUT_BACKUP_INTERVAL = 30 * 1000;
+ static final long TIMEOUT_RESTORE_INTERVAL = 60 * 1000;
+
private Context mContext;
private PackageManager mPackageManager;
private IActivityManager mActivityManager;
private PowerManager mPowerManager;
private AlarmManager mAlarmManager;
+ IBackupManager mBackupManagerBinder;
boolean mEnabled; // access to this is synchronized on 'this'
boolean mProvisioned;
PowerManager.WakeLock mWakelock;
- final BackupHandler mBackupHandler = new BackupHandler();
+ HandlerThread mHandlerThread = new HandlerThread("backup", Process.THREAD_PRIORITY_BACKGROUND);
+ BackupHandler mBackupHandler;
PendingIntent mRunBackupIntent, mRunInitIntent;
BroadcastReceiver mRunBackupReceiver, mRunInitReceiver;
// map UIDs to the set of backup client services within that UID's app set
@@ -185,6 +194,16 @@
}
}
+ // Bookkeeping of in-flight operations for timeout etc. purposes. The operation
+ // token is the index of the entry in the pending-operations list.
+ static final int OP_PENDING = 0;
+ static final int OP_ACKNOWLEDGED = 1;
+ static final int OP_TIMEOUT = -1;
+
+ final SparseIntArray mCurrentOperations = new SparseIntArray();
+ final Object mCurrentOpLock = new Object();
+ final Random mTokenGenerator = new Random();
+
// Where we keep our journal files and other bookkeeping
File mBaseStateDir;
File mDataDir;
@@ -200,6 +219,115 @@
HashSet<String> mPendingInits = new HashSet<String>(); // transport names
volatile boolean mInitInProgress = false;
+ // ----- Asynchronous backup/restore handler thread -----
+
+ private class BackupHandler extends Handler {
+ public BackupHandler(Looper looper) {
+ super(looper);
+ }
+
+ public void handleMessage(Message msg) {
+
+ switch (msg.what) {
+ case MSG_RUN_BACKUP:
+ {
+ mLastBackupPass = System.currentTimeMillis();
+ mNextBackupPass = mLastBackupPass + BACKUP_INTERVAL;
+
+ IBackupTransport transport = getTransport(mCurrentTransport);
+ if (transport == null) {
+ Log.v(TAG, "Backup requested but no transport available");
+ synchronized (mQueueLock) {
+ mBackupOrRestoreInProgress = false;
+ }
+ mWakelock.release();
+ break;
+ }
+
+ // snapshot the pending-backup set and work on that
+ ArrayList<BackupRequest> queue = new ArrayList<BackupRequest>();
+ synchronized (mQueueLock) {
+ // Do we have any work to do?
+ if (mPendingBackups.size() > 0) {
+ for (BackupRequest b: mPendingBackups.values()) {
+ queue.add(b);
+ }
+ if (DEBUG) Log.v(TAG, "clearing pending backups");
+ mPendingBackups.clear();
+
+ // Start a new backup-queue journal file too
+ File oldJournal = mJournal;
+ mJournal = null;
+
+ // At this point, we have started a new journal file, and the old
+ // file identity is being passed to the backup processing thread.
+ // When it completes successfully, that old journal file will be
+ // deleted. If we crash prior to that, the old journal is parsed
+ // at next boot and the journaled requests fulfilled.
+ (new PerformBackupTask(transport, queue, oldJournal)).run();
+ } else {
+ Log.v(TAG, "Backup requested but nothing pending");
+ synchronized (mQueueLock) {
+ mBackupOrRestoreInProgress = false;
+ }
+ mWakelock.release();
+ }
+ }
+ break;
+ }
+
+ case MSG_RUN_FULL_BACKUP:
+ break;
+
+ case MSG_RUN_RESTORE:
+ {
+ RestoreParams params = (RestoreParams)msg.obj;
+ Log.d(TAG, "MSG_RUN_RESTORE observer=" + params.observer);
+ (new PerformRestoreTask(params.transport, params.observer,
+ params.token)).run();
+ break;
+ }
+
+ case MSG_RUN_CLEAR:
+ {
+ ClearParams params = (ClearParams)msg.obj;
+ (new PerformClearTask(params.transport, params.packageInfo)).run();
+ break;
+ }
+
+ case MSG_RUN_INITIALIZE:
+ {
+ HashSet<String> queue;
+
+ // Snapshot the pending-init queue and work on that
+ synchronized (mQueueLock) {
+ queue = new HashSet<String>(mPendingInits);
+ mPendingInits.clear();
+ }
+
+ (new PerformInitializeTask(queue)).run();
+ break;
+ }
+
+ case MSG_TIMEOUT:
+ {
+ synchronized (mCurrentOpLock) {
+ final int token = msg.arg1;
+ int state = mCurrentOperations.get(token, OP_TIMEOUT);
+ if (state == OP_PENDING) {
+ if (DEBUG) Log.v(TAG, "TIMEOUT: token=" + token);
+ mCurrentOperations.put(token, OP_TIMEOUT);
+ }
+ mCurrentOpLock.notifyAll();
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ // ----- Main service implementation -----
+
public BackupManagerService(Context context) {
mContext = context;
mPackageManager = context.getPackageManager();
@@ -208,6 +336,13 @@
mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
+ mBackupManagerBinder = asInterface(asBinder());
+
+ // spin up the backup/restore handler thread
+ mHandlerThread = new HandlerThread("backup", Process.THREAD_PRIORITY_BACKGROUND);
+ mHandlerThread.start();
+ mBackupHandler = new BackupHandler(mHandlerThread.getLooper());
+
// Set up our bookkeeping
boolean areEnabled = Settings.Secure.getInt(context.getContentResolver(),
Settings.Secure.BACKUP_ENABLED, 0) != 0;
@@ -506,7 +641,7 @@
mTransports.put(name, transport);
} else {
mTransports.remove(name);
- if (mCurrentTransport.equals(name)) {
+ if ((mCurrentTransport != null) && mCurrentTransport.equals(name)) {
mCurrentTransport = null;
}
// Nothing further to do in the unregistration case
@@ -593,95 +728,6 @@
}
};
- // ----- Run the actual backup process asynchronously -----
-
- private class BackupHandler extends Handler {
- public void handleMessage(Message msg) {
-
- switch (msg.what) {
- case MSG_RUN_BACKUP:
- {
- mLastBackupPass = System.currentTimeMillis();
- mNextBackupPass = mLastBackupPass + BACKUP_INTERVAL;
-
- IBackupTransport transport = getTransport(mCurrentTransport);
- if (transport == null) {
- Log.v(TAG, "Backup requested but no transport available");
- synchronized (mQueueLock) {
- mBackupOrRestoreInProgress = false;
- }
- mWakelock.release();
- break;
- }
-
- // snapshot the pending-backup set and work on that
- ArrayList<BackupRequest> queue = new ArrayList<BackupRequest>();
- synchronized (mQueueLock) {
- // Do we have any work to do?
- if (mPendingBackups.size() > 0) {
- for (BackupRequest b: mPendingBackups.values()) {
- queue.add(b);
- }
- Log.v(TAG, "clearing pending backups");
- mPendingBackups.clear();
-
- // Start a new backup-queue journal file too
- File oldJournal = mJournal;
- mJournal = null;
-
- // At this point, we have started a new journal file, and the old
- // file identity is being passed to the backup processing thread.
- // When it completes successfully, that old journal file will be
- // deleted. If we crash prior to that, the old journal is parsed
- // at next boot and the journaled requests fulfilled.
- (new PerformBackupThread(transport, queue, oldJournal)).start();
- } else {
- Log.v(TAG, "Backup requested but nothing pending");
- synchronized (mQueueLock) {
- mBackupOrRestoreInProgress = false;
- }
- mWakelock.release();
- }
- }
- break;
- }
-
- case MSG_RUN_FULL_BACKUP:
- break;
-
- case MSG_RUN_RESTORE:
- {
- RestoreParams params = (RestoreParams)msg.obj;
- Log.d(TAG, "MSG_RUN_RESTORE observer=" + params.observer);
- (new PerformRestoreThread(params.transport, params.observer,
- params.token)).start();
- break;
- }
-
- case MSG_RUN_CLEAR:
- {
- ClearParams params = (ClearParams)msg.obj;
- (new PerformClearThread(params.transport, params.packageInfo)).start();
- break;
- }
-
- case MSG_RUN_INITIALIZE:
- {
- HashSet<String> queue;
-
- // Snapshot the pending-init queue and work on that
- synchronized (mQueueLock) {
- queue = new HashSet<String>(mPendingInits);
- mPendingInits.clear();
- }
-
- (new PerformInitializeThread(queue)).start();
- break;
- }
- }
- }
- }
-
// Add the backup agents in the given package to our set of known backup participants.
// If 'packageName' is null, adds all backup agents in the whole system.
void addPackageParticipantsLocked(String packageName) {
@@ -978,16 +1024,44 @@
}
}
+ // -----
+ // Utility methods used by the asynchronous-with-timeout backup/restore operations
+ boolean waitUntilOperationComplete(int token) {
+ int finalState = OP_PENDING;
+ synchronized (mCurrentOpLock) {
+ try {
+ while ((finalState = mCurrentOperations.get(token, OP_TIMEOUT)) == OP_PENDING) {
+ try {
+ mCurrentOpLock.wait();
+ } catch (InterruptedException e) {}
+ }
+ } catch (IndexOutOfBoundsException e) {
+ // the operation has been mysteriously cleared from our
+ // bookkeeping -- consider this a success and ignore it.
+ }
+ }
+ mBackupHandler.removeMessages(MSG_TIMEOUT);
+ if (DEBUG) Log.v(TAG, "operation " + token + " complete: finalState=" + finalState);
+ return finalState == OP_ACKNOWLEDGED;
+ }
+
+ void prepareOperationTimeout(int token, long interval) {
+ if (DEBUG) Log.v(TAG, "starting timeout: token=" + token + " interval=" + interval);
+ mCurrentOperations.put(token, OP_PENDING);
+ Message msg = mBackupHandler.obtainMessage(MSG_TIMEOUT, token, 0);
+ mBackupHandler.sendMessageDelayed(msg, interval);
+ }
+
// ----- Back up a set of applications via a worker thread -----
- class PerformBackupThread extends Thread {
+ class PerformBackupTask implements Runnable {
private static final String TAG = "PerformBackupThread";
IBackupTransport mTransport;
ArrayList<BackupRequest> mQueue;
File mStateDir;
File mJournal;
- public PerformBackupThread(IBackupTransport transport, ArrayList<BackupRequest> queue,
+ public PerformBackupTask(IBackupTransport transport, ArrayList<BackupRequest> queue,
File journal) {
mTransport = transport;
mQueue = queue;
@@ -1000,7 +1074,6 @@
}
}
- @Override
public void run() {
int status = BackupConstants.TRANSPORT_OK;
long startRealtime = SystemClock.elapsedRealtime();
@@ -1158,6 +1231,7 @@
ParcelFileDescriptor newState = null;
PackageInfo packInfo;
+ int token = mTokenGenerator.nextInt();
try {
// Look up the package info & signatures. This is first so that if it
// throws an exception, there's no file setup yet that would need to
@@ -1189,8 +1263,16 @@
ParcelFileDescriptor.MODE_CREATE |
ParcelFileDescriptor.MODE_TRUNCATE);
- // Run the target's backup pass
- agent.doBackup(savedState, backupData, newState);
+ // Initiate the target's backup pass
+ prepareOperationTimeout(token, TIMEOUT_BACKUP_INTERVAL);
+ agent.doBackup(savedState, backupData, newState, token, mBackupManagerBinder);
+ boolean success = waitUntilOperationComplete(token);
+
+ if (!success) {
+ // timeout -- bail out into the failed-transaction logic
+ throw new RuntimeException("Backup timeout");
+ }
+
logBackupComplete(packageName);
if (DEBUG) Log.v(TAG, "doBackup() success");
} catch (Exception e) {
@@ -1204,6 +1286,9 @@
try { if (backupData != null) backupData.close(); } catch (IOException e) {}
try { if (newState != null) newState.close(); } catch (IOException e) {}
savedState = backupData = newState = null;
+ synchronized (mCurrentOpLock) {
+ mCurrentOperations.clear();
+ }
}
// Now propagate the newly-backed-up data to the transport
@@ -1299,7 +1384,7 @@
return true;
}
- class PerformRestoreThread extends Thread {
+ class PerformRestoreTask implements Runnable {
private IBackupTransport mTransport;
private IRestoreObserver mObserver;
private long mToken;
@@ -1315,7 +1400,7 @@
}
}
- PerformRestoreThread(IBackupTransport transport, IRestoreObserver observer,
+ PerformRestoreTask(IBackupTransport transport, IRestoreObserver observer,
long restoreSetToken) {
mTransport = transport;
Log.d(TAG, "PerformRestoreThread mObserver=" + mObserver);
@@ -1329,7 +1414,6 @@
}
}
- @Override
public void run() {
long startRealtime = SystemClock.elapsedRealtime();
if (DEBUG) Log.v(TAG, "Beginning restore process mTransport=" + mTransport
@@ -1579,6 +1663,7 @@
ParcelFileDescriptor backupData = null;
ParcelFileDescriptor newState = null;
+ int token = mTokenGenerator.nextInt();
try {
// Run the transport's restore pass
backupData = ParcelFileDescriptor.open(backupDataName,
@@ -1602,7 +1687,14 @@
ParcelFileDescriptor.MODE_CREATE |
ParcelFileDescriptor.MODE_TRUNCATE);
- agent.doRestore(backupData, appVersionCode, newState);
+ // Kick off the restore, checking for hung agents
+ prepareOperationTimeout(token, TIMEOUT_RESTORE_INTERVAL);
+ agent.doRestore(backupData, appVersionCode, newState, token, mBackupManagerBinder);
+ boolean success = waitUntilOperationComplete(token);
+
+ if (!success) {
+ throw new RuntimeException("restore timeout");
+ }
// if everything went okay, remember the recorded state now
//
@@ -1635,20 +1727,20 @@
try { if (backupData != null) backupData.close(); } catch (IOException e) {}
try { if (newState != null) newState.close(); } catch (IOException e) {}
backupData = newState = null;
+ mCurrentOperations.delete(token);
}
}
}
- class PerformClearThread extends Thread {
+ class PerformClearTask implements Runnable {
IBackupTransport mTransport;
PackageInfo mPackage;
- PerformClearThread(IBackupTransport transport, PackageInfo packageInfo) {
+ PerformClearTask(IBackupTransport transport, PackageInfo packageInfo) {
mTransport = transport;
mPackage = packageInfo;
}
- @Override
public void run() {
try {
// Clear the on-device backup state to ensure a full backup next time
@@ -1678,14 +1770,13 @@
}
}
- class PerformInitializeThread extends Thread {
+ class PerformInitializeTask implements Runnable {
HashSet<String> mQueue;
- PerformInitializeThread(HashSet<String> transportNames) {
+ PerformInitializeTask(HashSet<String> transportNames) {
mQueue = transportNames;
}
- @Override
public void run() {
try {
for (String transportName : mQueue) {
@@ -2073,6 +2164,16 @@
return mActiveRestoreSession;
}
+ // Note that a currently-active backup agent has notified us that it has
+ // completed the given outstanding asynchronous backup/restore operation.
+ public void opComplete(int token) {
+ synchronized (mCurrentOpLock) {
+ if (DEBUG) Log.v(TAG, "opComplete: " + token);
+ mCurrentOperations.put(token, OP_ACKNOWLEDGED);
+ mCurrentOpLock.notifyAll();
+ }
+ }
+
// ----- Restore session -----
class ActiveRestoreSession extends IRestoreSession.Stub {
diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java
index cefd312..e14a973 100644
--- a/services/java/com/android/server/PowerManagerService.java
+++ b/services/java/com/android/server/PowerManagerService.java
@@ -2011,6 +2011,10 @@
}
}
}
+
+ if (mPolicy != null) {
+ mPolicy.userActivity();
+ }
}
private int getAutoBrightnessValue(int sensorValue, int[] values) {
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index 1d14e5e..88aadbd 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -2385,7 +2385,8 @@
// to provide the correct semantics while starting.
final int mask =
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
- | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD;
+ | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
+ | WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON;
WindowManager.LayoutParams sa = win.mAppToken.startingWindow.mAttrs;
sa.flags = (sa.flags&~mask) | (win.mAttrs.flags&mask);
}