Merge "Add new sensor types." into jb-mr2-dev
diff --git a/Android.mk b/Android.mk
index 43791c7..104293c 100644
--- a/Android.mk
+++ b/Android.mk
@@ -180,6 +180,7 @@
core/java/com/android/internal/appwidget/IAppWidgetService.aidl \
core/java/com/android/internal/appwidget/IAppWidgetHost.aidl \
core/java/com/android/internal/backup/IBackupTransport.aidl \
+ core/java/com/android/internal/backup/IObbBackupService.aidl \
core/java/com/android/internal/policy/IFaceLockCallback.aidl \
core/java/com/android/internal/policy/IFaceLockInterface.aidl \
core/java/com/android/internal/os/IDropBoxManagerService.aidl \
diff --git a/api/current.txt b/api/current.txt
index b173c70..4eb6a0b 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -2134,8 +2134,10 @@
public abstract class AbstractAccountAuthenticator {
ctor public AbstractAccountAuthenticator(android.content.Context);
method public abstract android.os.Bundle addAccount(android.accounts.AccountAuthenticatorResponse, java.lang.String, java.lang.String, java.lang.String[], android.os.Bundle) throws android.accounts.NetworkErrorException;
+ method public android.os.Bundle addAccountFromCredentials(android.accounts.AccountAuthenticatorResponse, android.accounts.Account, android.os.Bundle) throws android.accounts.NetworkErrorException;
method public abstract android.os.Bundle confirmCredentials(android.accounts.AccountAuthenticatorResponse, android.accounts.Account, android.os.Bundle) throws android.accounts.NetworkErrorException;
method public abstract android.os.Bundle editProperties(android.accounts.AccountAuthenticatorResponse, java.lang.String);
+ method public android.os.Bundle getAccountCredentialsForCloning(android.accounts.AccountAuthenticatorResponse, android.accounts.Account) throws android.accounts.NetworkErrorException;
method public android.os.Bundle getAccountRemovalAllowed(android.accounts.AccountAuthenticatorResponse, android.accounts.Account) throws android.accounts.NetworkErrorException;
method public abstract android.os.Bundle getAuthToken(android.accounts.AccountAuthenticatorResponse, android.accounts.Account, java.lang.String, android.os.Bundle) throws android.accounts.NetworkErrorException;
method public abstract java.lang.String getAuthTokenLabel(java.lang.String);
@@ -11282,6 +11284,7 @@
method public static android.media.MediaCodec createByCodecName(java.lang.String);
method public static android.media.MediaCodec createDecoderByType(java.lang.String);
method public static android.media.MediaCodec createEncoderByType(java.lang.String);
+ method public final android.view.Surface createInputSurface();
method public final int dequeueInputBuffer(long);
method public final int dequeueOutputBuffer(android.media.MediaCodec.BufferInfo, long);
method public final void flush();
@@ -11295,6 +11298,7 @@
method public final void release();
method public final void releaseOutputBuffer(int, boolean);
method public final void setVideoScalingMode(int);
+ method public final void signalEndOfInputStream();
method public final void start();
method public final void stop();
field public static final int BUFFER_FLAG_CODEC_CONFIG = 2; // 0x2
@@ -11374,6 +11378,7 @@
field public static final int COLOR_FormatRawBayer10bit = 31; // 0x1f
field public static final int COLOR_FormatRawBayer8bit = 30; // 0x1e
field public static final int COLOR_FormatRawBayer8bitcompressed = 32; // 0x20
+ field public static final int COLOR_FormatSurface = 2130708361; // 0x7f000789
field public static final int COLOR_FormatYCbYCr = 25; // 0x19
field public static final int COLOR_FormatYCrYCb = 26; // 0x1a
field public static final int COLOR_FormatYUV411PackedPlanar = 18; // 0x12
@@ -11596,6 +11601,20 @@
field public static final int OPTION_PREVIOUS_SYNC = 0; // 0x0
}
+ public final class MediaMuxer {
+ ctor public MediaMuxer(java.lang.String, int) throws java.io.IOException;
+ method public int addTrack(android.media.MediaFormat);
+ method public void release();
+ method public void start();
+ method public void stop();
+ method public void writeSampleData(int, java.nio.ByteBuffer, android.media.MediaCodec.BufferInfo);
+ field public static final int SAMPLE_FLAG_SYNC = 1; // 0x1
+ }
+
+ public static final class MediaMuxer.OutputFormat {
+ field public static final int MUXER_OUTPUT_MPEG_4 = 0; // 0x0
+ }
+
public class MediaPlayer {
ctor public MediaPlayer();
method public void addTimedTextSource(java.lang.String, java.lang.String) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException;
@@ -11809,6 +11828,7 @@
method public android.media.MediaRouter.UserRouteInfo createUserRoute(android.media.MediaRouter.RouteCategory);
method public android.media.MediaRouter.RouteCategory getCategoryAt(int);
method public int getCategoryCount();
+ method public android.media.MediaRouter.RouteInfo getDefaultRoute();
method public android.media.MediaRouter.RouteInfo getRouteAt(int);
method public int getRouteCount();
method public android.media.MediaRouter.RouteInfo getSelectedRoute(int);
@@ -14128,6 +14148,7 @@
method public static int eglGetError();
method public static boolean eglInitialize(android.opengl.EGLDisplay, int[], int, int[], int);
method public static boolean eglMakeCurrent(android.opengl.EGLDisplay, android.opengl.EGLSurface, android.opengl.EGLSurface, android.opengl.EGLContext);
+ method public static boolean eglPresentationTimeANDROID(android.opengl.EGLDisplay, android.opengl.EGLSurface, long);
method public static int eglQueryAPI();
method public static boolean eglQueryContext(android.opengl.EGLDisplay, android.opengl.EGLContext, int, int[], int);
method public static java.lang.String eglQueryString(android.opengl.EGLDisplay, int);
@@ -22528,19 +22549,19 @@
method public static java.text.DateFormat getMediumDateFormat(android.content.Context);
method public static java.text.DateFormat getTimeFormat(android.content.Context);
method public static boolean is24HourFormat(android.content.Context);
- field public static final char AM_PM = 97; // 0x0061 'a'
- field public static final char CAPITAL_AM_PM = 65; // 0x0041 'A'
- field public static final char DATE = 100; // 0x0064 'd'
- field public static final char DAY = 69; // 0x0045 'E'
- field public static final char HOUR = 104; // 0x0068 'h'
- field public static final char HOUR_OF_DAY = 107; // 0x006b 'k'
- field public static final char MINUTE = 109; // 0x006d 'm'
- field public static final char MONTH = 77; // 0x004d 'M'
- field public static final char QUOTE = 39; // 0x0027 '\''
- field public static final char SECONDS = 115; // 0x0073 's'
- field public static final char STANDALONE_MONTH = 76; // 0x004c 'L'
- field public static final char TIME_ZONE = 122; // 0x007a 'z'
- field public static final char YEAR = 121; // 0x0079 'y'
+ field public static final deprecated char AM_PM = 97; // 0x0061 'a'
+ field public static final deprecated char CAPITAL_AM_PM = 65; // 0x0041 'A'
+ field public static final deprecated char DATE = 100; // 0x0064 'd'
+ field public static final deprecated char DAY = 69; // 0x0045 'E'
+ field public static final deprecated char HOUR = 104; // 0x0068 'h'
+ field public static final deprecated char HOUR_OF_DAY = 107; // 0x006b 'k'
+ field public static final deprecated char MINUTE = 109; // 0x006d 'm'
+ field public static final deprecated char MONTH = 77; // 0x004d 'M'
+ field public static final deprecated char QUOTE = 39; // 0x0027 '\''
+ field public static final deprecated char SECONDS = 115; // 0x0073 's'
+ field public static final deprecated char STANDALONE_MONTH = 76; // 0x004c 'L'
+ field public static final deprecated char TIME_ZONE = 122; // 0x007a 'z'
+ field public static final deprecated char YEAR = 121; // 0x0079 'y'
}
public class DateUtils {
@@ -24167,6 +24188,7 @@
field public static final int SOURCE_CLASS_BUTTON = 1; // 0x1
field public static final int SOURCE_CLASS_JOYSTICK = 16; // 0x10
field public static final int SOURCE_CLASS_MASK = 255; // 0xff
+ field public static final int SOURCE_CLASS_NONE = 0; // 0x0
field public static final int SOURCE_CLASS_POINTER = 2; // 0x2
field public static final int SOURCE_CLASS_POSITION = 8; // 0x8
field public static final int SOURCE_CLASS_TRACKBALL = 4; // 0x4
@@ -24178,6 +24200,7 @@
field public static final int SOURCE_STYLUS = 16386; // 0x4002
field public static final int SOURCE_TOUCHPAD = 1048584; // 0x100008
field public static final int SOURCE_TOUCHSCREEN = 4098; // 0x1002
+ field public static final int SOURCE_TOUCH_NAVIGATION = 2097152; // 0x200000
field public static final int SOURCE_TRACKBALL = 65540; // 0x10004
field public static final int SOURCE_UNKNOWN = 0; // 0x0
}
@@ -24190,6 +24213,7 @@
method public float getMin();
method public float getRange();
method public int getSource();
+ method public boolean isFromSource(int);
}
public abstract class InputEvent implements android.os.Parcelable {
@@ -24198,6 +24222,7 @@
method public abstract int getDeviceId();
method public abstract long getEventTime();
method public abstract int getSource();
+ method public boolean isFromSource(int);
field public static final android.os.Parcelable.Creator CREATOR;
}
diff --git a/cmds/bu/src/com/android/commands/bu/Backup.java b/cmds/bu/src/com/android/commands/bu/Backup.java
index 046ccca..73fd660 100644
--- a/cmds/bu/src/com/android/commands/bu/Backup.java
+++ b/cmds/bu/src/com/android/commands/bu/Backup.java
@@ -22,6 +22,7 @@
import android.os.ServiceManager;
import android.util.Log;
+import java.io.IOException;
import java.util.ArrayList;
public final class Backup {
@@ -64,6 +65,7 @@
private void doFullBackup(int socketFd) {
ArrayList<String> packages = new ArrayList<String>();
boolean saveApks = false;
+ boolean saveObbs = false;
boolean saveShared = false;
boolean doEverything = false;
boolean allIncludesSystem = true;
@@ -75,6 +77,10 @@
saveApks = true;
} else if ("-noapk".equals(arg)) {
saveApks = false;
+ } else if ("-obb".equals(arg)) {
+ saveObbs = true;
+ } else if ("-noobb".equals(arg)) {
+ saveObbs = false;
} else if ("-shared".equals(arg)) {
saveShared = true;
} else if ("-noshared".equals(arg)) {
@@ -104,23 +110,37 @@
return;
}
+ ParcelFileDescriptor fd = null;
try {
- ParcelFileDescriptor fd = ParcelFileDescriptor.adoptFd(socketFd);
+ fd = ParcelFileDescriptor.adoptFd(socketFd);
String[] packArray = new String[packages.size()];
- mBackupManager.fullBackup(fd, saveApks, saveShared, doEverything, allIncludesSystem,
- packages.toArray(packArray));
+ mBackupManager.fullBackup(fd, saveApks, saveObbs, saveShared, doEverything,
+ allIncludesSystem, packages.toArray(packArray));
} catch (RemoteException e) {
Log.e(TAG, "Unable to invoke backup manager for backup");
+ } finally {
+ if (fd != null) {
+ try {
+ fd.close();
+ } catch (IOException e) {}
+ }
}
}
private void doFullRestore(int socketFd) {
// No arguments to restore
+ ParcelFileDescriptor fd = null;
try {
- ParcelFileDescriptor fd = ParcelFileDescriptor.adoptFd(socketFd);
+ fd = ParcelFileDescriptor.adoptFd(socketFd);
mBackupManager.fullRestore(fd);
} catch (RemoteException e) {
Log.e(TAG, "Unable to invoke backup manager for restore");
+ } finally {
+ if (fd != null) {
+ try {
+ fd.close();
+ } catch (IOException e) {}
+ }
}
}
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index 22ce841..98c82b5 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -1149,10 +1149,7 @@
ClearDataObserver obs = new ClearDataObserver();
try {
- if (!ActivityManagerNative.getDefault().clearApplicationUserData(pkg, obs, userId)) {
- System.err.println("Failed");
- }
-
+ ActivityManagerNative.getDefault().clearApplicationUserData(pkg, obs, userId);
synchronized (obs) {
while (!obs.finished) {
try {
diff --git a/core/java/android/accounts/AbstractAccountAuthenticator.java b/core/java/android/accounts/AbstractAccountAuthenticator.java
index fa46689..dbc9051 100644
--- a/core/java/android/accounts/AbstractAccountAuthenticator.java
+++ b/core/java/android/accounts/AbstractAccountAuthenticator.java
@@ -505,7 +505,6 @@
}
/**
- * @hide
* Returns a Bundle that contains whatever is required to clone the account on a different
* user. The Bundle is passed to the authenticator instance in the target user via
* {@link #addAccountFromCredentials(AccountAuthenticatorResponse, Account, Bundle)}.
@@ -529,7 +528,6 @@
}
/**
- * @hide
* Creates an account based on credentials provided by the authenticator instance of another
* user on the device, who has chosen to share the account with this user.
* @param response to send the result back to the AccountManager, will never be null
diff --git a/core/java/android/app/MediaRouteButton.java b/core/java/android/app/MediaRouteButton.java
index a1a147a..7e0a27a 100644
--- a/core/java/android/app/MediaRouteButton.java
+++ b/core/java/android/app/MediaRouteButton.java
@@ -123,13 +123,13 @@
if (mToggleMode) {
if (mRemoteActive) {
- mRouter.selectRouteInt(mRouteTypes, mRouter.getSystemAudioRoute());
+ mRouter.selectRouteInt(mRouteTypes, mRouter.getDefaultRoute());
} else {
final int N = mRouter.getRouteCount();
for (int i = 0; i < N; i++) {
final RouteInfo route = mRouter.getRouteAt(i);
if ((route.getSupportedTypes() & mRouteTypes) != 0 &&
- route != mRouter.getSystemAudioRoute()) {
+ route != mRouter.getDefaultRoute()) {
mRouter.selectRouteInt(mRouteTypes, route);
}
}
@@ -216,7 +216,7 @@
void updateRemoteIndicator() {
final RouteInfo selected = mRouter.getSelectedRoute(mRouteTypes);
- final boolean isRemote = selected != mRouter.getSystemAudioRoute();
+ final boolean isRemote = selected != mRouter.getDefaultRoute();
final boolean isConnecting = selected != null &&
selected.getStatusCode() == RouteInfo.STATUS_CONNECTING;
diff --git a/core/java/android/app/backup/BackupAgent.java b/core/java/android/app/backup/BackupAgent.java
index 44aa06f..3425765 100644
--- a/core/java/android/app/backup/BackupAgent.java
+++ b/core/java/android/app/backup/BackupAgent.java
@@ -472,6 +472,7 @@
File efLocation = getExternalFilesDir(null);
if (efLocation != null) {
basePath = getExternalFilesDir(null).getCanonicalPath();
+ mode = -1; // < 0 is a token to skip attempting a chmod()
}
}
} else {
diff --git a/core/java/android/app/backup/FullBackup.java b/core/java/android/app/backup/FullBackup.java
index 2fe08f3..cb0737e 100644
--- a/core/java/android/app/backup/FullBackup.java
+++ b/core/java/android/app/backup/FullBackup.java
@@ -89,7 +89,7 @@
* last modification time of the output file. if the {@code mode} parameter is
* negative then this parameter will be ignored.
* @param outFile Location within the filesystem to place the data. This must point
- * to a location that is writeable by the caller, prefereably using an absolute path.
+ * to a location that is writeable by the caller, preferably using an absolute path.
* @throws IOException
*/
static public void restoreFile(ParcelFileDescriptor data,
diff --git a/core/java/android/app/backup/IBackupManager.aidl b/core/java/android/app/backup/IBackupManager.aidl
index acdd0b5..bb4f5f1 100644
--- a/core/java/android/app/backup/IBackupManager.aidl
+++ b/core/java/android/app/backup/IBackupManager.aidl
@@ -152,6 +152,8 @@
* @param fd The file descriptor to which a 'tar' file stream is to be written
* @param includeApks If <code>true</code>, the resulting tar stream will include the
* application .apk files themselves as well as their data.
+ * @param includeObbs If <code>true</code>, the resulting tar stream will include any
+ * application expansion (OBB) files themselves belonging to each application.
* @param includeShared If <code>true</code>, the resulting tar stream will include
* the contents of the device's shared storage (SD card or equivalent).
* @param allApps If <code>true</code>, the resulting tar stream will include all
@@ -164,8 +166,9 @@
* @param packageNames The package names of the apps whose data (and optionally .apk files)
* are to be backed up. The <code>allApps</code> parameter supersedes this.
*/
- void fullBackup(in ParcelFileDescriptor fd, boolean includeApks, boolean includeShared,
- boolean allApps, boolean allIncludesSystem, in String[] packageNames);
+ void fullBackup(in ParcelFileDescriptor fd, boolean includeApks, boolean includeObbs,
+ boolean includeShared, boolean allApps, boolean allIncludesSystem,
+ in String[] packageNames);
/**
* Restore device content from the data stream passed through the given socket. The
diff --git a/core/java/android/appwidget/AppWidgetHost.java b/core/java/android/appwidget/AppWidgetHost.java
index a470e70..f7933d3 100644
--- a/core/java/android/appwidget/AppWidgetHost.java
+++ b/core/java/android/appwidget/AppWidgetHost.java
@@ -408,12 +408,10 @@
* @hide
*/
protected void onProvidersChanged(int userId) {
- checkUserMatch(userId);
// Does nothing
}
void updateAppWidgetView(int appWidgetId, RemoteViews views, int userId) {
- checkUserMatch(userId);
AppWidgetHostView v;
synchronized (mViews) {
v = mViews.get(appWidgetId);
@@ -424,7 +422,6 @@
}
void viewDataChanged(int appWidgetId, int viewId, int userId) {
- checkUserMatch(userId);
AppWidgetHostView v;
synchronized (mViews) {
v = mViews.get(appWidgetId);
@@ -434,16 +431,6 @@
}
}
- // Ensure that the userId passed to us agrees with the one associated with this instance
- // of AppWidgetHost.
- // TODO: This should be removed in production code.
- private void checkUserMatch(int userId) {
- if (userId != mContext.getUserId()) {
- throw new IllegalStateException(
- "User ids don't match, userId=" + userId + ", mUserId=" + mContext.getUserId());
- }
- }
-
/**
* Clear the list of Views that have been created by this AppWidgetHost.
*/
diff --git a/core/java/android/content/pm/RegisteredServicesCache.java b/core/java/android/content/pm/RegisteredServicesCache.java
index aaa0917..288d55f 100644
--- a/core/java/android/content/pm/RegisteredServicesCache.java
+++ b/core/java/android/content/pm/RegisteredServicesCache.java
@@ -488,7 +488,8 @@
XmlPullParser parser = Xml.newPullParser();
parser.setInput(fis, null);
int eventType = parser.getEventType();
- while (eventType != XmlPullParser.START_TAG) {
+ while (eventType != XmlPullParser.START_TAG
+ && eventType != XmlPullParser.END_DOCUMENT) {
eventType = parser.next();
}
String tagName = parser.getName();
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index 24a0bb5..805b05e 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -233,11 +233,13 @@
}
/**
- * Return the character sequence associated with a particular resource ID for a particular
- * numerical quantity.
- *
- * <p>See <a href="{@docRoot}guide/topics/resources/string-resource.html#Plurals">String
- * Resources</a> for more on quantity strings.
+ * Returns the character sequence necessary for grammatically correct pluralization
+ * of the given resource ID for the given quantity.
+ * Note that the character sequence is selected based solely on grammatical necessity,
+ * and that such rules differ between languages. Do not assume you know which string
+ * will be returned for a given quantity. See
+ * <a href="{@docRoot}guide/topics/resources/string-resource.html#Plurals">String Resources</a>
+ * for more detail.
*
* @param id The desired resource identifier, as generated by the aapt
* tool. This integer encodes the package, type, and resource
@@ -345,14 +347,17 @@
}
/**
- * Return the string value associated with a particular resource ID for a particular
- * numerical quantity, substituting the format arguments as defined in
- * {@link java.util.Formatter} and {@link java.lang.String#format}. It will be
- * stripped of any styled text information.
- * {@more}
+ * Formats the string necessary for grammatically correct pluralization
+ * of the given resource ID for the given quantity, using the given arguments.
+ * Note that the string is selected based solely on grammatical necessity,
+ * and that such rules differ between languages. Do not assume you know which string
+ * will be returned for a given quantity. See
+ * <a href="{@docRoot}guide/topics/resources/string-resource.html#Plurals">String Resources</a>
+ * for more detail.
*
- * <p>See <a href="{@docRoot}guide/topics/resources/string-resource.html#Plurals">String
- * Resources</a> for more on quantity strings.
+ * <p>Substitution of format arguments works as if using
+ * {@link java.util.Formatter} and {@link java.lang.String#format}.
+ * The resulting string will be stripped of any styled text information.
*
* @param id The desired resource identifier, as generated by the aapt
* tool. This integer encodes the package, type, and resource
@@ -373,11 +378,13 @@
}
/**
- * Return the string value associated with a particular resource ID for a particular
- * numerical quantity.
- *
- * <p>See <a href="{@docRoot}guide/topics/resources/string-resource.html#Plurals">String
- * Resources</a> for more on quantity strings.
+ * Returns the string necessary for grammatically correct pluralization
+ * of the given resource ID for the given quantity.
+ * Note that the string is selected based solely on grammatical necessity,
+ * and that such rules differ between languages. Do not assume you know which string
+ * will be returned for a given quantity. See
+ * <a href="{@docRoot}guide/topics/resources/string-resource.html#Plurals">String Resources</a>
+ * for more detail.
*
* @param id The desired resource identifier, as generated by the aapt
* tool. This integer encodes the package, type, and resource
diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java
index b9362da..5d13a18 100644
--- a/core/java/android/net/LinkProperties.java
+++ b/core/java/android/net/LinkProperties.java
@@ -92,6 +92,11 @@
public void setInterfaceName(String iface) {
mIfaceName = iface;
+ ArrayList<RouteInfo> newRoutes = new ArrayList<RouteInfo>(mRoutes.size());
+ for (RouteInfo route : mRoutes) {
+ newRoutes.add(routeWithInterface(route));
+ }
+ mRoutes = newRoutes;
}
public String getInterfaceName() {
@@ -130,9 +135,25 @@
mDomains = domains;
}
- public void addRoute(RouteInfo route) {
- if (route != null) mRoutes.add(route);
+ private RouteInfo routeWithInterface(RouteInfo route) {
+ return new RouteInfo(
+ route.getDestination(),
+ route.getGateway(),
+ mIfaceName);
}
+
+ public void addRoute(RouteInfo route) {
+ if (route != null) {
+ String routeIface = route.getInterface();
+ if (routeIface != null && !routeIface.equals(mIfaceName)) {
+ throw new IllegalArgumentException(
+ "Route added with non-matching interface: " + routeIface +
+ " vs. " + mIfaceName);
+ }
+ mRoutes.add(routeWithInterface(route));
+ }
+ }
+
public Collection<RouteInfo> getRoutes() {
return Collections.unmodifiableCollection(mRoutes);
}
@@ -349,7 +370,7 @@
public CompareResult<RouteInfo> compareRoutes(LinkProperties target) {
/*
* Duplicate the RouteInfos into removed, we will be removing
- * routes which are common between mDnses and target
+ * routes which are common between mRoutes and target
* leaving the routes that are different. And route address which
* are in target but not in mRoutes are placed in added.
*/
diff --git a/core/java/android/net/RouteInfo.java b/core/java/android/net/RouteInfo.java
index 112e143..3a7abc0 100644
--- a/core/java/android/net/RouteInfo.java
+++ b/core/java/android/net/RouteInfo.java
@@ -29,6 +29,17 @@
/**
* A simple container for route information.
*
+ * In order to be used, a route must have a destination prefix and:
+ *
+ * - A gateway address (next-hop, for gatewayed routes), or
+ * - An interface (for directly-connected routes), or
+ * - Both a gateway and an interface.
+ *
+ * This class does not enforce these constraints because there is code that
+ * uses RouteInfo objects to store directly-connected routes without interfaces.
+ * Such objects cannot be used directly, but can be put into a LinkProperties
+ * object which then specifies the interface.
+ *
* @hide
*/
public class RouteInfo implements Parcelable {
@@ -42,10 +53,30 @@
*/
private final InetAddress mGateway;
+ /**
+ * The interface for this route.
+ */
+ private final String mInterface;
+
private final boolean mIsDefault;
private final boolean mIsHost;
- public RouteInfo(LinkAddress destination, InetAddress gateway) {
+ /**
+ * Constructs a RouteInfo object.
+ *
+ * If destination is null, then gateway must be specified and the
+ * constructed route is either the IPv4 default route <code>0.0.0.0</code>
+ * if @gateway is an instance of {@link Inet4Address}, or the IPv6 default
+ * route <code>::/0</code> if gateway is an instance of
+ * {@link Inet6Address}.
+ *
+ * destination and gateway may not both be null.
+ *
+ * @param destination the destination prefix
+ * @param gateway the IP address to route packets through
+ * @param iface the interface name to send packets on
+ */
+ public RouteInfo(LinkAddress destination, InetAddress gateway, String iface) {
if (destination == null) {
if (gateway != null) {
if (gateway instanceof Inet4Address) {
@@ -55,7 +86,8 @@
}
} else {
// no destination, no gateway. invalid.
- throw new RuntimeException("Invalid arguments passed in.");
+ throw new IllegalArgumentException("Invalid arguments passed in: " + gateway + "," +
+ destination);
}
}
if (gateway == null) {
@@ -68,29 +100,34 @@
mDestination = new LinkAddress(NetworkUtils.getNetworkPart(destination.getAddress(),
destination.getNetworkPrefixLength()), destination.getNetworkPrefixLength());
mGateway = gateway;
+ mInterface = iface;
mIsDefault = isDefault();
mIsHost = isHost();
}
+ public RouteInfo(LinkAddress destination, InetAddress gateway) {
+ this(destination, gateway, null);
+ }
+
public RouteInfo(InetAddress gateway) {
- this(null, gateway);
+ this(null, gateway, null);
}
public RouteInfo(LinkAddress host) {
- this(host, null);
+ this(host, null, null);
}
- public static RouteInfo makeHostRoute(InetAddress host) {
- return makeHostRoute(host, null);
+ public static RouteInfo makeHostRoute(InetAddress host, String iface) {
+ return makeHostRoute(host, null, iface);
}
- public static RouteInfo makeHostRoute(InetAddress host, InetAddress gateway) {
+ public static RouteInfo makeHostRoute(InetAddress host, InetAddress gateway, String iface) {
if (host == null) return null;
if (host instanceof Inet4Address) {
- return new RouteInfo(new LinkAddress(host, 32), gateway);
+ return new RouteInfo(new LinkAddress(host, 32), gateway, iface);
} else {
- return new RouteInfo(new LinkAddress(host, 128), gateway);
+ return new RouteInfo(new LinkAddress(host, 128), gateway, iface);
}
}
@@ -119,6 +156,10 @@
return mGateway;
}
+ public String getInterface() {
+ return mInterface;
+ }
+
public boolean isDefaultRoute() {
return mIsDefault;
}
@@ -153,6 +194,8 @@
dest.writeByte((byte) 1);
dest.writeByteArray(mGateway.getAddress());
}
+
+ dest.writeString(mInterface);
}
@Override
@@ -171,14 +214,19 @@
target.getGateway() == null
: mGateway.equals(target.getGateway());
- return sameDestination && sameAddress
+ boolean sameInterface = (mInterface == null) ?
+ target.getInterface() == null
+ : mInterface.equals(target.getInterface());
+
+ return sameDestination && sameAddress && sameInterface
&& mIsDefault == target.mIsDefault;
}
@Override
public int hashCode() {
- return (mDestination == null ? 0 : mDestination.hashCode())
- + (mGateway == null ? 0 :mGateway.hashCode())
+ return (mDestination == null ? 0 : mDestination.hashCode() * 41)
+ + (mGateway == null ? 0 :mGateway.hashCode() * 47)
+ + (mInterface == null ? 0 :mInterface.hashCode() * 67)
+ (mIsDefault ? 3 : 7);
}
@@ -206,13 +254,15 @@
} catch (UnknownHostException e) {}
}
+ String iface = in.readString();
+
LinkAddress dest = null;
if (destAddr != null) {
dest = new LinkAddress(destAddr, prefix);
}
- return new RouteInfo(dest, gateway);
+ return new RouteInfo(dest, gateway, iface);
}
public RouteInfo[] newArray(int size) {
@@ -220,13 +270,9 @@
}
};
- private boolean matches(InetAddress destination) {
+ protected boolean matches(InetAddress destination) {
if (destination == null) return false;
- // if the destination is present and the route is default.
- // return true
- if (isDefault()) return true;
-
// match the route destination and destination with prefix length
InetAddress dstNet = NetworkUtils.getNetworkPart(destination,
mDestination.getNetworkPrefixLength());
diff --git a/core/java/android/net/SSLCertificateSocketFactory.java b/core/java/android/net/SSLCertificateSocketFactory.java
index c0a894b..2a2f7cf 100644
--- a/core/java/android/net/SSLCertificateSocketFactory.java
+++ b/core/java/android/net/SSLCertificateSocketFactory.java
@@ -23,8 +23,8 @@
import java.net.Socket;
import java.net.SocketException;
import java.security.KeyManagementException;
+import java.security.PrivateKey;
import java.security.cert.X509Certificate;
-import java.security.interfaces.ECPrivateKey;
import javax.net.SocketFactory;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
@@ -89,7 +89,7 @@
private TrustManager[] mTrustManagers = null;
private KeyManager[] mKeyManagers = null;
private byte[] mNpnProtocols = null;
- private ECPrivateKey mChannelIdPrivateKey = null;
+ private PrivateKey mChannelIdPrivateKey = null;
private final int mHandshakeTimeoutMillis;
private final SSLClientSessionCache mSessionCache;
@@ -321,7 +321,7 @@
}
/**
- * Sets the {@link ECPrivateKey} to be used for TLS Channel ID by connections made by this
+ * Sets the private key to be used for TLS Channel ID by connections made by this
* factory.
*
* @param privateKey private key (enables TLS Channel ID) or {@code null} for no key (disables
@@ -330,7 +330,7 @@
*
* @hide
*/
- public void setChannelIdPrivateKey(ECPrivateKey privateKey) {
+ public void setChannelIdPrivateKey(PrivateKey privateKey) {
mChannelIdPrivateKey = privateKey;
}
diff --git a/core/java/android/nfc/tech/NfcBarcode.java b/core/java/android/nfc/tech/NfcBarcode.java
index 3149857..76627de 100644
--- a/core/java/android/nfc/tech/NfcBarcode.java
+++ b/core/java/android/nfc/tech/NfcBarcode.java
@@ -86,6 +86,28 @@
/**
* Returns the barcode of an NfcBarcode tag.
*
+ * <p> Tags of {@link #TYPE_KOVIO} return 16 bytes:
+ * <ul>
+ * <p> The first byte is 0x80 ORd with a manufacturer ID, corresponding
+ * to ISO/IEC 7816-6.
+ * <p> The second byte describes the payload data format. Defined data
+ * format types include the following:<ul>
+ * <li>0x00: Reserved for manufacturer assignment</li>
+ * <li>0x01: 96-bit URL with "http://www." prefix</li>
+ * <li>0x02: 96-bit URL with "https://www." prefix</li>
+ * <li>0x03: 96-bit URL with "http://" prefix</li>
+ * <li>0x04: 96-bit URL with "https://" prefix</li>
+ * <li>0x05: 96-bit GS1 EPC</li>
+ * <li>0x06-0xFF: reserved</li>
+ * </ul>
+ * <p>The following 12 bytes are payload:<ul>
+ * <li> In case of a URL payload, the payload is encoded in US-ASCII,
+ * following the limitations defined in RF3987,
+ * {@see http://www.ietf.org/rfc/rfc3987.txt}</li>
+ * <li> In case of GS1 EPC daya, {@see http://www.gs1.org/gsmp/kc/epcglobal/tds/}
+ * for more details.</li></ul>
+ * <p>The last 2 bytes comprise the CRC.
+ * </ul>
* <p>Does not cause any RF activity and does not block.
*
* @return a byte array containing the barcode
diff --git a/core/java/android/nfc/tech/TagTechnology.java b/core/java/android/nfc/tech/TagTechnology.java
index 3493ea7..0e2c7c1 100644
--- a/core/java/android/nfc/tech/TagTechnology.java
+++ b/core/java/android/nfc/tech/TagTechnology.java
@@ -50,6 +50,7 @@
* <ul>
* <li>{@link MifareClassic}
* <li>{@link MifareUltralight}
+ * <li>{@link NfcBarcode}
* <li>{@link NdefFormatable} must only be enumerated on tags for which this Android device
* is capable of formatting. Proprietary knowledge is often required to format a tag
* to make it NDEF compatible.
diff --git a/core/java/android/os/Bundle.java b/core/java/android/os/Bundle.java
index 18a0018..b8769b4 100644
--- a/core/java/android/os/Bundle.java
+++ b/core/java/android/os/Bundle.java
@@ -218,7 +218,7 @@
return;
}
if (mMap == null) {
- mMap = new HashMap<String, Object>();
+ mMap = new HashMap<String, Object>(N);
}
mParcelledData.readMapInternal(mMap, N, mClassLoader);
mParcelledData.recycle();
diff --git a/core/java/android/text/format/DateFormat.java b/core/java/android/text/format/DateFormat.java
index 7e230ac..be4663d 100644
--- a/core/java/android/text/format/DateFormat.java
+++ b/core/java/android/text/format/DateFormat.java
@@ -34,178 +34,72 @@
import libcore.icu.LocaleData;
/**
- Utility class for producing strings with formatted date/time.
-
- <p>
- Most callers should avoid supplying their own format strings to this
- class' {@code format} methods and rely on the correctly localized ones
- supplied by the system. This class' factory methods return
- appropriately-localized {@link java.text.DateFormat} instances, suitable
- for both formatting and parsing dates. For the canonical documentation
- of format strings, see {@link java.text.SimpleDateFormat}.
- </p>
- <p>
- The format methods in this class takes as inputs a format string and a representation of a date/time.
- The format string controls how the output is generated.
- This class only supports a subset of the full Unicode specification.
- Use {@link java.text.SimpleDateFormat} if you need more.
- Formatting characters may be repeated in order to get more detailed representations
- of that field. For instance, the format character 'M' is used to
- represent the month. Depending on how many times that character is repeated
- you get a different representation.
- </p>
- <p>
- For the month of September:<br/>
- M -> 9<br/>
- MM -> 09<br/>
- MMM -> Sep<br/>
- MMMM -> September
- </p>
- <p>
- The effects of the duplication vary depending on the nature of the field.
- See the notes on the individual field formatters for details. For purely numeric
- fields such as <code>HOUR</code> adding more copies of the designator will
- zero-pad the value to that number of characters.
- </p>
- <p>
- For 7 minutes past the hour:<br/>
- m -> 7<br/>
- mm -> 07<br/>
- mmm -> 007<br/>
- mmmm -> 0007
- </p>
- <p>
- Examples for April 6, 1970 at 3:23am:<br/>
- "MM/dd/yy h:mmaa" -> "04/06/70 3:23am"<br/>
- "MMM dd, yyyy h:mmaa" -> "Apr 6, 1970 3:23am"<br/>
- "MMMM dd, yyyy h:mmaa" -> "April 6, 1970 3:23am"<br/>
- "E, MMMM dd, yyyy h:mmaa" -> "Mon, April 6, 1970 3:23am&<br/>
- "EEEE, MMMM dd, yyyy h:mmaa" -> "Monday, April 6, 1970 3:23am"<br/>
- "'Noteworthy day: 'M/d/yy" -> "Noteworthy day: 4/6/70"
+ * Utility class for producing strings with formatted date/time.
+ *
+ * <p>Most callers should avoid supplying their own format strings to this
+ * class' {@code format} methods and rely on the correctly localized ones
+ * supplied by the system. This class' factory methods return
+ * appropriately-localized {@link java.text.DateFormat} instances, suitable
+ * for both formatting and parsing dates. For the canonical documentation
+ * of format strings, see {@link java.text.SimpleDateFormat}.
+ *
+ * <p>The format methods in this class implement a subset of Unicode
+ * <a href="http://www.unicode.org/reports/tr35/#Date_Format_Patterns">UTS #35</a> patterns.
+ * The subset supported by this class includes the following format characters:
+ * {@code acdEHhLKkLMmsyz}. See {@link java.text.SimpleDateFormat} for more documentation
+ * about patterns, or if you need a more compete implementation.
*/
-
public class DateFormat {
- /**
- Text in the format string that should be copied verbatim rather that
- interpreted as formatting codes must be surrounded by the <code>QUOTE</code>
- character. If you need to embed a literal <code>QUOTE</code> character in
- the output text then use two in a row.
- */
+ /** @deprecated Use a literal {@code '} instead. */
+ @Deprecated
public static final char QUOTE = '\'';
-
- /**
- This designator indicates whether the <code>HOUR</code> field is before
- or after noon. The output is lower-case.
-
- Examples:
- a -> a or p
- aa -> am or pm
- */
+
+ /** @deprecated Use a literal {@code 'a'} instead. */
+ @Deprecated
public static final char AM_PM = 'a';
- /**
- This designator indicates whether the <code>HOUR</code> field is before
- or after noon. The output is capitalized.
-
- Examples:
- A -> A or P
- AA -> AM or PM
- */
+ /** @deprecated Use a literal {@code 'a'} instead; 'A' was always equivalent to 'a'. */
+ @Deprecated
public static final char CAPITAL_AM_PM = 'A';
- /**
- This designator indicates the day of the month.
-
- Examples for the 9th of the month:
- d -> 9
- dd -> 09
- */
+ /** @deprecated Use a literal {@code 'd'} instead. */
+ @Deprecated
public static final char DATE = 'd';
- /**
- This designator indicates the name of the day of the week.
-
- Examples for Sunday:
- E -> Sun
- EEEE -> Sunday
- */
+ /** @deprecated Use a literal {@code 'E'} instead. */
+ @Deprecated
public static final char DAY = 'E';
- /**
- This designator indicates the hour of the day in 12 hour format.
-
- Examples for 3pm:
- h -> 3
- hh -> 03
- */
+ /** @deprecated Use a literal {@code 'h'} instead. */
+ @Deprecated
public static final char HOUR = 'h';
- /**
- This designator indicates the hour of the day in 24 hour format.
-
- Example for 3pm:
- k -> 15
-
- Examples for midnight:
- k -> 0
- kk -> 00
- */
+ /** @deprecated Use a literal {@code 'k'} instead. */
+ @Deprecated
public static final char HOUR_OF_DAY = 'k';
- /**
- This designator indicates the minute of the hour.
-
- Examples for 7 minutes past the hour:
- m -> 7
- mm -> 07
- */
+ /** @deprecated Use a literal {@code 'm'} instead. */
+ @Deprecated
public static final char MINUTE = 'm';
- /**
- This designator indicates the month of the year. See also
- {@link #STANDALONE_MONTH}.
-
- Examples for September:
- M -> 9
- MM -> 09
- MMM -> Sep
- MMMM -> September
- */
+ /** @deprecated Use a literal {@code 'M'} instead. */
+ @Deprecated
public static final char MONTH = 'M';
- /**
- This designator indicates the standalone month of the year,
- necessary in some format strings in some languages. For
- example, Russian distinguishes between the "June" in
- "June" and that in "June 2010".
- */
+ /** @deprecated Use a literal {@code 'L'} instead. */
+ @Deprecated
public static final char STANDALONE_MONTH = 'L';
- /**
- This designator indicates the seconds of the minute.
-
- Examples for 7 seconds past the minute:
- s -> 7
- ss -> 07
- */
+ /** @deprecated Use a literal {@code 's'} instead. */
+ @Deprecated
public static final char SECONDS = 's';
- /**
- This designator indicates the offset of the timezone from GMT.
-
- Example for US/Pacific timezone:
- z -> -0800
- zz -> PST
- */
+ /** @deprecated Use a literal {@code 'z'} instead. */
+ @Deprecated
public static final char TIME_ZONE = 'z';
- /**
- This designator indicates the year.
-
- Examples for 2006
- y -> 06
- yyyy -> 2006
- */
+ /** @deprecated Use a literal {@code 'y'} instead. */
+ @Deprecated
public static final char YEAR = 'y';
@@ -233,8 +127,7 @@
}
java.text.DateFormat natural =
- java.text.DateFormat.getTimeInstance(
- java.text.DateFormat.LONG, locale);
+ java.text.DateFormat.getTimeInstance(java.text.DateFormat.LONG, locale);
if (natural instanceof SimpleDateFormat) {
SimpleDateFormat sdf = (SimpleDateFormat) natural;
@@ -273,7 +166,7 @@
}
/**
- * Returns a {@link java.text.DateFormat} object that can format the date
+ * Returns a {@link java.text.DateFormat} object that can format the date
* in short form (such as 12/31/1999) according
* to the current locale and the user's date-order preference.
* @param context the application context
@@ -298,7 +191,6 @@
public static java.text.DateFormat getDateFormatForSetting(Context context,
String value) {
String format = getDateFormatStringForSetting(context, value);
-
return new java.text.SimpleDateFormat(format);
}
@@ -342,10 +234,10 @@
value = context.getString(R.string.numeric_date_format);
return value;
}
-
+
/**
* Returns a {@link java.text.DateFormat} object that can format the date
- * in long form (such as December 31, 1999) for the current locale.
+ * in long form (such as {@code Monday, January 3, 2000}) for the current locale.
* @param context the application context
* @return the {@link java.text.DateFormat} object that formats the date in long form.
*/
@@ -355,7 +247,7 @@
/**
* Returns a {@link java.text.DateFormat} object that can format the date
- * in medium form (such as Dec. 31, 1999) for the current locale.
+ * in medium form (such as {@code Jan 3, 2000}) for the current locale.
* @param context the application context
* @return the {@link java.text.DateFormat} object that formats the date in long form.
*/
@@ -365,13 +257,13 @@
/**
* Gets the current date format stored as a char array. The array will contain
- * 3 elements ({@link #DATE}, {@link #MONTH}, and {@link #YEAR}) in the order
+ * 3 elements ({@link #DATE}, {@link #MONTH}, and {@link #YEAR}) in the order
* specified by the user's format preference. Note that this order is
* only appropriate for all-numeric dates; spelled-out (MEDIUM and LONG)
* dates will generally contain other punctuation, spaces, or words,
* not just the day, month, and year, and not necessarily in the same
* order returned here.
- */
+ */
public static char[] getDateFormatOrder(Context context) {
char[] order = new char[] {DATE, MONTH, YEAR};
String value = getDateFormatString(context);
@@ -401,7 +293,7 @@
}
return order;
}
-
+
private static String getDateFormatString(Context context) {
String value = Settings.System.getString(context.getContentResolver(),
Settings.System.DATE_FORMAT);
@@ -410,7 +302,7 @@
}
/**
- * Given a format string and a time in milliseconds since Jan 1, 1970 GMT, returns a
+ * Given a format string and a time in milliseconds since Jan 1, 1970 GMT, returns a
* CharSequence containing the requested date.
* @param inFormat the format string, as described in {@link android.text.format.DateFormat}
* @param inTimeInMillis in milliseconds since Jan 1, 1970 GMT
@@ -428,22 +320,20 @@
* @return a {@link CharSequence} containing the requested text
*/
public static CharSequence format(CharSequence inFormat, Date inDate) {
- Calendar c = new GregorianCalendar();
-
+ Calendar c = new GregorianCalendar();
c.setTime(inDate);
-
return format(inFormat, c);
}
/**
* Indicates whether the specified format string contains seconds.
- *
+ *
* Always returns false if the input format is null.
- *
+ *
* @param inFormat the format string, as described in {@link android.text.format.DateFormat}
- *
+ *
* @return true if the format string contains {@link #SECONDS}, false otherwise
- *
+ *
* @hide
*/
public static boolean hasSeconds(CharSequence inFormat) {
@@ -508,24 +398,23 @@
}
/**
- * Given a format string and a {@link java.util.Calendar} object, returns a CharSequence
+ * Given a format string and a {@link java.util.Calendar} object, returns a CharSequence
* containing the requested date.
* @param inFormat the format string, as described in {@link android.text.format.DateFormat}
* @param inDate the date to format
* @return a {@link CharSequence} containing the requested text
*/
public static CharSequence format(CharSequence inFormat, Calendar inDate) {
- SpannableStringBuilder s = new SpannableStringBuilder(inFormat);
- int c;
- int count;
+ SpannableStringBuilder s = new SpannableStringBuilder(inFormat);
+ int count;
+
+ LocaleData localeData = LocaleData.get(Locale.getDefault());
int len = inFormat.length();
for (int i = 0; i < len; i += count) {
- int temp;
-
count = 1;
- c = s.charAt(i);
+ int c = s.charAt(i);
if (c == QUOTE) {
count = appendQuotedText(s, i, len);
@@ -538,102 +427,102 @@
}
String replacement;
-
switch (c) {
- case AM_PM:
- replacement = DateUtils.getAMPMString(inDate.get(Calendar.AM_PM));
+ case 'A':
+ case 'a':
+ replacement = localeData.amPm[inDate.get(Calendar.AM_PM) - Calendar.AM];
break;
-
- case CAPITAL_AM_PM:
- //FIXME: this is the same as AM_PM? no capital?
- replacement = DateUtils.getAMPMString(inDate.get(Calendar.AM_PM));
- break;
-
- case DATE:
+ case 'd':
replacement = zeroPad(inDate.get(Calendar.DATE), count);
break;
-
- case DAY:
- temp = inDate.get(Calendar.DAY_OF_WEEK);
- replacement = DateUtils.getDayOfWeekString(temp,
- count < 4 ?
- DateUtils.LENGTH_MEDIUM :
- DateUtils.LENGTH_LONG);
+ case 'c':
+ case 'E':
+ replacement = getDayOfWeekString(localeData,
+ inDate.get(Calendar.DAY_OF_WEEK), count, c);
break;
-
- case HOUR:
- temp = inDate.get(Calendar.HOUR);
-
- if (0 == temp)
- temp = 12;
-
- replacement = zeroPad(temp, count);
+ case 'K': // hour in am/pm (0-11)
+ case 'h': // hour in am/pm (1-12)
+ {
+ int hour = inDate.get(Calendar.HOUR);
+ if (c == 'h' && hour == 0) {
+ hour = 12;
+ }
+ replacement = zeroPad(hour, count);
+ }
break;
-
- case HOUR_OF_DAY:
- replacement = zeroPad(inDate.get(Calendar.HOUR_OF_DAY), count);
+ case 'H': // hour in day (0-23)
+ case 'k': // hour in day (1-24)
+ {
+ int hour = inDate.get(Calendar.HOUR_OF_DAY);
+ if (c == 'k' && hour == 0) {
+ hour = 24;
+ }
+ replacement = zeroPad(hour, count);
+ }
break;
-
- case MINUTE:
+ case 'L':
+ case 'M':
+ replacement = getMonthString(localeData,
+ inDate.get(Calendar.MONTH), count, c);
+ break;
+ case 'm':
replacement = zeroPad(inDate.get(Calendar.MINUTE), count);
break;
-
- case MONTH:
- case STANDALONE_MONTH:
- replacement = getMonthString(inDate, count, c);
- break;
-
- case SECONDS:
+ case 's':
replacement = zeroPad(inDate.get(Calendar.SECOND), count);
break;
-
- case TIME_ZONE:
+ case 'y':
+ replacement = getYearString(inDate.get(Calendar.YEAR), count);
+ break;
+ case 'z':
replacement = getTimeZoneString(inDate, count);
break;
-
- case YEAR:
- replacement = getYearString(inDate, count);
- break;
-
default:
replacement = null;
break;
}
-
+
if (replacement != null) {
s.replace(i, i + count, replacement);
count = replacement.length(); // CARE: count is used in the for loop above
len = s.length();
}
}
-
- if (inFormat instanceof Spanned)
+
+ if (inFormat instanceof Spanned) {
return new SpannedString(s);
- else
+ } else {
return s.toString();
+ }
}
-
- private static String getMonthString(Calendar inDate, int count, int kind) {
- boolean standalone = (kind == STANDALONE_MONTH);
- int month = inDate.get(Calendar.MONTH);
-
- if (count >= 4) {
- return standalone
- ? DateUtils.getStandaloneMonthString(month, DateUtils.LENGTH_LONG)
- : DateUtils.getMonthString(month, DateUtils.LENGTH_LONG);
+
+ private static String getDayOfWeekString(LocaleData ld, int day, int count, int kind) {
+ boolean standalone = (kind == 'c');
+ if (count == 5) {
+ return standalone ? ld.tinyStandAloneWeekdayNames[day] : ld.tinyWeekdayNames[day];
+ } else if (count == 4) {
+ return standalone ? ld.longStandAloneWeekdayNames[day] : ld.longWeekdayNames[day];
+ } else {
+ return standalone ? ld.shortStandAloneWeekdayNames[day] : ld.shortWeekdayNames[day];
+ }
+ }
+
+ private static String getMonthString(LocaleData ld, int month, int count, int kind) {
+ boolean standalone = (kind == 'L');
+ if (count == 5) {
+ return standalone ? ld.tinyStandAloneMonthNames[month] : ld.tinyMonthNames[month];
+ } else if (count == 4) {
+ return standalone ? ld.longStandAloneMonthNames[month] : ld.longMonthNames[month];
} else if (count == 3) {
- return standalone
- ? DateUtils.getStandaloneMonthString(month, DateUtils.LENGTH_MEDIUM)
- : DateUtils.getMonthString(month, DateUtils.LENGTH_MEDIUM);
+ return standalone ? ld.shortStandAloneMonthNames[month] : ld.shortMonthNames[month];
} else {
// Calendar.JANUARY == 0, so add 1 to month.
return zeroPad(month+1, count);
}
}
-
+
private static String getTimeZoneString(Calendar inDate, int count) {
TimeZone tz = inDate.getTimeZone();
-
if (count < 2) { // FIXME: shouldn't this be <= 2 ?
return formatZoneOffset(inDate.get(Calendar.DST_OFFSET) +
inDate.get(Calendar.ZONE_OFFSET),
@@ -662,13 +551,12 @@
tb.append(zeroPad(minutes, 2));
return tb.toString();
}
-
- private static String getYearString(Calendar inDate, int count) {
- int year = inDate.get(Calendar.YEAR);
+
+ private static String getYearString(int year, int count) {
return (count <= 2) ? zeroPad(year % 100, 2)
: String.format(Locale.getDefault(), "%d", year);
}
-
+
private static int appendQuotedText(SpannableStringBuilder s, int i, int len) {
if (i + 1 < len && s.charAt(i + 1) == QUOTE) {
s.delete(i, i + 1);
diff --git a/core/java/android/text/format/DateUtils.java b/core/java/android/text/format/DateUtils.java
index 8920b24..6c8a737 100644
--- a/core/java/android/text/format/DateUtils.java
+++ b/core/java/android/text/format/DateUtils.java
@@ -274,10 +274,6 @@
*/
@Deprecated
public static String getMonthString(int month, int abbrev) {
- // Note that here we use d.shortMonthNames for MEDIUM, SHORT and SHORTER.
- // This is a shortcut to not spam the translators with too many variations
- // of the same string. If we find that in a language the distinction
- // is necessary, we can can add more without changing this API.
LocaleData d = LocaleData.get(Locale.getDefault());
String[] names;
switch (abbrev) {
@@ -308,19 +304,14 @@
*/
@Deprecated
public static String getStandaloneMonthString(int month, int abbrev) {
- // Note that here we use d.shortMonthNames for MEDIUM, SHORT and SHORTER.
- // This is a shortcut to not spam the translators with too many variations
- // of the same string. If we find that in a language the distinction
- // is necessary, we can can add more without changing this API.
LocaleData d = LocaleData.get(Locale.getDefault());
String[] names;
switch (abbrev) {
- case LENGTH_LONG: names = d.longStandAloneMonthNames;
- break;
+ case LENGTH_LONG: names = d.longStandAloneMonthNames; break;
case LENGTH_MEDIUM: names = d.shortMonthNames; break;
case LENGTH_SHORT: names = d.shortMonthNames; break;
case LENGTH_SHORTER: names = d.shortMonthNames; break;
- case LENGTH_SHORTEST: names = d.tinyMonthNames; break;
+ case LENGTH_SHORTEST: names = d.tinyStandAloneMonthNames; break;
default: names = d.shortMonthNames; break;
}
return names[month];
@@ -429,20 +420,7 @@
}
}
} else if (duration < WEEK_IN_MILLIS && minResolution < WEEK_IN_MILLIS) {
- count = getNumberOfDaysPassed(time, now);
- if (past) {
- if (abbrevRelative) {
- resId = com.android.internal.R.plurals.abbrev_num_days_ago;
- } else {
- resId = com.android.internal.R.plurals.num_days_ago;
- }
- } else {
- if (abbrevRelative) {
- resId = com.android.internal.R.plurals.abbrev_in_num_days;
- } else {
- resId = com.android.internal.R.plurals.in_num_days;
- }
- }
+ return getRelativeDayString(r, time, now);
} else {
// We know that we won't be showing the time, so it is safe to pass
// in a null context.
@@ -454,24 +432,6 @@
}
/**
- * Returns the number of days passed between two dates.
- *
- * @param date1 first date
- * @param date2 second date
- * @return number of days passed between to dates.
- */
- private synchronized static long getNumberOfDaysPassed(long date1, long date2) {
- if (sThenTime == null) {
- sThenTime = new Time();
- }
- sThenTime.set(date1);
- int day1 = Time.getJulianDay(date1, sThenTime.gmtoff);
- sThenTime.set(date2);
- int day2 = Time.getJulianDay(date2, sThenTime.gmtoff);
- return Math.abs(day2 - day1);
- }
-
- /**
* Return string describing the elapsed time since startTime formatted like
* "[relative time/date], [time]".
* <p>
@@ -529,28 +489,29 @@
* today this function returns "Today", if the day was a week ago it returns "7 days ago", and
* if the day is in 2 weeks it returns "in 14 days".
*
- * @param r the resources to get the strings from
+ * @param r the resources
* @param day the relative day to describe in UTC milliseconds
* @param today the current time in UTC milliseconds
- * @return a formatting string
*/
private static final String getRelativeDayString(Resources r, long day, long today) {
+ Locale locale = r.getConfiguration().locale;
+ if (locale == null) {
+ locale = Locale.getDefault();
+ }
+
+ // TODO: use TimeZone.getOffset instead.
Time startTime = new Time();
startTime.set(day);
+ int startDay = Time.getJulianDay(day, startTime.gmtoff);
+
Time currentTime = new Time();
currentTime.set(today);
-
- int startDay = Time.getJulianDay(day, startTime.gmtoff);
int currentDay = Time.getJulianDay(today, currentTime.gmtoff);
int days = Math.abs(currentDay - startDay);
boolean past = (today > day);
// TODO: some locales name other days too, such as de_DE's "Vorgestern" (today - 2).
- Locale locale = r.getConfiguration().locale;
- if (locale == null) {
- locale = Locale.getDefault();
- }
if (days == 1) {
if (past) {
return LocaleData.get(locale).yesterday;
@@ -1096,30 +1057,34 @@
// computation below that'd otherwise be thrown out.
boolean isInstant = (startMillis == endMillis);
- Time startDate;
+ Calendar startCalendar, endCalendar;
+ Time startDate = new Time();
if (timeZone != null) {
- startDate = new Time(timeZone);
+ startCalendar = Calendar.getInstance(TimeZone.getTimeZone(timeZone));
} else if (useUTC) {
- startDate = new Time(Time.TIMEZONE_UTC);
+ startCalendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
} else {
- startDate = new Time();
+ startCalendar = Calendar.getInstance();
}
- startDate.set(startMillis);
+ startCalendar.setTimeInMillis(startMillis);
+ setTimeFromCalendar(startDate, startCalendar);
- Time endDate;
+ Time endDate = new Time();
int dayDistance;
if (isInstant) {
endDate = startDate;
dayDistance = 0;
} else {
if (timeZone != null) {
- endDate = new Time(timeZone);
+ endCalendar = Calendar.getInstance(TimeZone.getTimeZone(timeZone));
} else if (useUTC) {
- endDate = new Time(Time.TIMEZONE_UTC);
+ endCalendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
} else {
- endDate = new Time();
+ endCalendar = Calendar.getInstance();
}
- endDate.set(endMillis);
+ endCalendar.setTimeInMillis(endMillis);
+ setTimeFromCalendar(endDate, endCalendar);
+
int startJulianDay = Time.getJulianDay(startMillis, startDate.gmtoff);
int endJulianDay = Time.getJulianDay(endMillis, endDate.gmtoff);
dayDistance = endJulianDay - startJulianDay;
@@ -1462,6 +1427,20 @@
return formatter.format(fullFormat, timeString, startWeekDayString, dateString);
}
+ private static void setTimeFromCalendar(Time t, Calendar c) {
+ t.hour = c.get(Calendar.HOUR_OF_DAY);
+ t.minute = c.get(Calendar.MINUTE);
+ t.month = c.get(Calendar.MONTH);
+ t.monthDay = c.get(Calendar.DAY_OF_MONTH);
+ t.second = c.get(Calendar.SECOND);
+ t.weekDay = c.get(Calendar.DAY_OF_WEEK) - 1;
+ t.year = c.get(Calendar.YEAR);
+ t.yearDay = c.get(Calendar.DAY_OF_YEAR);
+ t.isDst = (c.get(Calendar.DST_OFFSET) != 0) ? 1 : 0;
+ t.gmtoff = c.get(Calendar.ZONE_OFFSET) + c.get(Calendar.DST_OFFSET);
+ t.timezone = c.getTimeZone().getID();
+ }
+
/**
* Formats a date or a time according to the local conventions. There are
* lots of options that allow the caller to control, for example, if the
diff --git a/core/java/android/view/InputDevice.java b/core/java/android/view/InputDevice.java
index 3bb9c01..dd523d2 100644
--- a/core/java/android/view/InputDevice.java
+++ b/core/java/android/view/InputDevice.java
@@ -62,7 +62,14 @@
* specify the desired interpretation for its input events.
*/
public static final int SOURCE_CLASS_MASK = 0x000000ff;
-
+
+ /**
+ * The input source has no class.
+ *
+ * It is up to the application to determine how to handle the device based on the device type.
+ */
+ public static final int SOURCE_CLASS_NONE = 0x00000000;
+
/**
* The input source has buttons or keys.
* Examples: {@link #SOURCE_KEYBOARD}, {@link #SOURCE_DPAD}.
@@ -202,6 +209,17 @@
public static final int SOURCE_TOUCHPAD = 0x00100000 | SOURCE_CLASS_POSITION;
/**
+ * The input source is a touch device whose motions should be interpreted as navigation events.
+ *
+ * For example, an upward swipe should be as an upward focus traversal in the same manner as
+ * pressing up on a D-Pad would be. Swipes to the left, right and down should be treated in a
+ * similar manner.
+ *
+ * @see #SOURCE_CLASS_NONE
+ */
+ public static final int SOURCE_TOUCH_NAVIGATION = 0x00200000 | SOURCE_CLASS_NONE;
+
+ /**
* The input source is a joystick.
* (It may also be a {@link #SOURCE_GAMEPAD}).
*
@@ -633,6 +651,19 @@
return mSource;
}
+
+ /**
+ * Determines whether the event is from the given source.
+ *
+ * @param source The input source to check against. This can be a specific device type,
+ * such as {@link InputDevice#SOURCE_TOUCH_NAVIGATION}, or a more generic device class,
+ * such as {@link InputDevice#SOURCE_CLASS_POINTER}.
+ * @return Whether the event is from the given source.
+ */
+ public boolean isFromSource(int source) {
+ return (getSource() & source) == source;
+ }
+
/**
* Gets the inclusive minimum value for the axis.
* @return The inclusive minimum value.
diff --git a/core/java/android/view/InputEvent.java b/core/java/android/view/InputEvent.java
index ef810a3..24c3128 100644
--- a/core/java/android/view/InputEvent.java
+++ b/core/java/android/view/InputEvent.java
@@ -83,6 +83,18 @@
public abstract void setSource(int source);
/**
+ * Determines whether the event is from the given source.
+ *
+ * @param source The input source to check against. This can be a specific device type, such as
+ * {@link InputDevice#SOURCE_TOUCH_NAVIGATION}, or a more generic device class, such as
+ * {@link InputDevice#SOURCE_CLASS_POINTER}.
+ * @return Whether the event is from the given source.
+ */
+ public boolean isFromSource(int source) {
+ return (getSource() & source) == source;
+ }
+
+ /**
* Copies the event.
*
* @return A deep copy of the event.
diff --git a/core/java/android/view/SimulatedDpad.java b/core/java/android/view/SimulatedDpad.java
index 883fd49..c889328 100644
--- a/core/java/android/view/SimulatedDpad.java
+++ b/core/java/android/view/SimulatedDpad.java
@@ -28,7 +28,7 @@
import android.util.Log;
/**
- * This class creates DPAD events from touchpad events.
+ * This class creates DPAD events from TouchNavigation events.
*
* @see ViewRootImpl
*/
@@ -47,18 +47,18 @@
private static final int MSG_FLICK = 313;
// TODO: Pass touch slop from the input device
private static final int TOUCH_SLOP = 30;
- // The position of the previous touchpad event
- private float mLastTouchpadXPosition;
- private float mLastTouchpadYPosition;
- // Where the touchpad was initially pressed
- private float mTouchpadEnterXPosition;
- private float mTouchpadEnterYPosition;
+ // The position of the previous TouchNavigation event
+ private float mLastTouchNavigationXPosition;
+ private float mLastTouchNavigationYPosition;
+ // Where the Touch Navigation was initially pressed
+ private float mTouchNavigationEnterXPosition;
+ private float mTouchNavigationEnterYPosition;
// When the most recent ACTION_HOVER_ENTER occurred
- private long mLastTouchPadStartTimeMs = 0;
+ private long mLastTouchNavigationStartTimeMs = 0;
// When the most recent direction key was sent
- private long mLastTouchPadKeySendTimeMs = 0;
+ private long mLastTouchNavigationKeySendTimeMs = 0;
// When the most recent touch event of any type occurred
- private long mLastTouchPadEventTimeMs = 0;
+ private long mLastTouchNavigationEventTimeMs = 0;
// Did the swipe begin in a valid region
private boolean mEdgeSwipePossible;
@@ -140,7 +140,7 @@
}
};
- public void updateTouchPad(ViewRootImpl viewroot, MotionEvent event,
+ public void updateTouchNavigation(ViewRootImpl viewroot, MotionEvent event,
boolean synthesizeNewKeys) {
if (!synthesizeNewKeys) {
mHandler.removeMessages(MSG_FLICK);
@@ -149,14 +149,14 @@
if (device == null) {
return;
}
- // Store what time the touchpad event occurred
+ // Store what time the TouchNavigation event occurred
final long time = SystemClock.uptimeMillis();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
- mLastTouchPadStartTimeMs = time;
+ mLastTouchNavigationStartTimeMs = time;
mAlwaysInTapRegion = true;
- mTouchpadEnterXPosition = event.getX();
- mTouchpadEnterYPosition = event.getY();
+ mTouchNavigationEnterXPosition = event.getX();
+ mTouchNavigationEnterYPosition = event.getY();
mAccumulatedX = 0;
mAccumulatedY = 0;
mLastMoveX = 0;
@@ -173,8 +173,8 @@
break;
case MotionEvent.ACTION_MOVE:
// Determine whether the move is slop or an intentional move
- float deltaX = event.getX() - mTouchpadEnterXPosition;
- float deltaY = event.getY() - mTouchpadEnterYPosition;
+ float deltaX = event.getX() - mTouchNavigationEnterXPosition;
+ float deltaY = event.getY() - mTouchNavigationEnterYPosition;
if (mTouchSlopSquared < deltaX * deltaX + deltaY * deltaY) {
mAlwaysInTapRegion = false;
}
@@ -199,9 +199,9 @@
}
}
// Find the difference in position between the two most recent
- // touchpad events
- mLastMoveX = event.getX() - mLastTouchpadXPosition;
- mLastMoveY = event.getY() - mLastTouchpadYPosition;
+ // TouchNavigation events
+ mLastMoveX = event.getX() - mLastTouchNavigationXPosition;
+ mLastMoveY = event.getY() - mLastTouchNavigationYPosition;
mAccumulatedX += mLastMoveX;
mAccumulatedY += mLastMoveY;
float mAccumulatedXSquared = mAccumulatedX * mAccumulatedX;
@@ -251,28 +251,28 @@
mAccumulatedY = isXAxis ? 0 : dominantAxis;
mLastKeySent = key;
- mKeySendRateMs = (int) ((time - mLastTouchPadKeySendTimeMs) / repeatCount);
- mLastTouchPadKeySendTimeMs = time;
+ mKeySendRateMs = (int) (time - mLastTouchNavigationKeySendTimeMs) / repeatCount;
+ mLastTouchNavigationKeySendTimeMs = time;
}
break;
case MotionEvent.ACTION_UP:
- if (time - mLastTouchPadStartTimeMs < MAX_TAP_TIME && mAlwaysInTapRegion) {
+ if (time - mLastTouchNavigationStartTimeMs < MAX_TAP_TIME && mAlwaysInTapRegion) {
if (synthesizeNewKeys) {
- viewroot.enqueueInputEvent(new KeyEvent(mLastTouchPadStartTimeMs, time,
- KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_CENTER, 0,
- event.getMetaState(), event.getDeviceId(), 0,
- KeyEvent.FLAG_FALLBACK, event.getSource()));
- viewroot.enqueueInputEvent(new KeyEvent(mLastTouchPadStartTimeMs, time,
- KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DPAD_CENTER, 0,
- event.getMetaState(), event.getDeviceId(), 0,
- KeyEvent.FLAG_FALLBACK, event.getSource()));
+ viewroot.enqueueInputEvent(new KeyEvent(mLastTouchNavigationStartTimeMs,
+ time, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_CENTER, 0,
+ event.getMetaState(), event.getDeviceId(), 0,
+ KeyEvent.FLAG_FALLBACK, event.getSource()));
+ viewroot.enqueueInputEvent(new KeyEvent(mLastTouchNavigationStartTimeMs,
+ time, KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DPAD_CENTER, 0,
+ event.getMetaState(), event.getDeviceId(), 0,
+ KeyEvent.FLAG_FALLBACK, event.getSource()));
}
} else {
float xMoveSquared = mLastMoveX * mLastMoveX;
float yMoveSquared = mLastMoveY * mLastMoveY;
// Determine whether the last gesture was a fling.
if (mMinFlickDistanceSquared <= xMoveSquared + yMoveSquared &&
- time - mLastTouchPadEventTimeMs <= MAX_TAP_TIME &&
+ time - mLastTouchNavigationEventTimeMs <= MAX_TAP_TIME &&
mKeySendRateMs <= mMaxRepeatDelay && mKeySendRateMs > 0) {
mLastDeviceId = event.getDeviceId();
mLastSource = event.getSource();
@@ -291,8 +291,8 @@
}
// Store touch event position and time
- mLastTouchPadEventTimeMs = time;
- mLastTouchpadXPosition = event.getX();
- mLastTouchpadYPosition = event.getY();
+ mLastTouchNavigationEventTimeMs = time;
+ mLastTouchNavigationXPosition = event.getX();
+ mLastTouchNavigationYPosition = event.getY();
}
}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 7e0d115..2e60f51 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -8112,13 +8112,13 @@
* delivered to the focused view.
* </p>
* <pre> public boolean onGenericMotionEvent(MotionEvent event) {
- * if ((event.getSource() & InputDevice.SOURCE_CLASS_JOYSTICK) != 0) {
+ * if (event.isFromSource(InputDevice.SOURCE_CLASS_JOYSTICK)) {
* if (event.getAction() == MotionEvent.ACTION_MOVE) {
* // process the joystick movement...
* return true;
* }
* }
- * if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
+ * if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
* switch (event.getAction()) {
* case MotionEvent.ACTION_HOVER_MOVE:
* // process the mouse hover movement...
@@ -10642,7 +10642,7 @@
// Opaque if:
// - Has a background
// - Background is opaque
- // - Doesn't have scrollbars or scrollbars are inside overlay
+ // - Doesn't have scrollbars or scrollbars overlay
if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {
mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND;
@@ -10652,7 +10652,8 @@
final int flags = mViewFlags;
if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
- (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY) {
+ (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY ||
+ (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_OUTSIDE_OVERLAY) {
mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS;
} else {
mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS;
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index b8fae865..a937882 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -3559,15 +3559,15 @@
private int deliverGenericMotionEventPostIme(QueuedInputEvent q) {
final MotionEvent event = (MotionEvent) q.mEvent;
final int source = event.getSource();
- final boolean isJoystick = (source & InputDevice.SOURCE_CLASS_JOYSTICK) != 0;
- final boolean isTouchPad = (source & InputDevice.SOURCE_CLASS_POSITION) != 0;
+ final boolean isJoystick = event.isFromSource(InputDevice.SOURCE_CLASS_JOYSTICK);
+ final boolean isTouchNavigation = event.isFromSource(InputDevice.SOURCE_TOUCH_NAVIGATION);
// If there is no view, then the event will not be handled.
if (mView == null || !mAdded) {
if (isJoystick) {
updateJoystickDirection(event, false);
- } else if (isTouchPad) {
- mSimulatedDpad.updateTouchPad(this, event, false);
+ } else if (isTouchNavigation) {
+ mSimulatedDpad.updateTouchNavigation(this, event, false);
}
return EVENT_NOT_HANDLED;
}
@@ -3576,8 +3576,8 @@
if (mView.dispatchGenericMotionEvent(event)) {
if (isJoystick) {
updateJoystickDirection(event, false);
- } else if (isTouchPad) {
- mSimulatedDpad.updateTouchPad(this, event, false);
+ } else if (isTouchNavigation) {
+ mSimulatedDpad.updateTouchNavigation(this, event, false);
}
return EVENT_HANDLED;
}
@@ -3588,8 +3588,8 @@
updateJoystickDirection(event, true);
return EVENT_HANDLED;
}
- if (isTouchPad) {
- mSimulatedDpad.updateTouchPad(this, event, true);
+ if (isTouchNavigation) {
+ mSimulatedDpad.updateTouchNavigation(this, event, true);
return EVENT_HANDLED;
}
return EVENT_NOT_HANDLED;
diff --git a/core/java/android/webkit/BrowserFrame.java b/core/java/android/webkit/BrowserFrame.java
index 24ac54f..33e8364 100644
--- a/core/java/android/webkit/BrowserFrame.java
+++ b/core/java/android/webkit/BrowserFrame.java
@@ -70,6 +70,7 @@
* request's LoadListener
*/
private final static int MAX_OUTSTANDING_REQUESTS = 300;
+ private final static String SCHEME_HOST_DELIMITER = "://";
private final CallbackProxy mCallbackProxy;
private final WebSettingsClassic mSettings;
@@ -498,9 +499,14 @@
.getCurrentItem();
if (item != null) {
WebAddress uri = new WebAddress(item.getUrl());
- String schemePlusHost = uri.getScheme() + uri.getHost();
+ String schemePlusHost = uri.getScheme() + SCHEME_HOST_DELIMITER +
+ uri.getHost();
String[] up = mDatabase.getUsernamePassword(
schemePlusHost);
+ if (up == null) { // no row found, try again using the legacy method
+ schemePlusHost = uri.getScheme() + uri.getHost();
+ up = mDatabase.getUsernamePassword(schemePlusHost);
+ }
if (up != null && up[0] != null) {
setUsernamePassword(up[0], up[1]);
}
@@ -815,7 +821,7 @@
}
WebAddress uri = new WebAddress(mCallbackProxy
.getBackForwardList().getCurrentItem().getUrl());
- String schemePlusHost = uri.getScheme() + uri.getHost();
+ String schemePlusHost = uri.getScheme() + SCHEME_HOST_DELIMITER + uri.getHost();
// Check to see if the username & password appear in
// the post data (there could be another form on the
// page and that was posted instead.
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index aa9a329..1f00c9c 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -573,7 +573,8 @@
* forms. Note that this is unrelated to the credentials used for HTTP
* authentication.
*
- * @param host the host that required the credentials
+ * @param host the host that required the credentials. It is recommended that
+ * the host is given using scheme://hostname format.
* @param username the username for the given host
* @param password the password for the given host
* @see WebViewDatabase#clearUsernamePassword
diff --git a/core/java/android/webkit/WebViewClassic.java b/core/java/android/webkit/WebViewClassic.java
index 67041ac..c7dacf3 100644
--- a/core/java/android/webkit/WebViewClassic.java
+++ b/core/java/android/webkit/WebViewClassic.java
@@ -5419,7 +5419,7 @@
ClipData clipData = cm.getPrimaryClip();
if (clipData != null) {
ClipData.Item clipItem = clipData.getItemAt(0);
- CharSequence pasteText = clipItem.getText();
+ CharSequence pasteText = clipItem.coerceToText(mContext);
if (mInputConnection != null) {
mInputConnection.replaceSelection(pasteText);
}
diff --git a/core/java/android/webkit/WebViewDatabaseClassic.java b/core/java/android/webkit/WebViewDatabaseClassic.java
index be01028..5ad4fa5 100644
--- a/core/java/android/webkit/WebViewDatabaseClassic.java
+++ b/core/java/android/webkit/WebViewDatabaseClassic.java
@@ -37,7 +37,7 @@
private static final String DATABASE_FILE = "webview.db";
private static final String CACHE_DATABASE_FILE = "webviewCache.db";
- private static final int DATABASE_VERSION = 11;
+ private static final int DATABASE_VERSION = 12;
// 2 -> 3 Modified Cache table to allow cache of redirects
// 3 -> 4 Added Oma-Downloads table
// 4 -> 5 Modified Cache table to support persistent contentLength
@@ -50,6 +50,7 @@
// 10 -> 11 Drop cookies and cache now managed by the chromium stack,
// and update the form data table to use the new format
// implemented for b/5265606.
+ // 11 -> 12 Add a delimiter between scheme and host when storing passwords
private static WebViewDatabaseClassic sInstance = null;
private static final Object sInstanceLock = new Object();
@@ -169,11 +170,23 @@
private static void upgradeDatabase() {
upgradeDatabaseToV10();
upgradeDatabaseFromV10ToV11();
+ upgradeDatabaseFromV11ToV12();
// Add future database upgrade functions here, one version at a
// time.
sDatabase.setVersion(DATABASE_VERSION);
}
+ private static void upgradeDatabaseFromV11ToV12() {
+ int oldVersion = sDatabase.getVersion();
+
+ if (oldVersion >= 12) {
+ // Nothing to do.
+ return;
+ }
+ // delete the rows in the database.
+ sDatabase.delete(mTableNames[TABLE_PASSWORD_ID], null, null);
+ }
+
private static void upgradeDatabaseFromV10ToV11() {
int oldVersion = sDatabase.getVersion();
diff --git a/core/java/android/widget/DatePicker.java b/core/java/android/widget/DatePicker.java
index 07d3a7a..8f515f5 100644
--- a/core/java/android/widget/DatePicker.java
+++ b/core/java/android/widget/DatePicker.java
@@ -419,7 +419,7 @@
* @see #getCalendarView()
*/
public boolean getCalendarViewShown() {
- return mCalendarView.isShown();
+ return (mCalendarView.getVisibility() == View.VISIBLE);
}
/**
diff --git a/core/java/android/widget/RelativeLayout.java b/core/java/android/widget/RelativeLayout.java
index 5d6ec1e..c9d2d95 100644
--- a/core/java/android/widget/RelativeLayout.java
+++ b/core/java/android/widget/RelativeLayout.java
@@ -41,6 +41,7 @@
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.RemoteViews.RemoteView;
+import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR1;
import static android.util.Log.d;
/**
@@ -1215,6 +1216,7 @@
private int mEnd = DEFAULT_RELATIVE;
private boolean mRulesChanged = false;
+ private boolean mIsRtlCompatibilityMode = false;
/**
* When true, uses the parent as the anchor if the anchor doesn't exist or if
@@ -1229,6 +1231,10 @@
TypedArray a = c.obtainStyledAttributes(attrs,
com.android.internal.R.styleable.RelativeLayout_Layout);
+ final int targetSdkVersion = c.getApplicationInfo().targetSdkVersion;
+ mIsRtlCompatibilityMode = (targetSdkVersion < JELLY_BEAN_MR1 ||
+ !c.getApplicationInfo().hasRtlSupport());
+
final int[] rules = mRules;
//noinspection MismatchedReadAndWriteOfArray
final int[] initialRules = mInitialRules;
@@ -1397,28 +1403,132 @@
mInitialRules[ALIGN_PARENT_START] != 0 || mInitialRules[ALIGN_PARENT_END] != 0);
}
+ // The way we are resolving rules depends on the layout direction and if we are pre JB MR1
+ // or not.
+ //
+ // If we are pre JB MR1 (said as "RTL compatibility mode"), "left"/"right" rules are having
+ // predominance over any "start/end" rules that could have been defined. A special case:
+ // if no "left"/"right" rule has been defined and "start"/"end" rules are defined then we
+ // resolve those "start"/"end" rules to "left"/"right" respectively.
+ //
+ // If we are JB MR1+, then "start"/"end" rules are having predominance over "left"/"right"
+ // rules. If no "start"/"end" rule is defined then we use "left"/"right" rules.
+ //
+ // In all cases, the result of the resolution should clear the "start"/"end" rules to leave
+ // only the "left"/"right" rules at the end.
private void resolveRules(int layoutDirection) {
final boolean isLayoutRtl = (layoutDirection == View.LAYOUT_DIRECTION_RTL);
+
// Reset to initial state
System.arraycopy(mInitialRules, LEFT_OF, mRules, LEFT_OF, VERB_COUNT);
- // Apply rules depending on direction
- if (mRules[ALIGN_START] != 0) {
- mRules[isLayoutRtl ? ALIGN_RIGHT : ALIGN_LEFT] = mRules[ALIGN_START];
- }
- if (mRules[ALIGN_END] != 0) {
- mRules[isLayoutRtl ? ALIGN_LEFT : ALIGN_RIGHT] = mRules[ALIGN_END];
- }
- if (mRules[START_OF] != 0) {
- mRules[isLayoutRtl ? RIGHT_OF : LEFT_OF] = mRules[START_OF];
- }
- if (mRules[END_OF] != 0) {
- mRules[isLayoutRtl ? LEFT_OF : RIGHT_OF] = mRules[END_OF];
- }
- if (mRules[ALIGN_PARENT_START] != 0) {
- mRules[isLayoutRtl ? ALIGN_PARENT_RIGHT : ALIGN_PARENT_LEFT] = mRules[ALIGN_PARENT_START];
- }
- if (mRules[ALIGN_PARENT_END] != 0) {
- mRules[isLayoutRtl ? ALIGN_PARENT_LEFT : ALIGN_PARENT_RIGHT] = mRules[ALIGN_PARENT_END];
+
+ // Apply rules depending on direction and if we are in RTL compatibility mode
+ if (mIsRtlCompatibilityMode) {
+ if (mRules[ALIGN_START] != 0) {
+ if (mRules[ALIGN_LEFT] == 0) {
+ // "left" rule is not defined but "start" rule is: use the "start" rule as
+ // the "left" rule
+ mRules[ALIGN_LEFT] = mRules[ALIGN_START];
+ }
+ mRules[ALIGN_START] = 0;
+ }
+
+ if (mRules[ALIGN_END] != 0) {
+ if (mRules[ALIGN_RIGHT] == 0) {
+ // "right" rule is not defined but "end" rule is: use the "end" rule as the
+ // "right" rule
+ mRules[ALIGN_RIGHT] = mRules[ALIGN_END];
+ }
+ mRules[ALIGN_END] = 0;
+ }
+
+ if (mRules[START_OF] != 0) {
+ if (mRules[LEFT_OF] == 0) {
+ // "left" rule is not defined but "start" rule is: use the "start" rule as
+ // the "left" rule
+ mRules[LEFT_OF] = mRules[START_OF];
+ }
+ mRules[START_OF] = 0;
+ }
+
+ if (mRules[END_OF] != 0) {
+ if (mRules[RIGHT_OF] == 0) {
+ // "right" rule is not defined but "end" rule is: use the "end" rule as the
+ // "right" rule
+ mRules[RIGHT_OF] = mRules[END_OF];
+ }
+ mRules[END_OF] = 0;
+ }
+
+ if (mRules[ALIGN_PARENT_START] != 0) {
+ if (mRules[ALIGN_PARENT_LEFT] == 0) {
+ // "left" rule is not defined but "start" rule is: use the "start" rule as
+ // the "left" rule
+ mRules[ALIGN_PARENT_LEFT] = mRules[ALIGN_PARENT_START];
+ }
+ mRules[ALIGN_PARENT_START] = 0;
+ }
+
+ if (mRules[ALIGN_PARENT_RIGHT] == 0) {
+ if (mRules[ALIGN_PARENT_RIGHT] == 0) {
+ // "right" rule is not defined but "end" rule is: use the "end" rule as the
+ // "right" rule
+ mRules[ALIGN_PARENT_RIGHT] = mRules[ALIGN_PARENT_END];
+ }
+ mRules[ALIGN_PARENT_END] = 0;
+ }
+ } else {
+ // JB MR1+ case
+ if ((mRules[ALIGN_START] != 0 || mRules[ALIGN_END] != 0) &&
+ (mRules[ALIGN_LEFT] != 0 || mRules[ALIGN_RIGHT] != 0)) {
+ // "start"/"end" rules take precedence over "left"/"right" rules
+ mRules[ALIGN_LEFT] = 0;
+ mRules[ALIGN_RIGHT] = 0;
+ }
+ if (mRules[ALIGN_START] != 0) {
+ // "start" rule resolved to "left" or "right" depending on the direction
+ mRules[isLayoutRtl ? ALIGN_RIGHT : ALIGN_LEFT] = mRules[ALIGN_START];
+ mRules[ALIGN_START] = 0;
+ }
+ if (mRules[ALIGN_END] != 0) {
+ // "end" rule resolved to "left" or "right" depending on the direction
+ mRules[isLayoutRtl ? ALIGN_LEFT : ALIGN_RIGHT] = mRules[ALIGN_END];
+ mRules[ALIGN_END] = 0;
+ }
+
+ if ((mRules[START_OF] != 0 || mRules[END_OF] != 0) &&
+ (mRules[LEFT_OF] != 0 || mRules[RIGHT_OF] != 0)) {
+ // "start"/"end" rules take precedence over "left"/"right" rules
+ mRules[LEFT_OF] = 0;
+ mRules[RIGHT_OF] = 0;
+ }
+ if (mRules[START_OF] != 0) {
+ // "start" rule resolved to "left" or "right" depending on the direction
+ mRules[isLayoutRtl ? RIGHT_OF : LEFT_OF] = mRules[START_OF];
+ mRules[START_OF] = 0;
+ }
+ if (mRules[END_OF] != 0) {
+ // "end" rule resolved to "left" or "right" depending on the direction
+ mRules[isLayoutRtl ? LEFT_OF : RIGHT_OF] = mRules[END_OF];
+ mRules[END_OF] = 0;
+ }
+
+ if ((mRules[ALIGN_PARENT_START] != 0 || mRules[ALIGN_PARENT_END] != 0) &&
+ (mRules[ALIGN_PARENT_LEFT] != 0 || mRules[ALIGN_PARENT_RIGHT] != 0)) {
+ // "start"/"end" rules take precedence over "left"/"right" rules
+ mRules[ALIGN_PARENT_LEFT] = 0;
+ mRules[ALIGN_PARENT_RIGHT] = 0;
+ }
+ if (mRules[ALIGN_PARENT_START] != 0) {
+ // "start" rule resolved to "left" or "right" depending on the direction
+ mRules[isLayoutRtl ? ALIGN_PARENT_RIGHT : ALIGN_PARENT_LEFT] = mRules[ALIGN_PARENT_START];
+ mRules[ALIGN_PARENT_START] = 0;
+ }
+ if (mRules[ALIGN_PARENT_END] != 0) {
+ // "end" rule resolved to "left" or "right" depending on the direction
+ mRules[isLayoutRtl ? ALIGN_PARENT_LEFT : ALIGN_PARENT_RIGHT] = mRules[ALIGN_PARENT_END];
+ mRules[ALIGN_PARENT_END] = 0;
+ }
}
mRulesChanged = false;
}
diff --git a/core/java/com/android/internal/backup/IObbBackupService.aidl b/core/java/com/android/internal/backup/IObbBackupService.aidl
new file mode 100644
index 0000000..426dbc4
--- /dev/null
+++ b/core/java/com/android/internal/backup/IObbBackupService.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2013, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.backup;
+
+import android.app.backup.IBackupManager;
+import android.os.ParcelFileDescriptor;
+
+/**
+ * Interface for the Backup Manager Service to communicate with a helper service that
+ * handles local (whole-file) backup & restore of OBB content on behalf of applications.
+ * This can't be done within the Backup Manager Service itself because of the restrictions
+ * on system-user access to external storage, and can't be left to the apps because even
+ * apps that do not have permission to access external storage in the usual way can still
+ * use OBBs.
+ *
+ * {@hide}
+ */
+oneway interface IObbBackupService {
+ /*
+ * Back up a package's OBB directory tree
+ */
+ void backupObbs(in String packageName, in ParcelFileDescriptor data,
+ int token, in IBackupManager callbackBinder);
+
+ /*
+ * Restore an OBB file for the given package from the incoming stream
+ */
+ void restoreObbFile(in String pkgName, in ParcelFileDescriptor data,
+ long fileSize, int type, in String path, long mode, long mtime,
+ int token, in IBackupManager callbackBinder);
+}
diff --git a/core/java/com/android/internal/util/StateMachine.java b/core/java/com/android/internal/util/StateMachine.java
index 58d4aa7..e547f23 100644
--- a/core/java/com/android/internal/util/StateMachine.java
+++ b/core/java/com/android/internal/util/StateMachine.java
@@ -1606,6 +1606,19 @@
*
* Message is ignored if state machine has quit.
*/
+ public final void sendMessage(int what, int arg1, int arg2, Object obj) {
+ // mSmHandler can be null if the state machine has quit.
+ SmHandler smh = mSmHandler;
+ if (smh == null) return;
+
+ smh.sendMessage(obtainMessage(what, arg1, arg2, obj));
+ }
+
+ /**
+ * Enqueue a message to this state machine.
+ *
+ * Message is ignored if state machine has quit.
+ */
public final void sendMessage(Message msg) {
// mSmHandler can be null if the state machine has quit.
SmHandler smh = mSmHandler;
@@ -1645,6 +1658,20 @@
*
* Message is ignored if state machine has quit.
*/
+ public final void sendMessageDelayed(int what, int arg1, int arg2, Object obj,
+ long delayMillis) {
+ // mSmHandler can be null if the state machine has quit.
+ SmHandler smh = mSmHandler;
+ if (smh == null) return;
+
+ smh.sendMessageDelayed(obtainMessage(what, arg1, arg2, obj), delayMillis);
+ }
+
+ /**
+ * Enqueue a message to this state machine after a delay.
+ *
+ * Message is ignored if state machine has quit.
+ */
public final void sendMessageDelayed(Message msg, long delayMillis) {
// mSmHandler can be null if the state machine has quit.
SmHandler smh = mSmHandler;
@@ -1687,6 +1714,20 @@
*
* Message is ignored if state machine has quit.
*/
+ protected final void sendMessageAtFrontOfQueue(int what, int arg1, int arg2, Object obj) {
+ // mSmHandler can be null if the state machine has quit.
+ SmHandler smh = mSmHandler;
+ if (smh == null) return;
+
+ smh.sendMessageAtFrontOfQueue(obtainMessage(what, arg1, arg2, obj));
+ }
+
+ /**
+ * Enqueue a message to the front of the queue for this state machine.
+ * Protected, may only be called by instances of StateMachine.
+ *
+ * Message is ignored if state machine has quit.
+ */
protected final void sendMessageAtFrontOfQueue(Message msg) {
// mSmHandler can be null if the state machine has quit.
SmHandler smh = mSmHandler;
diff --git a/core/java/com/android/internal/widget/LockPatternView.java b/core/java/com/android/internal/widget/LockPatternView.java
index 7a76ab0..1b088b3 100644
--- a/core/java/com/android/internal/widget/LockPatternView.java
+++ b/core/java/com/android/internal/widget/LockPatternView.java
@@ -38,6 +38,7 @@
import android.view.accessibility.AccessibilityManager;
import com.android.internal.R;
+import com.android.internal.widget.LockPatternView.Cell;
import java.util.ArrayList;
import java.util.List;
@@ -72,6 +73,12 @@
*/
private static final int MILLIS_PER_CIRCLE_ANIMATING = 700;
+ /**
+ * This can be used to avoid updating the display for very small motions or noisy panels.
+ * It didn't seem to have much impact on the devices tested, so currently set to 0.
+ */
+ private static final float DRAG_THRESHHOLD = 0.0f;
+
private OnPatternListener mOnPatternListener;
private ArrayList<Cell> mPattern = new ArrayList<Cell>(9);
@@ -674,10 +681,11 @@
// Handle all recent motion events so we don't skip any cells even when the device
// is busy...
final int historySize = event.getHistorySize();
+ Rect invalidateRect = mInvalidate;
+ boolean invalidateNow = false;
for (int i = 0; i < historySize + 1; i++) {
final float x = i < historySize ? event.getHistoricalX(i) : event.getX();
final float y = i < historySize ? event.getHistoricalY(i) : event.getY();
- final int patternSizePreHitDetect = mPattern.size();
Cell hitCell = detectAndAddHit(x, y);
final int patternSize = mPattern.size();
if (hitCell != null && patternSize == 1) {
@@ -687,113 +695,47 @@
// note current x and y for rubber banding of in progress patterns
final float dx = Math.abs(x - mInProgressX);
final float dy = Math.abs(y - mInProgressY);
- if (dx + dy > mSquareWidth * 0.01f) {
- float oldX = mInProgressX;
- float oldY = mInProgressY;
-
- mInProgressX = x;
- mInProgressY = y;
-
- if (mPatternInProgress && patternSize > 0) {
- final ArrayList<Cell> pattern = mPattern;
- final float radius = mSquareWidth * mDiameterFactor * 0.5f;
-
- final Cell lastCell = pattern.get(patternSize - 1);
-
- float startX = getCenterXForColumn(lastCell.column);
- float startY = getCenterYForRow(lastCell.row);
-
- float left;
- float top;
- float right;
- float bottom;
-
- final Rect invalidateRect = mInvalidate;
-
- if (startX < x) {
- left = startX;
- right = x;
- } else {
- left = x;
- right = startX;
- }
-
- if (startY < y) {
- top = startY;
- bottom = y;
- } else {
- top = y;
- bottom = startY;
- }
-
- // Invalidate between the pattern's last cell and the current location
- invalidateRect.set((int) (left - radius), (int) (top - radius),
- (int) (right + radius), (int) (bottom + radius));
-
- if (startX < oldX) {
- left = startX;
- right = oldX;
- } else {
- left = oldX;
- right = startX;
- }
-
- if (startY < oldY) {
- top = startY;
- bottom = oldY;
- } else {
- top = oldY;
- bottom = startY;
- }
-
- // Invalidate between the pattern's last cell and the previous location
- invalidateRect.union((int) (left - radius), (int) (top - radius),
- (int) (right + radius), (int) (bottom + radius));
-
- // Invalidate between the pattern's new cell and the pattern's previous cell
- if (hitCell != null) {
- startX = getCenterXForColumn(hitCell.column);
- startY = getCenterYForRow(hitCell.row);
-
- if (patternSize >= 2) {
- // (re-using hitcell for old cell)
- hitCell = pattern.get(patternSize - 1 - (patternSize - patternSizePreHitDetect));
- oldX = getCenterXForColumn(hitCell.column);
- oldY = getCenterYForRow(hitCell.row);
-
- if (startX < oldX) {
- left = startX;
- right = oldX;
- } else {
- left = oldX;
- right = startX;
- }
-
- if (startY < oldY) {
- top = startY;
- bottom = oldY;
- } else {
- top = oldY;
- bottom = startY;
- }
- } else {
- left = right = startX;
- top = bottom = startY;
- }
-
- final float widthOffset = mSquareWidth / 2f;
- final float heightOffset = mSquareHeight / 2f;
-
- invalidateRect.set((int) (left - widthOffset),
- (int) (top - heightOffset), (int) (right + widthOffset),
- (int) (bottom + heightOffset));
- }
-
- invalidate(invalidateRect);
- } else {
- invalidate();
- }
+ if (dx > DRAG_THRESHHOLD || dy > DRAG_THRESHHOLD) {
+ invalidateNow = true;
}
+
+ if (mPatternInProgress && patternSize > 0) {
+ final ArrayList<Cell> pattern = mPattern;
+ final Cell lastCell = pattern.get(patternSize - 1);
+ float startX = getCenterXForColumn(lastCell.column);
+ float startY = getCenterYForRow(lastCell.row);
+
+ // Adjust for current position. Radius accounts for line width.
+ final float radius = (mSquareWidth * mDiameterFactor * 0.5f);
+ float left = Math.min(startX, x) - radius;
+ float right = Math.max(startX, x) + radius;
+ float top = Math.min(startY, y) - radius;
+ float bottom = Math.max(startY, y) + radius;
+
+ // Invalidate between the pattern's new cell and the pattern's previous cell
+ if (hitCell != null && patternSize >= 2) {
+ final float width = mSquareWidth * 0.5f;
+ final float height = mSquareHeight * 0.5f;
+ final float x2 = getCenterXForColumn(hitCell.column);
+ final float y2 = getCenterYForRow(hitCell.row);
+ left = Math.min(x2, left - width);
+ right = Math.max(x2, right + width);
+ top = Math.min(y2, top - height);
+ bottom = Math.max(y2, bottom + height);
+ }
+
+ // Invalidate between the pattern's last cell and the previous location
+ invalidateRect.union(Math.round(left), Math.round(top),
+ Math.round(right), Math.round(bottom));
+ }
+ }
+ mInProgressX = event.getX();
+ mInProgressY = event.getY();
+
+ // To save updates, we only invalidate if the user moved beyond a certain amount.
+ if (invalidateNow) {
+ invalidate(invalidateRect);
+ invalidateRect.setEmpty();
}
}
diff --git a/core/res/res/drawable-hdpi/ic_btn_search.png b/core/res/res/drawable-hdpi/ic_btn_search.png
deleted file mode 100644
index 98e61a3..0000000
--- a/core/res/res/drawable-hdpi/ic_btn_search.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_search.png b/core/res/res/drawable-hdpi/ic_menu_search.png
index a7f9bbe..ae2f44b 100644
--- a/core/res/res/drawable-hdpi/ic_menu_search.png
+++ b/core/res/res/drawable-hdpi/ic_menu_search.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_search_holo_dark.png b/core/res/res/drawable-hdpi/ic_menu_search_holo_dark.png
index a7f9bbe..420d680 100644
--- a/core/res/res/drawable-hdpi/ic_menu_search_holo_dark.png
+++ b/core/res/res/drawable-hdpi/ic_menu_search_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_search_holo_light.png b/core/res/res/drawable-hdpi/ic_menu_search_holo_light.png
index 1cb61fa..cc661e3 100644
--- a/core/res/res/drawable-hdpi/ic_menu_search_holo_light.png
+++ b/core/res/res/drawable-hdpi/ic_menu_search_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_btn_search.png b/core/res/res/drawable-ldpi/ic_btn_search.png
deleted file mode 100644
index bdefbf5..0000000
--- a/core/res/res/drawable-ldpi/ic_btn_search.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_btn_search.png b/core/res/res/drawable-mdpi/ic_btn_search.png
deleted file mode 100644
index 662f5de..0000000
--- a/core/res/res/drawable-mdpi/ic_btn_search.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_search.png b/core/res/res/drawable-mdpi/ic_menu_search.png
index 5d3155e..d18f542 100644
--- a/core/res/res/drawable-mdpi/ic_menu_search.png
+++ b/core/res/res/drawable-mdpi/ic_menu_search.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_search_holo_dark.png b/core/res/res/drawable-mdpi/ic_menu_search_holo_dark.png
index 5d3155e..906da53 100644
--- a/core/res/res/drawable-mdpi/ic_menu_search_holo_dark.png
+++ b/core/res/res/drawable-mdpi/ic_menu_search_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_search_holo_light.png b/core/res/res/drawable-mdpi/ic_menu_search_holo_light.png
index 2369d03..0350a43 100644
--- a/core/res/res/drawable-mdpi/ic_menu_search_holo_light.png
+++ b/core/res/res/drawable-mdpi/ic_menu_search_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_btn_search.png b/core/res/res/drawable-xhdpi/ic_btn_search.png
deleted file mode 100644
index a267c0a..0000000
--- a/core/res/res/drawable-xhdpi/ic_btn_search.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_search.png b/core/res/res/drawable-xhdpi/ic_menu_search.png
index 5c18f9e..4444495 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_search.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_search.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_search_holo_dark.png b/core/res/res/drawable-xhdpi/ic_menu_search_holo_dark.png
index d49c7e2..1208859 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_search_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_search_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_search_holo_light.png b/core/res/res/drawable-xhdpi/ic_menu_search_holo_light.png
index 578cb24..6811782 100644
--- a/core/res/res/drawable-xhdpi/ic_menu_search_holo_light.png
+++ b/core/res/res/drawable-xhdpi/ic_menu_search_holo_light.png
Binary files differ
diff --git a/core/tests/coretests/src/android/net/LinkPropertiesTest.java b/core/tests/coretests/src/android/net/LinkPropertiesTest.java
index e3b6b5f..fffaa00 100644
--- a/core/tests/coretests/src/android/net/LinkPropertiesTest.java
+++ b/core/tests/coretests/src/android/net/LinkPropertiesTest.java
@@ -197,4 +197,63 @@
}
}
+ private void assertAllRoutesHaveInterface(String iface, LinkProperties lp) {
+ for (RouteInfo r : lp.getRoutes()) {
+ assertEquals(iface, r.getInterface());
+ }
+ }
+
+ @SmallTest
+ public void testRouteInterfaces() {
+ LinkAddress prefix = new LinkAddress(
+ NetworkUtils.numericToInetAddress("2001:db8::"), 32);
+ InetAddress address = NetworkUtils.numericToInetAddress(ADDRV6);
+
+ // Add a route with no interface to a LinkProperties with no interface. No errors.
+ LinkProperties lp = new LinkProperties();
+ RouteInfo r = new RouteInfo(prefix, address, null);
+ lp.addRoute(r);
+ assertEquals(1, lp.getRoutes().size());
+ assertAllRoutesHaveInterface(null, lp);
+
+ // Add a route with an interface. Except an exception.
+ r = new RouteInfo(prefix, address, "wlan0");
+ try {
+ lp.addRoute(r);
+ fail("Adding wlan0 route to LP with no interface, expect exception");
+ } catch (IllegalArgumentException expected) {}
+
+ // Change the interface name. All the routes should change their interface name too.
+ lp.setInterfaceName("rmnet0");
+ assertAllRoutesHaveInterface("rmnet0", lp);
+
+ // Now add a route with the wrong interface. This causes an exception too.
+ try {
+ lp.addRoute(r);
+ fail("Adding wlan0 route to rmnet0 LP, expect exception");
+ } catch (IllegalArgumentException expected) {}
+
+ // If the interface name matches, the route is added.
+ lp.setInterfaceName("wlan0");
+ lp.addRoute(r);
+ assertEquals(2, lp.getRoutes().size());
+ assertAllRoutesHaveInterface("wlan0", lp);
+
+ // Routes with null interfaces are converted to wlan0.
+ r = RouteInfo.makeHostRoute(NetworkUtils.numericToInetAddress(ADDRV6), null);
+ lp.addRoute(r);
+ assertEquals(3, lp.getRoutes().size());
+ assertAllRoutesHaveInterface("wlan0", lp);
+
+ // Check comparisons work.
+ LinkProperties lp2 = new LinkProperties(lp);
+ assertAllRoutesHaveInterface("wlan0", lp);
+ assertEquals(0, lp.compareRoutes(lp2).added.size());
+ assertEquals(0, lp.compareRoutes(lp2).removed.size());
+
+ lp2.setInterfaceName("p2p0");
+ assertAllRoutesHaveInterface("p2p0", lp2);
+ assertEquals(3, lp.compareRoutes(lp2).added.size());
+ assertEquals(3, lp.compareRoutes(lp2).removed.size());
+ }
}
diff --git a/core/tests/coretests/src/android/net/RouteInfoTest.java b/core/tests/coretests/src/android/net/RouteInfoTest.java
new file mode 100644
index 0000000..59eb601
--- /dev/null
+++ b/core/tests/coretests/src/android/net/RouteInfoTest.java
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import java.lang.reflect.Method;
+import java.net.InetAddress;
+
+import android.net.LinkAddress;
+import android.net.RouteInfo;
+import android.os.Parcel;
+
+import junit.framework.TestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+public class RouteInfoTest extends TestCase {
+
+ private InetAddress Address(String addr) {
+ return InetAddress.parseNumericAddress(addr);
+ }
+
+ private LinkAddress Prefix(String prefix) {
+ String[] parts = prefix.split("/");
+ return new LinkAddress(Address(parts[0]), Integer.parseInt(parts[1]));
+ }
+
+ @SmallTest
+ public void testConstructor() {
+ RouteInfo r;
+
+ // Invalid input.
+ try {
+ r = new RouteInfo(null, null, "rmnet0");
+ fail("Expected RuntimeException: destination and gateway null");
+ } catch(RuntimeException e) {}
+
+ // Null destination is default route.
+ r = new RouteInfo(null, Address("2001:db8::1"), null);
+ assertEquals(Prefix("::/0"), r.getDestination());
+ assertEquals(Address("2001:db8::1"), r.getGateway());
+ assertNull(r.getInterface());
+
+ r = new RouteInfo(null, Address("192.0.2.1"), "wlan0");
+ assertEquals(Prefix("0.0.0.0/0"), r.getDestination());
+ assertEquals(Address("192.0.2.1"), r.getGateway());
+ assertEquals("wlan0", r.getInterface());
+
+ // Null gateway sets gateway to unspecified address (why?).
+ r = new RouteInfo(Prefix("2001:db8:beef:cafe::/48"), null, "lo");
+ assertEquals(Prefix("2001:db8:beef::/48"), r.getDestination());
+ assertEquals(Address("::"), r.getGateway());
+ assertEquals("lo", r.getInterface());
+
+ r = new RouteInfo(Prefix("192.0.2.5/24"), null);
+ assertEquals(Prefix("192.0.2.0/24"), r.getDestination());
+ assertEquals(Address("0.0.0.0"), r.getGateway());
+ assertNull(r.getInterface());
+ }
+
+ public void testMatches() {
+ class PatchedRouteInfo extends RouteInfo {
+ public PatchedRouteInfo(LinkAddress destination, InetAddress gateway, String iface) {
+ super(destination, gateway, iface);
+ }
+
+ public boolean matches(InetAddress destination) {
+ return super.matches(destination);
+ }
+ }
+
+ RouteInfo r;
+
+ r = new PatchedRouteInfo(Prefix("2001:db8:f00::ace:d00d/127"), null, "rmnet0");
+ assertTrue(r.matches(Address("2001:db8:f00::ace:d00c")));
+ assertTrue(r.matches(Address("2001:db8:f00::ace:d00d")));
+ assertFalse(r.matches(Address("2001:db8:f00::ace:d00e")));
+ assertFalse(r.matches(Address("2001:db8:f00::bad:d00d")));
+ assertFalse(r.matches(Address("2001:4868:4860::8888")));
+
+ r = new PatchedRouteInfo(Prefix("192.0.2.0/23"), null, "wlan0");
+ assertTrue(r.matches(Address("192.0.2.43")));
+ assertTrue(r.matches(Address("192.0.3.21")));
+ assertFalse(r.matches(Address("192.0.0.21")));
+ assertFalse(r.matches(Address("8.8.8.8")));
+
+ RouteInfo ipv6Default = new PatchedRouteInfo(Prefix("::/0"), null, "rmnet0");
+ assertTrue(ipv6Default.matches(Address("2001:db8::f00")));
+ assertFalse(ipv6Default.matches(Address("192.0.2.1")));
+
+ RouteInfo ipv4Default = new PatchedRouteInfo(Prefix("0.0.0.0/0"), null, "rmnet0");
+ assertTrue(ipv4Default.matches(Address("255.255.255.255")));
+ assertTrue(ipv4Default.matches(Address("192.0.2.1")));
+ assertFalse(ipv4Default.matches(Address("2001:db8::f00")));
+ }
+
+ private void assertAreEqual(Object o1, Object o2) {
+ assertTrue(o1.equals(o2));
+ assertTrue(o2.equals(o1));
+ }
+
+ private void assertAreNotEqual(Object o1, Object o2) {
+ assertFalse(o1.equals(o2));
+ assertFalse(o2.equals(o1));
+ }
+
+ public void testEquals() {
+ // IPv4
+ RouteInfo r1 = new RouteInfo(Prefix("2001:db8:ace::/48"), Address("2001:db8::1"), "wlan0");
+ RouteInfo r2 = new RouteInfo(Prefix("2001:db8:ace::/48"), Address("2001:db8::1"), "wlan0");
+ assertAreEqual(r1, r2);
+
+ RouteInfo r3 = new RouteInfo(Prefix("2001:db8:ace::/49"), Address("2001:db8::1"), "wlan0");
+ RouteInfo r4 = new RouteInfo(Prefix("2001:db8:ace::/48"), Address("2001:db8::2"), "wlan0");
+ RouteInfo r5 = new RouteInfo(Prefix("2001:db8:ace::/48"), Address("2001:db8::1"), "rmnet0");
+ assertAreNotEqual(r1, r3);
+ assertAreNotEqual(r1, r4);
+ assertAreNotEqual(r1, r5);
+
+ // IPv6
+ r1 = new RouteInfo(Prefix("192.0.2.0/25"), Address("192.0.2.1"), "wlan0");
+ r2 = new RouteInfo(Prefix("192.0.2.0/25"), Address("192.0.2.1"), "wlan0");
+ assertAreEqual(r1, r2);
+
+ r3 = new RouteInfo(Prefix("192.0.2.0/24"), Address("192.0.2.1"), "wlan0");
+ r4 = new RouteInfo(Prefix("192.0.2.0/25"), Address("192.0.2.2"), "wlan0");
+ r5 = new RouteInfo(Prefix("192.0.2.0/25"), Address("192.0.2.1"), "rmnet0");
+ assertAreNotEqual(r1, r3);
+ assertAreNotEqual(r1, r4);
+ assertAreNotEqual(r1, r5);
+
+ // Interfaces (but not destinations or gateways) can be null.
+ r1 = new RouteInfo(Prefix("192.0.2.0/25"), Address("192.0.2.1"), null);
+ r2 = new RouteInfo(Prefix("192.0.2.0/25"), Address("192.0.2.1"), null);
+ r3 = new RouteInfo(Prefix("192.0.2.0/24"), Address("192.0.2.1"), "wlan0");
+ assertAreEqual(r1, r2);
+ assertAreNotEqual(r1, r3);
+ }
+
+ public RouteInfo passThroughParcel(RouteInfo r) {
+ Parcel p = Parcel.obtain();
+ RouteInfo r2 = null;
+ try {
+ r.writeToParcel(p, 0);
+ p.setDataPosition(0);
+ r2 = RouteInfo.CREATOR.createFromParcel(p);
+ } finally {
+ p.recycle();
+ }
+ assertNotNull(r2);
+ return r2;
+ }
+
+ public void assertParcelingIsLossless(RouteInfo r) {
+ RouteInfo r2 = passThroughParcel(r);
+ assertEquals(r, r2);
+ }
+
+ public void testParceling() {
+ RouteInfo r;
+
+ r = new RouteInfo(Prefix("::/0"), Address("2001:db8::"), null);
+ assertParcelingIsLossless(r);
+
+ r = new RouteInfo(Prefix("192.0.2.0/24"), null, "wlan0");
+ assertParcelingIsLossless(r);
+ }
+}
diff --git a/core/tests/coretests/src/android/text/format/DateUtilsTest.java b/core/tests/coretests/src/android/text/format/DateUtilsTest.java
index cf42bb1..c5f6236 100644
--- a/core/tests/coretests/src/android/text/format/DateUtilsTest.java
+++ b/core/tests/coretests/src/android/text/format/DateUtilsTest.java
@@ -21,8 +21,9 @@
import junit.framework.TestCase;
public class DateUtilsTest extends TestCase {
+ // This test is not in CTS because formatDuration is @hidden.
@SmallTest
- public void testFormatDurationSeconds() throws Exception {
+ public void test_formatDuration_seconds() throws Exception {
assertEquals("0 seconds", DateUtils.formatDuration(0));
assertEquals("0 seconds", DateUtils.formatDuration(1));
assertEquals("0 seconds", DateUtils.formatDuration(499));
@@ -31,16 +32,18 @@
assertEquals("2 seconds", DateUtils.formatDuration(1500));
}
+ // This test is not in CTS because formatDuration is @hidden.
@SmallTest
- public void testFormatDurationMinutes() throws Exception {
+ public void test_formatDuration_Minutes() throws Exception {
assertEquals("59 seconds", DateUtils.formatDuration(59000));
assertEquals("60 seconds", DateUtils.formatDuration(59500));
assertEquals("1 minute", DateUtils.formatDuration(60000));
assertEquals("2 minutes", DateUtils.formatDuration(120000));
}
+ // This test is not in CTS because formatDuration is @hidden.
@SmallTest
- public void testFormatDurationHours() throws Exception {
+ public void test_formatDuration_Hours() throws Exception {
assertEquals("59 minutes", DateUtils.formatDuration(3540000));
assertEquals("1 hour", DateUtils.formatDuration(3600000));
assertEquals("48 hours", DateUtils.formatDuration(172800000));
diff --git a/docs/downloads/training/InteractiveChart.zip b/docs/downloads/training/InteractiveChart.zip
new file mode 100644
index 0000000..95248ad
--- /dev/null
+++ b/docs/downloads/training/InteractiveChart.zip
Binary files differ
diff --git a/docs/html/about/dashboards/index.jd b/docs/html/about/dashboards/index.jd
index 93876f8..b2d50ce 100644
--- a/docs/html/about/dashboards/index.jd
+++ b/docs/html/about/dashboards/index.jd
@@ -32,11 +32,11 @@
</tr>
<tr><td><a href="/about/versions/android-1.6.html">1.6</a></td><td>Donut</td> <td>4</td><td>0.2%</td></tr>
<tr><td><a href="/about/versions/android-2.1.html">2.1</a></td><td>Eclair</td> <td>7</td><td>1.9%</td></tr>
-<tr><td><a href="/about/versions/android-2.2.html">2.2</a></td><td>Froyo</td> <td>8</td><td>7.6%</td></tr>
+<tr><td><a href="/about/versions/android-2.2.html">2.2</a></td><td>Froyo</td> <td>8</td><td>7.5%</td></tr>
<tr><td><a href="/about/versions/android-2.3.html">2.3 - 2.3.2</a>
</td><td rowspan="2">Gingerbread</td> <td>9</td><td>0.2%</td></tr>
<tr><td><a href="/about/versions/android-2.3.3.html">2.3.3 - 2.3.7
- </a></td><!-- Gingerbread --> <td>10</td><td>44%</td></tr>
+ </a></td><!-- Gingerbread --> <td>10</td><td>43.9%</td></tr>
<tr><td><a href="/about/versions/android-3.1.html">3.1</a></td>
<td rowspan="2">Honeycomb</td> <td>12</td><td>0.3%</td></tr>
<tr><td><a href="/about/versions/android-3.2.html">3.2</a></td> <!-- Honeycomb --><td>13</td><td>0.9%</td></tr>
@@ -51,7 +51,7 @@
<div class="col-8" style="margin-right:0">
<img style="margin-left:30px" alt=""
-src="//chart.apis.google.com/chart?&cht=p&chs=460x245&chf=bg,s,00000000&chd=t:2.0,7.6,44.2,1.2,28.6,16.5&chl=Eclair%20%26%20older|Froyo|Gingerbread|Honeycomb|Ice%20Cream%20Sandwich|Jelly%20Bean&chco=c4df9b,6fad0c"
+src="//chart.apis.google.com/chart?&cht=p&chs=460x245&chf=bg,s,00000000&chd=t:2.1,7.5,44.1,1.2,28.6,16.5&chl=Eclair%20%26%20older|Froyo|Gingerbread|Honeycomb|Ice%20Cream%20Sandwich|Jelly%20Bean&chco=c4df9b,6fad0c"
/>
</div><!-- end dashboard-panel -->
diff --git a/docs/html/develop/index.jd b/docs/html/develop/index.jd
index 190a6d9..0cb2635 100644
--- a/docs/html/develop/index.jd
+++ b/docs/html/develop/index.jd
@@ -345,7 +345,7 @@
var playlistId = "PLWz5rJ2EKKc_XOgcRukSoKKjewFJZrKV0"; /* DevBytes */
var script = "<script type='text/javascript' src='//gdata.youtube.com/feeds/api/playlists/"
+ playlistId +
- "?v=2&alt=json-in-script&max-results=10&callback=renderDevelopersLivePlaylist&orderby=published'><\/script > ";
+ "?v=2&alt=json-in-script&max-results=10&callback=renderDevelopersLivePlaylist&orderby=reversedPosition'><\/script > ";
$("body").append(script);
}
diff --git a/docs/html/google/play/licensing/adding-licensing.jd b/docs/html/google/play/licensing/adding-licensing.jd
index f991e14..3f2460f 100644
--- a/docs/html/google/play/licensing/adding-licensing.jd
+++ b/docs/html/google/play/licensing/adding-licensing.jd
@@ -598,15 +598,15 @@
<p>First, open the class file of the application's main Activity and import
{@code LicenseChecker} and {@code LicenseCheckerCallback} from the LVL package.</p>
-<pre> import com.android.vending.licensing.LicenseChecker;
- import com.android.vending.licensing.LicenseCheckerCallback;</pre>
+<pre> import com.google.android.vending.licensing.LicenseChecker;
+ import com.google.android.vending.licensing.LicenseCheckerCallback;</pre>
<p>If you are using the default {@code Policy} implementation provided with the LVL,
ServerManagedPolicy, import it also, together with the AESObfuscator. If you are
using a custom {@code Policy} or {@code Obfuscator}, import those instead. </p>
-<pre> import com.android.vending.licensing.ServerManagedPolicy;
- import com.android.vending.licensing.AESObfuscator;</pre>
+<pre> import com.google.android.vending.licensing.ServerManagedPolicy;
+ import com.google.android.vending.licensing.AESObfuscator;</pre>
<h3 id="lc-impl">Implement LicenseCheckerCallback as a private inner class</h3>
diff --git a/docs/html/guide/topics/manifest/intent-filter-element.jd b/docs/html/guide/topics/manifest/intent-filter-element.jd
index f90541c..68da981 100644
--- a/docs/html/guide/topics/manifest/intent-filter-element.jd
+++ b/docs/html/guide/topics/manifest/intent-filter-element.jd
@@ -119,7 +119,11 @@
<p>
The value must be an integer, such as "{@code 100}". Higher numbers have a
-higher priority.
+higher priority. The default value is 0.
+The value must be greater than -1000 and less than 1000.</p>
+
+<p>Also see {@link android.content.IntentFilter#setPriority
+setPriority()}.
</p></dd>
</dl></dd>
diff --git a/docs/html/guide/topics/resources/animation-resource.jd b/docs/html/guide/topics/resources/animation-resource.jd
index 3af52aa..ef64f07 100644
--- a/docs/html/guide/topics/resources/animation-resource.jd
+++ b/docs/html/guide/topics/resources/animation-resource.jd
@@ -217,7 +217,7 @@
</dd>
<dt id="val-animator-element"><code><animator></code></dt>
- <dd>Animates a over a specified amount of time.
+ <dd>Performs an animation over a specified amount of time.
Represents a {@link android.animation.ValueAnimator}.
<p class="caps">attributes:</p>
diff --git a/docs/html/images/home/io-logo-2013.png b/docs/html/images/home/io-logo-2013.png
index c95719e..1a200e1 100644
--- a/docs/html/images/home/io-logo-2013.png
+++ b/docs/html/images/home/io-logo-2013.png
Binary files differ
diff --git a/docs/html/index.jd b/docs/html/index.jd
index a0029b5..f2df7be 100644
--- a/docs/html/index.jd
+++ b/docs/html/index.jd
@@ -24,7 +24,7 @@
<p>For more information about event details and planned sessions,
stay tuned to <a
href="http://google.com/+GoogleDevelopers">+Google Developers</a>.</p>
- <p><a href="https://developers.google.com/events/io/" class="button">Register here</a></p>
+ <p><a href="https://developers.google.com/events/io/register" class="button">Register here</a></p>
</div>
</li>
<li class="item carousel-home">
diff --git a/docs/html/training/gestures/detector.jd b/docs/html/training/gestures/detector.jd
index 06d0e98..65ddb1b 100644
--- a/docs/html/training/gestures/detector.jd
+++ b/docs/html/training/gestures/detector.jd
@@ -25,12 +25,18 @@
<li><a href="http://developer.android.com/guide/topics/ui/ui-events.html">Input Events</a> API Guide
</li>
<li><a href="{@docRoot}guide/topics/sensors/sensors_overview.html">Sensors Overview</a></li>
- <li><a href="http://android-developers.blogspot.com/2010/06/making-sense-of-multitouch.html">Making Sense of Multitouch</a> blog post</li>
<li><a href="{@docRoot}training/custom-views/making-interactive.html">Making the View Interactive</a> </li>
<li>Design Guide for <a href="{@docRoot}design/patterns/gestures.html">Gestures</a></li>
<li>Design Guide for <a href="{@docRoot}design/style/touch-feedback.html">Touch Feedback</a></li>
</ul>
+<h2>Try it out</h2>
+
+<div class="download-box">
+ <a href="{@docRoot}shareables/training/InteractiveChart.zip"
+class="button">Download the sample</a>
+ <p class="filename">InteractiveChart.zip</p>
+</div>
</div>
</div>
diff --git a/docs/html/training/gestures/index.jd b/docs/html/training/gestures/index.jd
index 0191450..16ca7b0 100644
--- a/docs/html/training/gestures/index.jd
+++ b/docs/html/training/gestures/index.jd
@@ -20,12 +20,18 @@
<li><a href="http://developer.android.com/guide/topics/ui/ui-events.html">Input Events</a> API Guide
</li>
<li><a href="{@docRoot}guide/topics/sensors/sensors_overview.html">Sensors Overview</a></li>
- <li><a href="http://android-developers.blogspot.com/2010/06/making-sense-of-multitouch.html">Making Sense of Multitouch</a> blog post</li>
<li><a href="{@docRoot}training/custom-views/making-interactive.html">Making the View Interactive</a> </li>
<li>Design Guide for <a href="{@docRoot}design/patterns/gestures.html">Gestures</a></li>
<li>Design Guide for <a href="{@docRoot}design/style/touch-feedback.html">Touch Feedback</a></li>
</ul>
+<h2>Try it out</h2>
+
+<div class="download-box">
+ <a href="{@docRoot}shareables/training/InteractiveChart.zip"
+class="button">Download the sample</a>
+ <p class="filename">InteractiveChart.zip</p>
+</div>
</div>
</div>
diff --git a/docs/html/training/gestures/movement.jd b/docs/html/training/gestures/movement.jd
index f2c49d7..fdc1ea4 100644
--- a/docs/html/training/gestures/movement.jd
+++ b/docs/html/training/gestures/movement.jd
@@ -24,12 +24,18 @@
<li><a href="http://developer.android.com/guide/topics/ui/ui-events.html">Input Events</a> API Guide
</li>
<li><a href="{@docRoot}guide/topics/sensors/sensors_overview.html">Sensors Overview</a></li>
- <li><a href="http://android-developers.blogspot.com/2010/06/making-sense-of-multitouch.html">Making Sense of Multitouch</a> blog post</li>
<li><a href="{@docRoot}training/custom-views/making-interactive.html">Making the View Interactive</a> </li>
<li>Design Guide for <a href="{@docRoot}design/patterns/gestures.html">Gestures</a></li>
<li>Design Guide for <a href="{@docRoot}design/style/touch-feedback.html">Touch Feedback</a></li>
</ul>
+<h2>Try it out</h2>
+
+<div class="download-box">
+ <a href="{@docRoot}shareables/training/InteractiveChart.zip"
+class="button">Download the sample</a>
+ <p class="filename">InteractiveChart.zip</p>
+</div>
</div>
</div>
diff --git a/docs/html/training/gestures/multi.jd b/docs/html/training/gestures/multi.jd
index d4c5b1d..6a0df11 100644
--- a/docs/html/training/gestures/multi.jd
+++ b/docs/html/training/gestures/multi.jd
@@ -25,12 +25,18 @@
<li><a href="http://developer.android.com/guide/topics/ui/ui-events.html">Input Events</a> API Guide
</li>
<li><a href="{@docRoot}guide/topics/sensors/sensors_overview.html">Sensors Overview</a></li>
- <li><a href="http://android-developers.blogspot.com/2010/06/making-sense-of-multitouch.html">Making Sense of Multitouch</a> blog post</li>
<li><a href="{@docRoot}training/custom-views/making-interactive.html">Making the View Interactive</a> </li>
<li>Design Guide for <a href="{@docRoot}design/patterns/gestures.html">Gestures</a></li>
<li>Design Guide for <a href="{@docRoot}design/style/touch-feedback.html">Touch Feedback</a></li>
</ul>
+<h2>Try it out</h2>
+
+<div class="download-box">
+ <a href="{@docRoot}shareables/training/InteractiveChart.zip"
+class="button">Download the sample</a>
+ <p class="filename">InteractiveChart.zip</p>
+</div>
</div>
</div>
diff --git a/docs/html/training/gestures/scale.jd b/docs/html/training/gestures/scale.jd
index 17e4085..f2e4eb8 100644
--- a/docs/html/training/gestures/scale.jd
+++ b/docs/html/training/gestures/scale.jd
@@ -15,6 +15,7 @@
<h2>This lesson teaches you to</h2>
<ol>
<li><a href="#drag">Drag an Object</a></li>
+ <li><a href="#pan">Drag to Pan</a></li>
<li><a href="#scale">Use Touch to Perform Scaling</a></li>
</ol>
@@ -25,20 +26,25 @@
<li><a href="http://developer.android.com/guide/topics/ui/ui-events.html">Input Events</a> API Guide
</li>
<li><a href="{@docRoot}guide/topics/sensors/sensors_overview.html">Sensors Overview</a></li>
- <li><a href="http://android-developers.blogspot.com/2010/06/making-sense-of-multitouch.html">Making Sense of Multitouch</a> blog post</li>
<li><a href="{@docRoot}training/custom-views/making-interactive.html">Making the View Interactive</a> </li>
<li>Design Guide for <a href="{@docRoot}design/patterns/gestures.html">Gestures</a></li>
<li>Design Guide for <a href="{@docRoot}design/style/touch-feedback.html">Touch Feedback</a></li>
</ul>
+<h2>Try it out</h2>
+
+<div class="download-box">
+ <a href="{@docRoot}shareables/training/InteractiveChart.zip"
+class="button">Download the sample</a>
+ <p class="filename">InteractiveChart.zip</p>
+</div>
</div>
</div>
+
<p>This lesson describes how to use touch gestures to drag and scale on-screen
objects, using {@link android.view.View#onTouchEvent onTouchEvent()} to intercept
-touch events. Here is the original <a
-href="http://code.google.com/p/android-touchexample/">source code</a>
-for the examples used in this lesson.
+touch events.
</p>
<h2 id="drag">Drag an Object</h2>
@@ -128,17 +134,15 @@
final float x = MotionEventCompat.getX(ev, pointerIndex);
final float y = MotionEventCompat.getY(ev, pointerIndex);
- // Only move if the ScaleGestureDetector isn't processing a gesture.
- if (!mScaleDetector.isInProgress()) {
- // Calculate the distance moved
- final float dx = x - mLastTouchX;
- final float dy = y - mLastTouchY;
+ // Calculate the distance moved
+ final float dx = x - mLastTouchX;
+ final float dy = y - mLastTouchY;
- mPosX += dx;
- mPosY += dy;
+ mPosX += dx;
+ mPosY += dy;
- invalidate();
- }
+ invalidate();
+
// Remember this touch position for the next move event
mLastTouchX = x;
mLastTouchY = y;
@@ -175,6 +179,88 @@
return true;
}</pre>
+<h2 id="pan">Drag to Pan</h2>
+
+<p>The previous section showed an example of dragging an object around the screen. Another
+common scenario is <em>panning</em>, which is when a user's dragging motion causes scrolling
+in both the x and y axes. The above snippet directly intercepted the {@link android.view.MotionEvent}
+actions to implement dragging. The snippet in this section takes advantage of the platform's
+built-in support for common gestures. It overrides
+{@link android.view.GestureDetector.OnGestureListener#onScroll onScroll()} in
+{@link android.view.GestureDetector.SimpleOnGestureListener}.</p>
+
+<p>To provide a little more context, {@link android.view.GestureDetector.OnGestureListener#onScroll onScroll()}
+is called when a user is dragging his finger to pan the content.
+{@link android.view.GestureDetector.OnGestureListener#onScroll onScroll()} is only called when
+a finger is down; as soon as the finger is lifted from the screen, the gesture either ends,
+or a fling gesture is started (if the finger was moving with some speed just before it was lifted).
+For more discussion of scrolling vs. flinging, see <a href="scroll.html">Animating a Scroll Gesture</a>.</p>
+
+<p>Here is the snippet for {@link android.view.GestureDetector.OnGestureListener#onScroll onScroll()}:
+
+
+<pre>// The current viewport. This rectangle represents the currently visible
+// chart domain and range.
+private RectF mCurrentViewport =
+ new RectF(AXIS_X_MIN, AXIS_Y_MIN, AXIS_X_MAX, AXIS_Y_MAX);
+
+// The current destination rectangle (in pixel coordinates) into which the
+// chart data should be drawn.
+private Rect mContentRect;
+
+private final GestureDetector.SimpleOnGestureListener mGestureListener
+ = new GestureDetector.SimpleOnGestureListener() {
+...
+
+@Override
+public boolean onScroll(MotionEvent e1, MotionEvent e2,
+ float distanceX, float distanceY) {
+ // Scrolling uses math based on the viewport (as opposed to math using pixels).
+
+ // Pixel offset is the offset in screen pixels, while viewport offset is the
+ // offset within the current viewport.
+ float viewportOffsetX = distanceX * mCurrentViewport.width()
+ / mContentRect.width();
+ float viewportOffsetY = -distanceY * mCurrentViewport.height()
+ / mContentRect.height();
+ ...
+ // Updates the viewport, refreshes the display.
+ setViewportBottomLeft(
+ mCurrentViewport.left + viewportOffsetX,
+ mCurrentViewport.bottom + viewportOffsetY);
+ ...
+ return true;
+}</pre>
+
+<p>The implementation of {@link android.view.GestureDetector.OnGestureListener#onScroll onScroll()}
+scrolls the viewport in response to the touch gesture:</p>
+
+<pre>
+/**
+ * Sets the current viewport (defined by mCurrentViewport) to the given
+ * X and Y positions. Note that the Y value represents the topmost pixel position,
+ * and thus the bottom of the mCurrentViewport rectangle.
+ */
+private void setViewportBottomLeft(float x, float y) {
+ /*
+ * Constrains within the scroll range. The scroll range is simply the viewport
+ * extremes (AXIS_X_MAX, etc.) minus the viewport size. For example, if the
+ * extremes were 0 and 10, and the viewport size was 2, the scroll range would
+ * be 0 to 8.
+ */
+
+ float curWidth = mCurrentViewport.width();
+ float curHeight = mCurrentViewport.height();
+ x = Math.max(AXIS_X_MIN, Math.min(x, AXIS_X_MAX - curWidth));
+ y = Math.max(AXIS_Y_MIN + curHeight, Math.min(y, AXIS_Y_MAX));
+
+ mCurrentViewport.set(x, y - curHeight, x + curWidth, y);
+
+ // Invalidates the View to update the display.
+ ViewCompat.postInvalidateOnAnimation(this);
+}
+</pre>
+
<h2 id="scale">Use Touch to Perform Scaling</h2>
<p>As discussed in <a href="detector.html">Detecting Common Gestures</a>,
@@ -191,10 +277,10 @@
{@link android.view.ScaleGestureDetector.SimpleOnScaleGestureListener}
as a helper class that you can extend if you don’t care about all of the reported events.</p>
-<p>Here is a snippet that gives you the basic idea of how to perform scaling.
-Here is the original <a
-href="http://code.google.com/p/android-touchexample/">source code</a>
-for the examples.</p>
+
+<h3>Basic scaling example</h3>
+
+<p>Here is a snippet that illustrates the basic ingredients involved in scaling.</p>
<pre>private ScaleGestureDetector mScaleDetector;
private float mScaleFactor = 1.f;
@@ -238,3 +324,88 @@
return true;
}
}</pre>
+
+
+
+
+<h3>More complex scaling example</h3>
+<p>Here is a more complex example from the {@code InteractiveChart} sample provided with this class.
+The {@code InteractiveChart} sample supports both scrolling (panning) and scaling with multiple fingers,
+using the {@link android.view.ScaleGestureDetector} "span"
+({@link android.view.ScaleGestureDetector#getCurrentSpanX getCurrentSpanX/Y}) and
+"focus" ({@link android.view.ScaleGestureDetector#getFocusX getFocusX/Y}) features:</p>
+
+<pre>@Override
+private RectF mCurrentViewport =
+ new RectF(AXIS_X_MIN, AXIS_Y_MIN, AXIS_X_MAX, AXIS_Y_MAX);
+private Rect mContentRect;
+private ScaleGestureDetector mScaleGestureDetector;
+...
+public boolean onTouchEvent(MotionEvent event) {
+ boolean retVal = mScaleGestureDetector.onTouchEvent(event);
+ retVal = mGestureDetector.onTouchEvent(event) || retVal;
+ return retVal || super.onTouchEvent(event);
+}
+
+/**
+ * The scale listener, used for handling multi-finger scale gestures.
+ */
+private final ScaleGestureDetector.OnScaleGestureListener mScaleGestureListener
+ = new ScaleGestureDetector.SimpleOnScaleGestureListener() {
+ /**
+ * This is the active focal point in terms of the viewport. Could be a local
+ * variable but kept here to minimize per-frame allocations.
+ */
+ private PointF viewportFocus = new PointF();
+ private float lastSpanX;
+ private float lastSpanY;
+
+ // Detects that new pointers are going down.
+ @Override
+ public boolean onScaleBegin(ScaleGestureDetector scaleGestureDetector) {
+ lastSpanX = ScaleGestureDetectorCompat.
+ getCurrentSpanX(scaleGestureDetector);
+ lastSpanY = ScaleGestureDetectorCompat.
+ getCurrentSpanY(scaleGestureDetector);
+ return true;
+ }
+
+ @Override
+ public boolean onScale(ScaleGestureDetector scaleGestureDetector) {
+
+ float spanX = ScaleGestureDetectorCompat.
+ getCurrentSpanX(scaleGestureDetector);
+ float spanY = ScaleGestureDetectorCompat.
+ getCurrentSpanY(scaleGestureDetector);
+
+ float newWidth = lastSpanX / spanX * mCurrentViewport.width();
+ float newHeight = lastSpanY / spanY * mCurrentViewport.height();
+
+ float focusX = scaleGestureDetector.getFocusX();
+ float focusY = scaleGestureDetector.getFocusY();
+ // Makes sure that the chart point is within the chart region.
+ // See the sample for the implementation of hitTest().
+ hitTest(scaleGestureDetector.getFocusX(),
+ scaleGestureDetector.getFocusY(),
+ viewportFocus);
+
+ mCurrentViewport.set(
+ viewportFocus.x
+ - newWidth * (focusX - mContentRect.left)
+ / mContentRect.width(),
+ viewportFocus.y
+ - newHeight * (mContentRect.bottom - focusY)
+ / mContentRect.height(),
+ 0,
+ 0);
+ mCurrentViewport.right = mCurrentViewport.left + newWidth;
+ mCurrentViewport.bottom = mCurrentViewport.top + newHeight;
+ ...
+ // Invalidates the View to update the display.
+ ViewCompat.postInvalidateOnAnimation(InteractiveLineGraphView.this);
+
+ lastSpanX = spanX;
+ lastSpanY = spanY;
+ return true;
+ }
+};</pre>
diff --git a/docs/html/training/gestures/scroll.jd b/docs/html/training/gestures/scroll.jd
index 8576948..bd1537a 100644
--- a/docs/html/training/gestures/scroll.jd
+++ b/docs/html/training/gestures/scroll.jd
@@ -14,6 +14,7 @@
<!-- table of contents -->
<h2>This lesson teaches you to</h2>
<ol>
+ <li><a href="#term">Understand Scrolling Terminology</a></li>
<li><a href="#scroll">Implement Touch-Based Scrolling</a></li>
</ol>
@@ -24,12 +25,18 @@
<li><a href="http://developer.android.com/guide/topics/ui/ui-events.html">Input Events</a> API Guide
</li>
<li><a href="{@docRoot}guide/topics/sensors/sensors_overview.html">Sensors Overview</a></li>
- <li><a href="http://android-developers.blogspot.com/2010/06/making-sense-of-multitouch.html">Making Sense of Multitouch</a> blog post</li>
<li><a href="{@docRoot}training/custom-views/making-interactive.html">Making the View Interactive</a> </li>
<li>Design Guide for <a href="{@docRoot}design/patterns/gestures.html">Gestures</a></li>
<li>Design Guide for <a href="{@docRoot}design/style/touch-feedback.html">Touch Feedback</a></li>
</ul>
+<h2>Try it out</h2>
+
+<div class="download-box">
+ <a href="{@docRoot}shareables/training/InteractiveChart.zip"
+class="button">Download the sample</a>
+ <p class="filename">InteractiveChart.zip</p>
+</div>
</div>
</div>
@@ -45,7 +52,26 @@
<p>You can use scrollers ({@link android.widget.Scroller} or {@link
android.widget.OverScroller}) to collect the data you need to produce a
-scrolling animation in response to a touch event.</p>
+scrolling animation in response to a touch event. They are similar, but
+{@link android.widget.OverScroller}
+includes methods for indicating to users that they've reached the content edges
+after a pan or fling gesture. The {@code InteractiveChart} sample
+uses the the {@link android.widget.EdgeEffect} class
+(actually the {@link android.support.v4.widget.EdgeEffectCompat} class)
+to display a "glow" effect when users reach the content edges.</p>
+
+<p class="note"><strong>Note:</strong> We recommend that you
+use {@link android.widget.OverScroller} rather than {@link
+android.widget.Scroller} for scrolling animations.
+{@link android.widget.OverScroller} provides the best backward
+compatibility with older devices.
+<br />
+Also note that you generally only need to use scrollers
+when implementing scrolling yourself. {@link android.widget.ScrollView} and
+{@link android.widget.HorizontalScrollView} do all of this for you if you nest your
+layout within them.
+</p>
+
<p>A scroller is used to animate scrolling over time, using platform-standard
scrolling physics (friction, velocity, etc.). The scroller itself doesn't
@@ -54,101 +80,280 @@
responsibility to get and apply new coordinates at a rate that will make the
scrolling animation look smooth.</p>
-<p class="note"><strong>Note:</strong> You generally only need to use scrollers
-when implementing scrolling yourself. {@link android.widget.ScrollView} and
-{@link android.widget.HorizontalScrollView} do all this for you do all of this for you if you nest your layout within them.</p>
-
-<h2 id = "scroll">Implement Touch-Based Scrolling</h2>
-<p>This snippet illustrates the basics of using a scroller. It uses a
-{@link android.view.GestureDetector}, and overrides the
-{@link android.view.GestureDetector.SimpleOnGestureListener} methods
-{@link android.view.GestureDetector.OnGestureListener#onDown onDown()} and
-{@link android.view.GestureDetector.OnGestureListener#onFling onFling()}. It also
-overrides {@link android.view.GestureDetector.OnGestureListener#onScroll onScroll()}
-to return {@code false} since you don't need to animate a scroll.</p>
+<h2 id="term">Understand Scrolling Terminology</h2>
+<p>"Scrolling" is a word that can take on different meanings in Android, depending on the context.</p>
-<p>It's common to use scrollers in conjunction with a fling gesture, but they
+<p><strong>Scrolling</strong> is the general process of moving the viewport (that is, the 'window'
+of content you're looking at). When scrolling is in both the x and y axes, it's called
+<em>panning</em>. The sample application provided with this class, {@code InteractiveChart}, illustrates
+two different types of scrolling, dragging and flinging:</p>
+<ul>
+ <li><strong>Dragging</strong> is the type of scrolling that occurs when a user drags her
+finger across the touch screen. Simple dragging is often implemented by overriding
+{@link android.view.GestureDetector.OnGestureListener#onScroll onScroll()} in
+{@link android.view.GestureDetector.OnGestureListener}. For more discussion of dragging, see
+<a href="dragging.jd">Dragging and Scaling</a>.</li>
+
+ <li><strong>Flinging</strong> is the type of scrolling that occurs when a user
+drags and lifts her finger quickly. After the user lifts her finger, you generally
+want to keep scrolling (moving the viewport), but decelerate until the viewport stops moving.
+Flinging can be implemented by overriding
+{@link android.view.GestureDetector.OnGestureListener#onFling onFling()}
+in {@link android.view.GestureDetector.OnGestureListener}, and by using
+a scroller object. This is the use
+case that is the topic of this lesson.</li>
+</ul>
+
+<p>It's common to use scroller objects
+in conjunction with a fling gesture, but they
can be used in pretty much any context where you want the UI to display
-scrolling in response to a touch event. For example, you could override {@link
-android.view.View#onTouchEvent onTouchEvent()} to process touch events directly,
-and produce a scrolling effect in response to those touch events.</p>
+scrolling in response to a touch event. For example, you could override
+{@link android.view.View#onTouchEvent onTouchEvent()} to process touch
+events directly, and produce a scrolling effect or a "snapping to page" animation
+in response to those touch events.</p>
-<pre>
-private OverScroller mScroller = new OverScroller(context);
-private GestureDetector.SimpleOnGestureListener mGestureListener
+<h2 id="#scroll">Implement Touch-Based Scrolling</h2>
+
+<p>This section describes how to use a scroller.
+The snippet shown below comes from the {@code InteractiveChart} sample
+provided with this class.
+It uses a
+{@link android.view.GestureDetector}, and overrides the
+{@link android.view.GestureDetector.SimpleOnGestureListener} method
+{@link android.view.GestureDetector.OnGestureListener#onFling onFling()}.
+It uses {@link android.widget.OverScroller} to track the fling gesture.
+If the user reaches the content edges
+after the fling gesture, the app displays a "glow" effect.
+</p>
+
+<p class="note"><strong>Note:</strong> The {@code InteractiveChart} sample app displays a
+chart that you can zoom, pan, scroll, and so on. In the following snippet,
+{@code mContentRect} represents the rectangle coordinates within the view that the chart
+will be drawn into. At any given time, a subset of the total chart domain and range are drawn
+into this rectangular area.
+{@code mCurrentViewport} represents the portion of the chart that is currently
+visible in the screen. Because pixel offsets are generally treated as integers,
+{@code mContentRect} is of the type {@link android.graphics.Rect}. Because the
+graph domain and range are decimal/float values, {@code mCurrentViewport} is of
+the type {@link android.graphics.RectF}.</p>
+
+<p>The first part of the snippet shows the implementation of
+{@link android.view.GestureDetector.OnGestureListener#onFling onFling()}:</p>
+
+<pre>// The current viewport. This rectangle represents the currently visible
+// chart domain and range. The viewport is the part of the app that the
+// user manipulates via touch gestures.
+private RectF mCurrentViewport =
+ new RectF(AXIS_X_MIN, AXIS_Y_MIN, AXIS_X_MAX, AXIS_Y_MAX);
+
+// The current destination rectangle (in pixel coordinates) into which the
+// chart data should be drawn.
+private Rect mContentRect;
+
+private OverScroller mScroller;
+private RectF mScrollerStartViewport;
+...
+private final GestureDetector.SimpleOnGestureListener mGestureListener
= new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onDown(MotionEvent e) {
- // Abort any active scroll animations and invalidate.
+ // Initiates the decay phase of any active edge effects.
+ releaseEdgeEffects();
+ mScrollerStartViewport.set(mCurrentViewport);
+ // Aborts any active scroll animations and invalidates.
mScroller.forceFinished(true);
- // There is also a compatibility version:
- // ViewCompat.postInvalidateOnAnimation
- postInvalidateOnAnimation();
+ ViewCompat.postInvalidateOnAnimation(InteractiveLineGraphView.this);
return true;
}
-
- @Override
- public boolean onScroll(MotionEvent e1, MotionEvent e2,
- float distanceX, float distanceY) {
- // You don't use a scroller in onScroll because you don't need to animate
- // a scroll. The scroll occurs instantly in response to touch feedback.
- return false;
- }
-
+ ...
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2,
float velocityX, float velocityY) {
- // Before flinging, abort the current animation.
- mScroller.forceFinished(true);
- // Begin the scroll animation
- mScroller.fling(
- // Current scroll position
- startX,
- startY,
- // Velocities, negated for natural touch response
- (int) -velocityX,
- (int) -velocityY,
- // Minimum and maximum scroll positions. The minimum scroll
- // position is generally zero and the maximum scroll position
- // is generally the content size less the screen size. So if the
- // content width is 1000 pixels and the screen width is 200
- // pixels, the maximum scroll offset should be 800 pixels.
- minX, maxX,
- minY, maxY,
- // The maximum overscroll bounds. This is useful when using
- // the EdgeEffect class to draw overscroll "glow" overlays.
- mContentRect.width() / 2,
- mContentRect.height() / 2);
- // Invalidate to trigger computeScroll()
- postInvalidateOnAnimation();
+ fling((int) -velocityX, (int) -velocityY);
return true;
}
};
+private void fling(int velocityX, int velocityY) {
+ // Initiates the decay phase of any active edge effects.
+ releaseEdgeEffects();
+ // Flings use math in pixels (as opposed to math based on the viewport).
+ Point surfaceSize = computeScrollSurfaceSize();
+ mScrollerStartViewport.set(mCurrentViewport);
+ int startX = (int) (surfaceSize.x * (mScrollerStartViewport.left -
+ AXIS_X_MIN) / (
+ AXIS_X_MAX - AXIS_X_MIN));
+ int startY = (int) (surfaceSize.y * (AXIS_Y_MAX -
+ mScrollerStartViewport.bottom) / (
+ AXIS_Y_MAX - AXIS_Y_MIN));
+ // Before flinging, aborts the current animation.
+ mScroller.forceFinished(true);
+ // Begins the animation
+ mScroller.fling(
+ // Current scroll position
+ startX,
+ startY,
+ velocityX,
+ velocityY,
+ /*
+ * Minimum and maximum scroll positions. The minimum scroll
+ * position is generally zero and the maximum scroll position
+ * is generally the content size less the screen size. So if the
+ * content width is 1000 pixels and the screen width is 200
+ * pixels, the maximum scroll offset should be 800 pixels.
+ */
+ 0, surfaceSize.x - mContentRect.width(),
+ 0, surfaceSize.y - mContentRect.height(),
+ // The edges of the content. This comes into play when using
+ // the EdgeEffect class to draw "glow" overlays.
+ mContentRect.width() / 2,
+ mContentRect.height() / 2);
+ // Invalidates to trigger computeScroll()
+ ViewCompat.postInvalidateOnAnimation(this);
+}</pre>
+
+<p>When {@link android.view.GestureDetector.OnGestureListener#onFling onFling()} calls
+{@link android.support.v4.view.ViewCompat#postInvalidateOnAnimation postInvalidateOnAnimation()},
+it triggers
+{@link android.view.View#computeScroll computeScroll()} to update the values for x and y.
+This is typically be done when a view child is animating a scroll using a scroller object, as in this example. </p>
+
+<p>Most views pass the scroller object's x and y position directly to
+{@link android.view.View#scrollTo scrollTo()}.
+The following implementation of {@link android.view.View#computeScroll computeScroll()}
+takes a different approach—it calls
+{@link android.widget.OverScroller#computeScrollOffset computeScrollOffset()} to get the current
+location of x and y. When the criteria for displaying an overscroll "glow" edge effect are met
+(the display is zoomed in, x or y is out of bounds, and the app isn't already showing an overscroll),
+the code sets up the overscroll glow effect and calls
+{@link android.support.v4.view.ViewCompat#postInvalidateOnAnimation postInvalidateOnAnimation()}
+to trigger an invalidate on the view:</p>
+
+<pre>// Edge effect / overscroll tracking objects.
+private EdgeEffectCompat mEdgeEffectTop;
+private EdgeEffectCompat mEdgeEffectBottom;
+private EdgeEffectCompat mEdgeEffectLeft;
+private EdgeEffectCompat mEdgeEffectRight;
+
+private boolean mEdgeEffectTopActive;
+private boolean mEdgeEffectBottomActive;
+private boolean mEdgeEffectLeftActive;
+private boolean mEdgeEffectRightActive;
+
@Override
public void computeScroll() {
super.computeScroll();
- // Compute the current scroll offsets. If this returns true, then the
- // scroll has not yet finished.
+ boolean needsInvalidate = false;
+
+ // The scroller isn't finished, meaning a fling or programmatic pan
+ // operation is currently active.
if (mScroller.computeScrollOffset()) {
+ Point surfaceSize = computeScrollSurfaceSize();
int currX = mScroller.getCurrX();
int currY = mScroller.getCurrY();
- // Actually render the scrolled viewport, or actually scroll the
- // view using View.scrollTo.
+ boolean canScrollX = (mCurrentViewport.left > AXIS_X_MIN
+ || mCurrentViewport.right < AXIS_X_MAX);
+ boolean canScrollY = (mCurrentViewport.top > AXIS_Y_MIN
+ || mCurrentViewport.bottom < AXIS_Y_MAX);
- // If currX or currY are outside the bounds, render the overscroll
- // glow using EdgeEffect.
+ /*
+ * If you are zoomed in and currX or currY is
+ * outside of bounds and you're not already
+ * showing overscroll, then render the overscroll
+ * glow edge effect.
+ */
+ if (canScrollX
+ && currX < 0
+ && mEdgeEffectLeft.isFinished()
+ && !mEdgeEffectLeftActive) {
+ mEdgeEffectLeft.onAbsorb((int)
+ OverScrollerCompat.getCurrVelocity(mScroller));
+ mEdgeEffectLeftActive = true;
+ needsInvalidate = true;
+ } else if (canScrollX
+ && currX > (surfaceSize.x - mContentRect.width())
+ && mEdgeEffectRight.isFinished()
+ && !mEdgeEffectRightActive) {
+ mEdgeEffectRight.onAbsorb((int)
+ OverScrollerCompat.getCurrVelocity(mScroller));
+ mEdgeEffectRightActive = true;
+ needsInvalidate = true;
+ }
- } else {
- // The scroll has finished.
- }
+ if (canScrollY
+ && currY < 0
+ && mEdgeEffectTop.isFinished()
+ && !mEdgeEffectTopActive) {
+ mEdgeEffectTop.onAbsorb((int)
+ OverScrollerCompat.getCurrVelocity(mScroller));
+ mEdgeEffectTopActive = true;
+ needsInvalidate = true;
+ } else if (canScrollY
+ && currY > (surfaceSize.y - mContentRect.height())
+ && mEdgeEffectBottom.isFinished()
+ && !mEdgeEffectBottomActive) {
+ mEdgeEffectBottom.onAbsorb((int)
+ OverScrollerCompat.getCurrVelocity(mScroller));
+ mEdgeEffectBottomActive = true;
+ needsInvalidate = true;
+ }
+ ...
+ }</pre>
+
+<p>Here is the section of the code that performs the actual zoom:</p>
+
+<pre>// Custom object that is functionally similar to Scroller
+Zoomer mZoomer;
+private PointF mZoomFocalPoint = new PointF();
+...
+
+// If a zoom is in progress (either programmatically or via double
+// touch), performs the zoom.
+if (mZoomer.computeZoom()) {
+ float newWidth = (1f - mZoomer.getCurrZoom()) *
+ mScrollerStartViewport.width();
+ float newHeight = (1f - mZoomer.getCurrZoom()) *
+ mScrollerStartViewport.height();
+ float pointWithinViewportX = (mZoomFocalPoint.x -
+ mScrollerStartViewport.left)
+ / mScrollerStartViewport.width();
+ float pointWithinViewportY = (mZoomFocalPoint.y -
+ mScrollerStartViewport.top)
+ / mScrollerStartViewport.height();
+ mCurrentViewport.set(
+ mZoomFocalPoint.x - newWidth * pointWithinViewportX,
+ mZoomFocalPoint.y - newHeight * pointWithinViewportY,
+ mZoomFocalPoint.x + newWidth * (1 - pointWithinViewportX),
+ mZoomFocalPoint.y + newHeight * (1 - pointWithinViewportY));
+ constrainViewport();
+ needsInvalidate = true;
+}
+if (needsInvalidate) {
+ ViewCompat.postInvalidateOnAnimation(this);
+}
+</pre>
+
+<p>This is the {@code computeScrollSurfaceSize()} method that's called in the above snippet. It
+computes the current scrollable surface size, in pixels. For example, if the entire chart area is visible,
+this is simply the current size of {@code mContentRect}. If the chart is zoomed in 200% in both directions,
+the returned size will be twice as large horizontally and vertically.</p>
+
+<pre>private Point computeScrollSurfaceSize() {
+ return new Point(
+ (int) (mContentRect.width() * (AXIS_X_MAX - AXIS_X_MIN)
+ / mCurrentViewport.width()),
+ (int) (mContentRect.height() * (AXIS_Y_MAX - AXIS_Y_MIN)
+ / mCurrentViewport.height()));
}</pre>
-<p>For another example of scroller usage, see the <a href="http://github.com/android/platform_frameworks_support/blob/master/v4/java/android/support/v4/view/ViewPager.java">source code</a> for the
-{@link android.support.v4.view.ViewPager} class.</p>
+<p>For another example of scroller usage, see the
+<a href="http://github.com/android/platform_frameworks_support/blob/master/v4/java/android/support/v4/view/ViewPager.java">source code</a> for the
+{@link android.support.v4.view.ViewPager} class. It scrolls in response to flings,
+and uses scrolling to implement the "snapping to page" animation.</p>
+
diff --git a/docs/html/training/gestures/viewgroup.jd b/docs/html/training/gestures/viewgroup.jd
index 257a5d8..5b32300 100644
--- a/docs/html/training/gestures/viewgroup.jd
+++ b/docs/html/training/gestures/viewgroup.jd
@@ -26,12 +26,19 @@
<li><a href="http://developer.android.com/guide/topics/ui/ui-events.html">Input Events</a> API Guide
</li>
<li><a href="{@docRoot}guide/topics/sensors/sensors_overview.html">Sensors Overview</a></li>
- <li><a href="http://android-developers.blogspot.com/2010/06/making-sense-of-multitouch.html">Making Sense of Multitouch</a> blog post</li>
<li><a href="{@docRoot}training/custom-views/making-interactive.html">Making the View Interactive</a> </li>
<li>Design Guide for <a href="{@docRoot}design/patterns/gestures.html">Gestures</a></li>
<li>Design Guide for <a href="{@docRoot}design/style/touch-feedback.html">Touch Feedback</a></li>
</ul>
+<h2>Try it out</h2>
+
+<div class="download-box">
+ <a href="{@docRoot}shareables/training/InteractiveChart.zip"
+class="button">Download the sample</a>
+ <p class="filename">InteractiveChart.zip</p>
+</div>
+
</div>
</div>
diff --git a/docs/html/training/id-auth/authenticate.jd b/docs/html/training/id-auth/authenticate.jd
index 592fe1c..3084bea 100644
--- a/docs/html/training/id-auth/authenticate.jd
+++ b/docs/html/training/id-auth/authenticate.jd
@@ -114,7 +114,7 @@
new Handler(new OnError())); // Callback called if an error occurs
</pre>
-<p>In this example, <code>OnTokenAcquired</code> is a class that extends
+<p>In this example, <code>OnTokenAcquired</code> is a class that implements
{@link android.accounts.AccountManagerCallback}. {@link android.accounts.AccountManager} calls
{@link android.accounts.AccountManagerCallback#run run()} on <code>OnTokenAcquired</code> with an
{@link android.accounts.AccountManagerFuture} that contains a {@link android.os.Bundle}. If
@@ -179,7 +179,7 @@
@Override
public void run(AccountManagerFuture<Bundle> result) {
...
- Intent launch = (Intent) result.get(AccountManager.KEY_INTENT);
+ Intent launch = (Intent) result.getResult().get(AccountManager.KEY_INTENT);
if (launch != null) {
startActivityForResult(launch, 0);
return;
diff --git a/docs/html/training/implementing-navigation/lateral.jd b/docs/html/training/implementing-navigation/lateral.jd
index b59bab2..9a31d7a 100644
--- a/docs/html/training/implementing-navigation/lateral.jd
+++ b/docs/html/training/implementing-navigation/lateral.jd
@@ -131,6 +131,9 @@
ViewPager mViewPager;
public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_collection_demo);
+
// ViewPager and its adapters use support library
// fragments, so use getSupportFragmentManager.
mDemoCollectionPagerAdapter =
diff --git a/graphics/java/android/renderscript/ScriptIntrinsic3DLUT.java b/graphics/java/android/renderscript/ScriptIntrinsic3DLUT.java
index 24af6ea..3e58b87 100644
--- a/graphics/java/android/renderscript/ScriptIntrinsic3DLUT.java
+++ b/graphics/java/android/renderscript/ScriptIntrinsic3DLUT.java
@@ -45,7 +45,7 @@
int id = rs.nScriptIntrinsicCreate(8, e.getID(rs));
if (!e.isCompatible(Element.U8_4(rs))) {
- throw new RSIllegalArgumentException("Element must be compatibile with uchar4.");
+ throw new RSIllegalArgumentException("Element must be compatible with uchar4.");
}
return new ScriptIntrinsic3DLUT(id, rs, e);
diff --git a/libs/androidfw/BackupHelpers.cpp b/libs/androidfw/BackupHelpers.cpp
index dcf41b7..b8d3f48 100644
--- a/libs/androidfw/BackupHelpers.cpp
+++ b/libs/androidfw/BackupHelpers.cpp
@@ -553,7 +553,7 @@
if (buf == NULL) {
ALOGE("Out of mem allocating transfer buffer");
err = ENOMEM;
- goto cleanup;
+ goto done;
}
// Magic fields for the ustar file format
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index 33d8063..1618110 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -5,7 +5,9 @@
# defined in the current device/board configuration
ifeq ($(USE_OPENGL_RENDERER),true)
LOCAL_SRC_FILES:= \
+ utils/Blur.cpp \
utils/SortedListImpl.cpp \
+ thread/TaskManager.cpp \
font/CacheTexture.cpp \
font/Font.cpp \
FontRenderer.cpp \
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index ca699d5..dc32a7e 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -25,6 +25,9 @@
#include <cutils/compiler.h>
+#include "thread/TaskProcessor.h"
+#include "thread/TaskManager.h"
+
#include "FontRenderer.h"
#include "GammaFontRenderer.h"
#include "TextureCache.h"
@@ -278,6 +281,8 @@
GammaFontRenderer* fontRenderer;
+ TaskManager tasks;
+
Dither dither;
Stencil stencil;
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index d231907..105f45f 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -1005,7 +1005,7 @@
: DrawBoundedOp(paint), mPath(path) {
float left, top, offset;
uint32_t width, height;
- computePathBounds(path, paint, left, top, offset, width, height);
+ PathCache::computePathBounds(path, paint, left, top, offset, width, height);
left -= offset;
top -= offset;
mLocalBounds.set(left, top, left + width, top + height);
@@ -1016,6 +1016,11 @@
return renderer.drawPath(mPath, getPaint(renderer));
}
+ virtual void onDrawOpDeferred(OpenGLRenderer& renderer) {
+ SkPaint* paint = getPaint(renderer);
+ renderer.getCaches().pathCache.precache(mPath, paint);
+ }
+
virtual void output(int level, uint32_t flags) {
OP_LOG("Draw Path %p in "RECT_STRING, mPath, RECT_ARGS(mLocalBounds));
}
diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp
index 77b8df1..f0dcb30 100644
--- a/libs/hwui/FontRenderer.cpp
+++ b/libs/hwui/FontRenderer.cpp
@@ -23,9 +23,11 @@
#include <utils/Log.h>
-#include "RenderScript.h"
+#include <RenderScript.h>
+#include "utils/Blur.h"
#include "utils/Timing.h"
+
#include "Caches.h"
#include "Debug.h"
#include "FontRenderer.h"
@@ -569,7 +571,7 @@
}
int size = paddedWidth * paddedHeight;
- uint8_t* dataBuffer = (uint8_t*)memalign(RS_CPU_ALLOCATION_ALIGNMENT, size);
+ uint8_t* dataBuffer = (uint8_t*) memalign(RS_CPU_ALLOCATION_ALIGNMENT, size);
memset(dataBuffer, 0, size);
int penX = radius - bounds.left;
@@ -655,147 +657,21 @@
}
}
-void FontRenderer::computeGaussianWeights(float* weights, int32_t radius) {
- // Compute gaussian weights for the blur
- // e is the euler's number
- float e = 2.718281828459045f;
- float pi = 3.1415926535897932f;
- // g(x) = ( 1 / sqrt( 2 * pi ) * sigma) * e ^ ( -x^2 / 2 * sigma^2 )
- // x is of the form [-radius .. 0 .. radius]
- // and sigma varies with radius.
- // Based on some experimental radius values and sigma's
- // we approximately fit sigma = f(radius) as
- // sigma = radius * 0.3 + 0.6
- // The larger the radius gets, the more our gaussian blur
- // will resemble a box blur since with large sigma
- // the gaussian curve begins to lose its shape
- float sigma = 0.3f * (float) radius + 0.6f;
-
- // Now compute the coefficints
- // We will store some redundant values to save some math during
- // the blur calculations
- // precompute some values
- float coeff1 = 1.0f / (sqrt( 2.0f * pi ) * sigma);
- float coeff2 = - 1.0f / (2.0f * sigma * sigma);
-
- float normalizeFactor = 0.0f;
- for (int32_t r = -radius; r <= radius; r ++) {
- float floatR = (float) r;
- weights[r + radius] = coeff1 * pow(e, floatR * floatR * coeff2);
- normalizeFactor += weights[r + radius];
- }
-
- //Now we need to normalize the weights because all our coefficients need to add up to one
- normalizeFactor = 1.0f / normalizeFactor;
- for (int32_t r = -radius; r <= radius; r ++) {
- weights[r + radius] *= normalizeFactor;
- }
-}
-
-void FontRenderer::horizontalBlur(float* weights, int32_t radius,
- const uint8_t* source, uint8_t* dest, int32_t width, int32_t height) {
- float blurredPixel = 0.0f;
- float currentPixel = 0.0f;
-
- for (int32_t y = 0; y < height; y ++) {
-
- const uint8_t* input = source + y * width;
- uint8_t* output = dest + y * width;
-
- for (int32_t x = 0; x < width; x ++) {
- blurredPixel = 0.0f;
- const float* gPtr = weights;
- // Optimization for non-border pixels
- if (x > radius && x < (width - radius)) {
- const uint8_t *i = input + (x - radius);
- for (int r = -radius; r <= radius; r ++) {
- currentPixel = (float) (*i);
- blurredPixel += currentPixel * gPtr[0];
- gPtr++;
- i++;
- }
- } else {
- for (int32_t r = -radius; r <= radius; r ++) {
- // Stepping left and right away from the pixel
- int validW = x + r;
- if (validW < 0) {
- validW = 0;
- }
- if (validW > width - 1) {
- validW = width - 1;
- }
-
- currentPixel = (float) input[validW];
- blurredPixel += currentPixel * gPtr[0];
- gPtr++;
- }
- }
- *output = (uint8_t)blurredPixel;
- output ++;
- }
- }
-}
-
-void FontRenderer::verticalBlur(float* weights, int32_t radius,
- const uint8_t* source, uint8_t* dest, int32_t width, int32_t height) {
- float blurredPixel = 0.0f;
- float currentPixel = 0.0f;
-
- for (int32_t y = 0; y < height; y ++) {
- uint8_t* output = dest + y * width;
-
- for (int32_t x = 0; x < width; x ++) {
- blurredPixel = 0.0f;
- const float* gPtr = weights;
- const uint8_t* input = source + x;
- // Optimization for non-border pixels
- if (y > radius && y < (height - radius)) {
- const uint8_t *i = input + ((y - radius) * width);
- for (int32_t r = -radius; r <= radius; r ++) {
- currentPixel = (float)(*i);
- blurredPixel += currentPixel * gPtr[0];
- gPtr++;
- i += width;
- }
- } else {
- for (int32_t r = -radius; r <= radius; r ++) {
- int validH = y + r;
- // Clamp to zero and width
- if (validH < 0) {
- validH = 0;
- }
- if (validH > height - 1) {
- validH = height - 1;
- }
-
- const uint8_t *i = input + validH * width;
- currentPixel = (float) (*i);
- blurredPixel += currentPixel * gPtr[0];
- gPtr++;
- }
- }
- *output = (uint8_t) blurredPixel;
- output++;
- }
- }
-}
-
void FontRenderer::blurImage(uint8_t** image, int32_t width, int32_t height, int32_t radius) {
if (width * height * radius < RS_MIN_INPUT_CUTOFF) {
float *gaussian = new float[2 * radius + 1];
- computeGaussianWeights(gaussian, radius);
+ Blur::generateGaussianWeights(gaussian, radius);
uint8_t* scratch = new uint8_t[width * height];
-
- horizontalBlur(gaussian, radius, *image, scratch, width, height);
- verticalBlur(gaussian, radius, scratch, *image, width, height);
+ Blur::horizontal(gaussian, radius, *image, scratch, width, height);
+ Blur::vertical(gaussian, radius, scratch, *image, width, height);
delete[] gaussian;
delete[] scratch;
return;
}
- uint8_t* outImage = (uint8_t*)memalign(RS_CPU_ALLOCATION_ALIGNMENT, width * height);
+ uint8_t* outImage = (uint8_t*) memalign(RS_CPU_ALLOCATION_ALIGNMENT, width * height);
if (mRs.get() == 0) {
mRs = new RSC::RS();
diff --git a/libs/hwui/GradientCache.cpp b/libs/hwui/GradientCache.cpp
index 78f9cf5..d681609 100644
--- a/libs/hwui/GradientCache.cpp
+++ b/libs/hwui/GradientCache.cpp
@@ -17,7 +17,6 @@
#define LOG_TAG "OpenGLRenderer"
#include <utils/JenkinsHash.h>
-#include <utils/threads.h>
#include "Caches.h"
#include "Debug.h"
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 22ec93b..7fe0a69 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -276,6 +276,12 @@
renderOverdraw();
endTiling();
+ // When finish() is invoked on FBO 0 we've reached the end
+ // of the current frame
+ if (getTargetFbo() == 0) {
+ mCaches.pathCache.trim();
+ }
+
if (!suppressErrorChecks()) {
#if DEBUG_OPENGL
GLenum status = GL_NO_ERROR;
@@ -2633,16 +2639,7 @@
fontTransform = mat4::identity();
} else {
if (CC_UNLIKELY(transform.isPerspective())) {
- // When the below condition is true, we are rendering text with a
- // perspective transform inside a layer (either an inline layer
- // created by Canvas.saveLayer() or a hardware layer.)
- if (hasLayer() || getTargetFbo() != 0) {
- float sx, sy;
- currentTransform().decomposeScale(sx, sy);
- fontTransform.loadScale(sx, sy, 1.0f);
- } else {
- fontTransform = mat4::identity();
- }
+ fontTransform = mat4::identity();
} else {
float sx, sy;
currentTransform().decomposeScale(sx, sy);
diff --git a/libs/hwui/PathCache.cpp b/libs/hwui/PathCache.cpp
index 4f682ed..afdc2c9 100644
--- a/libs/hwui/PathCache.cpp
+++ b/libs/hwui/PathCache.cpp
@@ -16,34 +16,47 @@
#define LOG_TAG "OpenGLRenderer"
-#include <utils/threads.h>
+#include <utils/Mutex.h>
+#include <sys/sysinfo.h>
+
+#include "Caches.h"
#include "PathCache.h"
#include "Properties.h"
namespace android {
namespace uirenderer {
-// Defined in ShapeCache.h
+///////////////////////////////////////////////////////////////////////////////
+// Path precaching
+///////////////////////////////////////////////////////////////////////////////
-void computePathBounds(const SkPath* path, const SkPaint* paint,
- float& left, float& top, float& offset, uint32_t& width, uint32_t& height) {
- const SkRect& bounds = path->getBounds();
- computeBounds(bounds, paint, left, top, offset, width, height);
+PathCache::PathProcessor::PathProcessor(Caches& caches):
+ TaskProcessor<SkBitmap*>(&caches.tasks), mMaxTextureSize(caches.maxTextureSize) {
}
-void computeBounds(const SkRect& bounds, const SkPaint* paint,
- float& left, float& top, float& offset, uint32_t& width, uint32_t& height) {
- const float pathWidth = fmax(bounds.width(), 1.0f);
- const float pathHeight = fmax(bounds.height(), 1.0f);
+void PathCache::PathProcessor::onProcess(const sp<Task<SkBitmap*> >& task) {
+ sp<PathTask> t = static_cast<PathTask* >(task.get());
+ ATRACE_NAME("pathPrecache");
- left = bounds.fLeft;
- top = bounds.fTop;
+ float left, top, offset;
+ uint32_t width, height;
+ PathCache::computePathBounds(t->path, t->paint, left, top, offset, width, height);
- offset = (int) floorf(fmax(paint->getStrokeWidth(), 1.0f) * 1.5f + 0.5f);
+ PathTexture* texture = t->texture;
+ texture->left = left;
+ texture->top = top;
+ texture->offset = offset;
+ texture->width = width;
+ texture->height = height;
- width = uint32_t(pathWidth + offset * 2.0 + 0.5);
- height = uint32_t(pathHeight + offset * 2.0 + 0.5);
+ if (width <= mMaxTextureSize && height <= mMaxTextureSize) {
+ SkBitmap* bitmap = new SkBitmap();
+ PathCache::drawPath(t->path, t->paint, *bitmap, left, top, offset, width, height);
+ t->setResult(bitmap);
+ } else {
+ t->setResult(NULL);
+ }
}
///////////////////////////////////////////////////////////////////////////////
@@ -54,13 +67,16 @@
PROPERTY_PATH_CACHE_SIZE, DEFAULT_PATH_CACHE_SIZE) {
}
+PathCache::~PathCache() {
+}
+
void PathCache::remove(SkPath* path) {
Vector<PathCacheEntry> pathsToRemove;
LruCache<PathCacheEntry, PathTexture*>::Iterator i(mCache);
while (i.next()) {
const PathCacheEntry& key = i.key();
- if (key.path == path) {
+ if (key.path == path || key.path == path->getSourcePath()) {
pathsToRemove.push(key);
}
}
@@ -71,12 +87,12 @@
}
void PathCache::removeDeferred(SkPath* path) {
- Mutex::Autolock _l(mLock);
+ Mutex::Autolock l(mLock);
mGarbage.push(path);
}
void PathCache::clearGarbage() {
- Mutex::Autolock _l(mLock);
+ Mutex::Autolock l(mLock);
size_t count = mGarbage.size();
for (size_t i = 0; i < count; i++) {
remove(mGarbage.itemAt(i));
@@ -84,24 +100,97 @@
mGarbage.clear();
}
-PathTexture* PathCache::get(SkPath* path, SkPaint* paint) {
+/**
+ * To properly handle path mutations at draw time we always make a copy
+ * of paths objects when recording display lists. The source path points
+ * to the path we originally copied the path from. This ensures we use
+ * the original path as a cache key the first time a path is inserted
+ * in the cache. The source path is also used to reclaim garbage when a
+ * Dalvik Path object is collected.
+ */
+static SkPath* getSourcePath(SkPath* path) {
const SkPath* sourcePath = path->getSourcePath();
if (sourcePath && sourcePath->getGenerationID() == path->getGenerationID()) {
- path = const_cast<SkPath*>(sourcePath);
+ return const_cast<SkPath*>(sourcePath);
}
+ return path;
+}
+
+PathTexture* PathCache::get(SkPath* path, SkPaint* paint) {
+ path = getSourcePath(path);
PathCacheEntry entry(path, paint);
PathTexture* texture = mCache.get(entry);
if (!texture) {
texture = addTexture(entry, path, paint);
- } else if (path->getGenerationID() != texture->generation) {
- mCache.remove(entry);
- texture = addTexture(entry, path, paint);
+ } else {
+ // A bitmap is attached to the texture, this means we need to
+ // upload it as a GL texture
+ const sp<Task<SkBitmap*> >& task = texture->task();
+ if (task != NULL) {
+ // But we must first wait for the worker thread to be done
+ // producing the bitmap, so let's wait
+ SkBitmap* bitmap = task->getResult();
+ if (bitmap) {
+ addTexture(entry, bitmap, texture);
+ texture->clearTask();
+ } else {
+ ALOGW("Path too large to be rendered into a texture (%dx%d)",
+ texture->width, texture->height);
+ texture->clearTask();
+ texture = NULL;
+ mCache.remove(entry);
+ }
+ } else if (path->getGenerationID() != texture->generation) {
+ mCache.remove(entry);
+ texture = addTexture(entry, path, paint);
+ }
}
return texture;
}
+void PathCache::precache(SkPath* path, SkPaint* paint) {
+ if (!Caches::getInstance().tasks.canRunTasks()) {
+ return;
+ }
+
+ path = getSourcePath(path);
+
+ PathCacheEntry entry(path, paint);
+ PathTexture* texture = mCache.get(entry);
+
+ bool generate = false;
+ if (!texture) {
+ generate = true;
+ } else if (path->getGenerationID() != texture->generation) {
+ mCache.remove(entry);
+ generate = true;
+ }
+
+ if (generate) {
+ // It is important to specify the generation ID so we do not
+ // attempt to precache the same path several times
+ texture = createTexture(0.0f, 0.0f, 0.0f, 0, 0, path->getGenerationID());
+ sp<PathTask> task = new PathTask(path, paint, texture);
+ texture->setTask(task);
+
+ // During the precaching phase we insert path texture objects into
+ // the cache that do not point to any GL texture. They are instead
+ // treated as a task for the precaching worker thread. This is why
+ // we do not check the cache limit when inserting these objects.
+ // The conversion into GL texture will happen in get(), when a client
+ // asks for a path texture. This is also when the cache limit will
+ // be enforced.
+ mCache.put(entry, texture);
+
+ if (mProcessor == NULL) {
+ mProcessor = new PathProcessor(Caches::getInstance());
+ }
+ mProcessor->add(task);
+ }
+}
+
}; // namespace uirenderer
}; // namespace android
diff --git a/libs/hwui/PathCache.h b/libs/hwui/PathCache.h
index 8a0235b..27031a5 100644
--- a/libs/hwui/PathCache.h
+++ b/libs/hwui/PathCache.h
@@ -17,14 +17,23 @@
#ifndef ANDROID_HWUI_PATH_CACHE_H
#define ANDROID_HWUI_PATH_CACHE_H
+#include <utils/Thread.h>
#include <utils/Vector.h>
#include "Debug.h"
#include "ShapeCache.h"
+#include "thread/Signal.h"
+#include "thread/Task.h"
+#include "thread/TaskProcessor.h"
+
+class SkPaint;
+class SkPath;
namespace android {
namespace uirenderer {
+class Caches;
+
///////////////////////////////////////////////////////////////////////////////
// Classes
///////////////////////////////////////////////////////////////////////////////
@@ -69,6 +78,7 @@
class PathCache: public ShapeCache<PathCacheEntry> {
public:
PathCache();
+ ~PathCache();
/**
* Returns the texture associated with the specified path. If the texture
@@ -89,7 +99,36 @@
*/
void clearGarbage();
+ void precache(SkPath* path, SkPaint* paint);
+
private:
+ class PathTask: public Task<SkBitmap*> {
+ public:
+ PathTask(SkPath* path, SkPaint* paint, PathTexture* texture):
+ path(path), paint(paint), texture(texture) {
+ }
+
+ ~PathTask() {
+ delete future()->get();
+ }
+
+ SkPath* path;
+ SkPaint* paint;
+ PathTexture* texture;
+ };
+
+ class PathProcessor: public TaskProcessor<SkBitmap*> {
+ public:
+ PathProcessor(Caches& caches);
+ ~PathProcessor() { }
+
+ virtual void onProcess(const sp<Task<SkBitmap*> >& task);
+
+ private:
+ uint32_t mMaxTextureSize;
+ };
+
+ sp<PathProcessor> mProcessor;
Vector<SkPath*> mGarbage;
mutable Mutex mLock;
}; // class PathCache
diff --git a/libs/hwui/ShapeCache.h b/libs/hwui/ShapeCache.h
index 47cab83e..58fea08 100644
--- a/libs/hwui/ShapeCache.h
+++ b/libs/hwui/ShapeCache.h
@@ -17,6 +17,8 @@
#ifndef ANDROID_HWUI_SHAPE_CACHE_H
#define ANDROID_HWUI_SHAPE_CACHE_H
+#define ATRACE_TAG ATRACE_TAG_VIEW
+
#include <GLES2/gl2.h>
#include <SkBitmap.h>
@@ -27,10 +29,12 @@
#include <utils/JenkinsHash.h>
#include <utils/LruCache.h>
+#include <utils/Trace.h>
#include "Debug.h"
#include "Properties.h"
#include "Texture.h"
+#include "thread/Task.h"
namespace android {
namespace uirenderer {
@@ -57,6 +61,10 @@
PathTexture(): Texture() {
}
+ ~PathTexture() {
+ clearTask();
+ }
+
/**
* Left coordinate of the path bounds.
*/
@@ -69,6 +77,23 @@
* Offset to draw the path at the correct origin.
*/
float offset;
+
+ sp<Task<SkBitmap*> > task() const {
+ return mTask;
+ }
+
+ void setTask(const sp<Task<SkBitmap*> >& task) {
+ mTask = task;
+ }
+
+ void clearTask() {
+ if (mTask != NULL) {
+ mTask.clear();
+ }
+ }
+
+private:
+ sp<Task<SkBitmap*> > mTask;
}; // struct PathTexture
/**
@@ -449,6 +474,52 @@
*/
uint32_t getSize();
+ /**
+ * Trims the contents of the cache, removing items until it's under its
+ * specified limit.
+ *
+ * Trimming is used for caches that support pre-caching from a worker
+ * thread. During pre-caching the maximum limit of the cache can be
+ * exceeded for the duration of the frame. It is therefore required to
+ * trim the cache at the end of the frame to keep the total amount of
+ * memory used under control.
+ *
+ * Only the PathCache currently supports pre-caching.
+ */
+ void trim();
+
+ static void computePathBounds(const SkPath* path, const SkPaint* paint,
+ float& left, float& top, float& offset, uint32_t& width, uint32_t& height) {
+ const SkRect& bounds = path->getBounds();
+ computeBounds(bounds, paint, left, top, offset, width, height);
+ }
+
+ static void computeBounds(const SkRect& bounds, const SkPaint* paint,
+ float& left, float& top, float& offset, uint32_t& width, uint32_t& height) {
+ const float pathWidth = fmax(bounds.width(), 1.0f);
+ const float pathHeight = fmax(bounds.height(), 1.0f);
+
+ left = bounds.fLeft;
+ top = bounds.fTop;
+
+ offset = (int) floorf(fmax(paint->getStrokeWidth(), 1.0f) * 1.5f + 0.5f);
+
+ width = uint32_t(pathWidth + offset * 2.0 + 0.5);
+ height = uint32_t(pathHeight + offset * 2.0 + 0.5);
+ }
+
+ static void drawPath(const SkPath *path, const SkPaint* paint, SkBitmap& bitmap,
+ float left, float top, float offset, uint32_t width, uint32_t height) {
+ initBitmap(bitmap, width, height);
+
+ SkPaint pathPaint(*paint);
+ initPaint(pathPaint);
+
+ SkCanvas canvas(bitmap);
+ canvas.translate(-left + offset, -top + offset);
+ canvas.drawPath(*path, pathPaint);
+ }
+
protected:
PathTexture* addTexture(const Entry& entry, const SkPath *path, const SkPaint* paint);
PathTexture* addTexture(const Entry& entry, SkBitmap* bitmap);
@@ -460,17 +531,51 @@
*/
void purgeCache(uint32_t width, uint32_t height);
- void initBitmap(SkBitmap& bitmap, uint32_t width, uint32_t height);
- void initPaint(SkPaint& paint);
-
- bool checkTextureSize(uint32_t width, uint32_t height);
-
PathTexture* get(Entry entry) {
return mCache.get(entry);
}
void removeTexture(PathTexture* texture);
+ bool checkTextureSize(uint32_t width, uint32_t height) {
+ if (width > mMaxTextureSize || height > mMaxTextureSize) {
+ ALOGW("Shape %s too large to be rendered into a texture (%dx%d, max=%dx%d)",
+ mName, width, height, mMaxTextureSize, mMaxTextureSize);
+ return false;
+ }
+ return true;
+ }
+
+ static PathTexture* createTexture(float left, float top, float offset,
+ uint32_t width, uint32_t height, uint32_t id) {
+ PathTexture* texture = new PathTexture();
+ texture->left = left;
+ texture->top = top;
+ texture->offset = offset;
+ texture->width = width;
+ texture->height = height;
+ texture->generation = id;
+ return texture;
+ }
+
+ static void initBitmap(SkBitmap& bitmap, uint32_t width, uint32_t height) {
+ bitmap.setConfig(SkBitmap::kA8_Config, width, height);
+ bitmap.allocPixels();
+ bitmap.eraseColor(0);
+ }
+
+ static void initPaint(SkPaint& paint) {
+ // Make sure the paint is opaque, color, alpha, filter, etc.
+ // will be applied later when compositing the alpha8 texture
+ paint.setColor(0xff000000);
+ paint.setAlpha(255);
+ paint.setColorFilter(NULL);
+ paint.setMaskFilter(NULL);
+ paint.setShader(NULL);
+ SkXfermode* mode = SkXfermode::Create(SkXfermode::kSrc_Mode);
+ SkSafeUnref(paint.setXfermode(mode));
+ }
+
LruCache<Entry, PathTexture*> mCache;
uint32_t mSize;
uint32_t mMaxSize;
@@ -617,23 +722,6 @@
}
}
-void computePathBounds(const SkPath* path, const SkPaint* paint,
- float& left, float& top, float& offset, uint32_t& width, uint32_t& height);
-void computeBounds(const SkRect& bounds, const SkPaint* paint,
- float& left, float& top, float& offset, uint32_t& width, uint32_t& height);
-
-static PathTexture* createTexture(float left, float top, float offset,
- uint32_t width, uint32_t height, uint32_t id) {
- PathTexture* texture = new PathTexture;
- texture->left = left;
- texture->top = top;
- texture->offset = offset;
- texture->width = width;
- texture->height = height;
- texture->generation = id;
- return texture;
-}
-
template<class Entry>
void ShapeCache<Entry>::purgeCache(uint32_t width, uint32_t height) {
const uint32_t size = width * height;
@@ -646,38 +734,16 @@
}
template<class Entry>
-void ShapeCache<Entry>::initBitmap(SkBitmap& bitmap, uint32_t width, uint32_t height) {
- bitmap.setConfig(SkBitmap::kA8_Config, width, height);
- bitmap.allocPixels();
- bitmap.eraseColor(0);
-}
-
-template<class Entry>
-void ShapeCache<Entry>::initPaint(SkPaint& paint) {
- // Make sure the paint is opaque, color, alpha, filter, etc.
- // will be applied later when compositing the alpha8 texture
- paint.setColor(0xff000000);
- paint.setAlpha(255);
- paint.setColorFilter(NULL);
- paint.setMaskFilter(NULL);
- paint.setShader(NULL);
- SkXfermode* mode = SkXfermode::Create(SkXfermode::kSrc_Mode);
- SkSafeUnref(paint.setXfermode(mode));
-}
-
-template<class Entry>
-bool ShapeCache<Entry>::checkTextureSize(uint32_t width, uint32_t height) {
- if (width > mMaxTextureSize || height > mMaxTextureSize) {
- ALOGW("Shape %s too large to be rendered into a texture (%dx%d, max=%dx%d)",
- mName, width, height, mMaxTextureSize, mMaxTextureSize);
- return false;
+void ShapeCache<Entry>::trim() {
+ while (mSize > mMaxSize) {
+ mCache.removeOldest();
}
- return true;
}
template<class Entry>
PathTexture* ShapeCache<Entry>::addTexture(const Entry& entry, const SkPath *path,
const SkPaint* paint) {
+ ATRACE_CALL();
float left, top, offset;
uint32_t width, height;
@@ -688,16 +754,10 @@
purgeCache(width, height);
SkBitmap bitmap;
- initBitmap(bitmap, width, height);
+ drawPath(path, paint, bitmap, left, top, offset, width, height);
- SkPaint pathPaint(*paint);
- initPaint(pathPaint);
-
- SkCanvas canvas(bitmap);
- canvas.translate(-left + offset, -top + offset);
- canvas.drawPath(*path, pathPaint);
-
- PathTexture* texture = createTexture(left, top, offset, width, height, path->getGenerationID());
+ PathTexture* texture = createTexture(left, top, offset, width, height,
+ path->getGenerationID());
addTexture(entry, &bitmap, texture);
return texture;
diff --git a/libs/hwui/TextureCache.cpp b/libs/hwui/TextureCache.cpp
index 5cff5a5..2378eb5 100644
--- a/libs/hwui/TextureCache.cpp
+++ b/libs/hwui/TextureCache.cpp
@@ -20,7 +20,7 @@
#include <SkCanvas.h>
-#include <utils/threads.h>
+#include <utils/Mutex.h>
#include "Caches.h"
#include "TextureCache.h"
diff --git a/libs/hwui/thread/Barrier.h b/libs/hwui/thread/Barrier.h
new file mode 100644
index 0000000..6cb23e5
--- /dev/null
+++ b/libs/hwui/thread/Barrier.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HWUI_BARRIER_H
+#define ANDROID_HWUI_BARRIER_H
+
+#include <utils/Condition.h>
+
+namespace android {
+namespace uirenderer {
+
+class Barrier {
+public:
+ Barrier(Condition::WakeUpType type = Condition::WAKE_UP_ALL) : mType(type), mOpened(false) { }
+ ~Barrier() { }
+
+ void open() {
+ Mutex::Autolock l(mLock);
+ mOpened = true;
+ mCondition.signal(mType);
+ }
+
+ void close() {
+ Mutex::Autolock l(mLock);
+ mOpened = false;
+ }
+
+ void wait() const {
+ Mutex::Autolock l(mLock);
+ while (!mOpened) {
+ mCondition.wait(mLock);
+ }
+ }
+
+private:
+ Condition::WakeUpType mType;
+ volatile bool mOpened;
+ mutable Mutex mLock;
+ mutable Condition mCondition;
+};
+
+}; // namespace uirenderer
+}; // namespace android
+
+#endif // ANDROID_HWUI_BARRIER_H
diff --git a/libs/hwui/thread/Future.h b/libs/hwui/thread/Future.h
new file mode 100644
index 0000000..a3ff3bc
--- /dev/null
+++ b/libs/hwui/thread/Future.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HWUI_FUTURE_H
+#define ANDROID_HWUI_FUTURE_H
+
+#include <utils/RefBase.h>
+
+#include "Barrier.h"
+
+namespace android {
+namespace uirenderer {
+
+template<typename T>
+class Future: public LightRefBase<Future<T> > {
+public:
+ Future(Condition::WakeUpType type = Condition::WAKE_UP_ONE): mBarrier(type), mResult() { }
+ ~Future() { }
+
+ /**
+ * Returns the result of this future, blocking if
+ * the result is not available yet.
+ */
+ T get() const {
+ mBarrier.wait();
+ return mResult;
+ }
+
+ /**
+ * This method must be called only once.
+ */
+ void produce(T result) {
+ mResult = result;
+ mBarrier.open();
+ }
+
+private:
+ Barrier mBarrier;
+ T mResult;
+};
+
+}; // namespace uirenderer
+}; // namespace android
+
+#endif // ANDROID_HWUI_FUTURE_H
diff --git a/libs/hwui/thread/Signal.h b/libs/hwui/thread/Signal.h
new file mode 100644
index 0000000..dcf5449
--- /dev/null
+++ b/libs/hwui/thread/Signal.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HWUI_SIGNAL_H
+#define ANDROID_HWUI_SIGNAL_H
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <utils/threads.h>
+
+namespace android {
+namespace uirenderer {
+
+class Signal {
+public:
+ Signal(Condition::WakeUpType type = Condition::WAKE_UP_ALL) : mType(type), mSignaled(false) { }
+ ~Signal() { }
+
+ void signal() {
+ Mutex::Autolock l(mLock);
+ mSignaled = true;
+ mCondition.signal(mType);
+ }
+
+ void wait() {
+ Mutex::Autolock l(mLock);
+ while (!mSignaled) {
+ mCondition.wait(mLock);
+ }
+ mSignaled = false;
+ }
+
+private:
+ Condition::WakeUpType mType;
+ volatile bool mSignaled;
+ mutable Mutex mLock;
+ mutable Condition mCondition;
+};
+
+}; // namespace uirenderer
+}; // namespace android
+
+#endif // ANDROID_HWUI_SIGNAL_H
diff --git a/libs/hwui/thread/Task.h b/libs/hwui/thread/Task.h
new file mode 100644
index 0000000..9a211a2
--- /dev/null
+++ b/libs/hwui/thread/Task.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HWUI_TASK_H
+#define ANDROID_HWUI_TASK_H
+
+#define ATRACE_TAG ATRACE_TAG_VIEW
+
+#include <utils/RefBase.h>
+#include <utils/Trace.h>
+
+#include "Future.h"
+
+namespace android {
+namespace uirenderer {
+
+class TaskBase: public RefBase {
+public:
+ TaskBase() { }
+ virtual ~TaskBase() { }
+};
+
+template<typename T>
+class Task: public TaskBase {
+public:
+ Task(): mFuture(new Future<T>()) { }
+ virtual ~Task() { }
+
+ T getResult() const {
+ ATRACE_NAME("waitForTask");
+ return mFuture->get();
+ }
+
+ void setResult(T result) {
+ mFuture->produce(result);
+ }
+
+protected:
+ const sp<Future<T> >& future() const {
+ return mFuture;
+ }
+
+private:
+ sp<Future<T> > mFuture;
+};
+
+}; // namespace uirenderer
+}; // namespace android
+
+#endif // ANDROID_HWUI_TASK_H
diff --git a/libs/hwui/thread/TaskManager.cpp b/libs/hwui/thread/TaskManager.cpp
new file mode 100644
index 0000000..ce6c8c0
--- /dev/null
+++ b/libs/hwui/thread/TaskManager.cpp
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <sys/sysinfo.h>
+
+#include "Task.h"
+#include "TaskProcessor.h"
+#include "TaskManager.h"
+
+namespace android {
+namespace uirenderer {
+
+///////////////////////////////////////////////////////////////////////////////
+// Manager
+///////////////////////////////////////////////////////////////////////////////
+
+TaskManager::TaskManager() {
+ // Get the number of available CPUs. This value does not change over time.
+ int cpuCount = sysconf(_SC_NPROCESSORS_ONLN);
+
+ for (int i = 0; i < cpuCount / 2; i++) {
+ String8 name;
+ name.appendFormat("hwuiTask%d", i + 1);
+ mThreads.add(new WorkerThread(name));
+ }
+}
+
+TaskManager::~TaskManager() {
+ for (size_t i = 0; i < mThreads.size(); i++) {
+ mThreads[i]->exit();
+ }
+}
+
+bool TaskManager::canRunTasks() const {
+ return mThreads.size() > 0;
+}
+
+bool TaskManager::addTaskBase(const sp<TaskBase>& task, const sp<TaskProcessorBase>& processor) {
+ if (mThreads.size() > 0) {
+ TaskWrapper wrapper(task, processor);
+
+ size_t minQueueSize = INT_MAX;
+ sp<WorkerThread> thread;
+
+ for (size_t i = 0; i < mThreads.size(); i++) {
+ if (mThreads[i]->getTaskCount() < minQueueSize) {
+ thread = mThreads[i];
+ minQueueSize = mThreads[i]->getTaskCount();
+ }
+ }
+
+ return thread->addTask(wrapper);
+ }
+ return false;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Thread
+///////////////////////////////////////////////////////////////////////////////
+
+bool TaskManager::WorkerThread::threadLoop() {
+ mSignal.wait();
+ Vector<TaskWrapper> tasks;
+ {
+ Mutex::Autolock l(mLock);
+ tasks = mTasks;
+ mTasks.clear();
+ }
+
+ for (size_t i = 0; i < tasks.size(); i++) {
+ const TaskWrapper& task = tasks.itemAt(i);
+ task.mProcessor->process(task.mTask);
+ }
+
+ return true;
+}
+
+bool TaskManager::WorkerThread::addTask(TaskWrapper task) {
+ if (!isRunning()) {
+ run(mName.string(), PRIORITY_DEFAULT);
+ }
+
+ Mutex::Autolock l(mLock);
+ ssize_t index = mTasks.add(task);
+ mSignal.signal();
+
+ return index >= 0;
+}
+
+size_t TaskManager::WorkerThread::getTaskCount() const {
+ Mutex::Autolock l(mLock);
+ return mTasks.size();
+}
+
+void TaskManager::WorkerThread::exit() {
+ {
+ Mutex::Autolock l(mLock);
+ mTasks.clear();
+ }
+ requestExit();
+ mSignal.signal();
+}
+
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/thread/TaskManager.h b/libs/hwui/thread/TaskManager.h
new file mode 100644
index 0000000..bc86062
--- /dev/null
+++ b/libs/hwui/thread/TaskManager.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HWUI_TASK_MANAGER_H
+#define ANDROID_HWUI_TASK_MANAGER_H
+
+#include <utils/Mutex.h>
+#include <utils/String8.h>
+#include <utils/Thread.h>
+#include <utils/Vector.h>
+
+#include "Signal.h"
+
+namespace android {
+namespace uirenderer {
+
+template <typename T>
+class Task;
+class TaskBase;
+
+template <typename T>
+class TaskProcessor;
+class TaskProcessorBase;
+
+class TaskManager {
+public:
+ TaskManager();
+ ~TaskManager();
+
+ /**
+ * Returns true if this task manager can run tasks,
+ * false otherwise. This method will typically return
+ * true on a single CPU core device.
+ */
+ bool canRunTasks() const;
+
+private:
+ template <typename T>
+ friend class TaskProcessor;
+
+ template<typename T>
+ bool addTask(const sp<Task<T> >& task, const sp<TaskProcessor<T> >& processor) {
+ return addTaskBase(sp<TaskBase>(task), sp<TaskProcessorBase>(processor));
+ }
+
+ bool addTaskBase(const sp<TaskBase>& task, const sp<TaskProcessorBase>& processor);
+
+ struct TaskWrapper {
+ TaskWrapper(): mTask(), mProcessor() { }
+
+ TaskWrapper(const sp<TaskBase>& task, const sp<TaskProcessorBase>& processor):
+ mTask(task), mProcessor(processor) {
+ }
+
+ sp<TaskBase> mTask;
+ sp<TaskProcessorBase> mProcessor;
+ };
+
+ class WorkerThread: public Thread {
+ public:
+ WorkerThread(const String8 name): mSignal(Condition::WAKE_UP_ONE), mName(name) { }
+
+ bool addTask(TaskWrapper task);
+ size_t getTaskCount() const;
+ void exit();
+
+ private:
+ virtual bool threadLoop();
+
+ // Lock for the list of tasks
+ mutable Mutex mLock;
+ Vector<TaskWrapper> mTasks;
+
+ // Signal used to wake up the thread when a new
+ // task is available in the list
+ mutable Signal mSignal;
+
+ const String8 mName;
+ };
+
+ Vector<sp<WorkerThread> > mThreads;
+};
+
+}; // namespace uirenderer
+}; // namespace android
+
+#endif // ANDROID_HWUI_TASK_MANAGER_H
diff --git a/libs/hwui/thread/TaskProcessor.h b/libs/hwui/thread/TaskProcessor.h
new file mode 100644
index 0000000..d1269f0
--- /dev/null
+++ b/libs/hwui/thread/TaskProcessor.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HWUI_TASK_PROCESSOR_H
+#define ANDROID_HWUI_TASK_PROCESSOR_H
+
+#include <utils/RefBase.h>
+
+#include "Task.h"
+#include "TaskManager.h"
+
+namespace android {
+namespace uirenderer {
+
+class TaskProcessorBase: public RefBase {
+public:
+ TaskProcessorBase() { }
+ virtual ~TaskProcessorBase() { };
+
+private:
+ friend class TaskManager;
+
+ virtual void process(const sp<TaskBase>& task) = 0;
+};
+
+template<typename T>
+class TaskProcessor: public TaskProcessorBase {
+public:
+ TaskProcessor(TaskManager* manager): mManager(manager) { }
+ virtual ~TaskProcessor() { }
+
+ bool add(const sp<Task<T> >& task);
+
+ virtual void onProcess(const sp<Task<T> >& task) = 0;
+
+private:
+ virtual void process(const sp<TaskBase>& task) {
+ sp<Task<T> > realTask = static_cast<Task<T>* >(task.get());
+ // This is the right way to do it but sp<> doesn't play nice
+ // sp<Task<T> > realTask = static_cast<sp<Task<T> > >(task);
+ onProcess(realTask);
+ }
+
+ TaskManager* mManager;
+};
+
+template<typename T>
+bool TaskProcessor<T>::add(const sp<Task<T> >& task) {
+ if (mManager) {
+ sp<TaskProcessor<T> > self(this);
+ return mManager->addTask(task, self);
+ }
+ return false;
+}
+
+}; // namespace uirenderer
+}; // namespace android
+
+#endif // ANDROID_HWUI_TASK_PROCESSOR_H
diff --git a/libs/hwui/utils/Blur.cpp b/libs/hwui/utils/Blur.cpp
new file mode 100644
index 0000000..85d90d0
--- /dev/null
+++ b/libs/hwui/utils/Blur.cpp
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "OpenGLRenderer"
+
+#include <math.h>
+
+#include "Blur.h"
+
+namespace android {
+namespace uirenderer {
+
+void Blur::generateGaussianWeights(float* weights, int32_t radius) {
+ // Compute gaussian weights for the blur
+ // e is the euler's number
+ static float e = 2.718281828459045f;
+ static float pi = 3.1415926535897932f;
+ // g(x) = ( 1 / sqrt( 2 * pi ) * sigma) * e ^ ( -x^2 / 2 * sigma^2 )
+ // x is of the form [-radius .. 0 .. radius]
+ // and sigma varies with radius.
+ // Based on some experimental radius values and sigma's
+ // we approximately fit sigma = f(radius) as
+ // sigma = radius * 0.3 + 0.6
+ // The larger the radius gets, the more our gaussian blur
+ // will resemble a box blur since with large sigma
+ // the gaussian curve begins to lose its shape
+ float sigma = 0.3f * (float) radius + 0.6f;
+
+ // Now compute the coefficints
+ // We will store some redundant values to save some math during
+ // the blur calculations
+ // precompute some values
+ float coeff1 = 1.0f / (sqrt(2.0f * pi) * sigma);
+ float coeff2 = - 1.0f / (2.0f * sigma * sigma);
+
+ float normalizeFactor = 0.0f;
+ for (int32_t r = -radius; r <= radius; r ++) {
+ float floatR = (float) r;
+ weights[r + radius] = coeff1 * pow(e, floatR * floatR * coeff2);
+ normalizeFactor += weights[r + radius];
+ }
+
+ //Now we need to normalize the weights because all our coefficients need to add up to one
+ normalizeFactor = 1.0f / normalizeFactor;
+ for (int32_t r = -radius; r <= radius; r ++) {
+ weights[r + radius] *= normalizeFactor;
+ }
+}
+
+void Blur::horizontal(float* weights, int32_t radius,
+ const uint8_t* source, uint8_t* dest, int32_t width, int32_t height) {
+ float blurredPixel = 0.0f;
+ float currentPixel = 0.0f;
+
+ for (int32_t y = 0; y < height; y ++) {
+
+ const uint8_t* input = source + y * width;
+ uint8_t* output = dest + y * width;
+
+ for (int32_t x = 0; x < width; x ++) {
+ blurredPixel = 0.0f;
+ const float* gPtr = weights;
+ // Optimization for non-border pixels
+ if (x > radius && x < (width - radius)) {
+ const uint8_t *i = input + (x - radius);
+ for (int r = -radius; r <= radius; r ++) {
+ currentPixel = (float) (*i);
+ blurredPixel += currentPixel * gPtr[0];
+ gPtr++;
+ i++;
+ }
+ } else {
+ for (int32_t r = -radius; r <= radius; r ++) {
+ // Stepping left and right away from the pixel
+ int validW = x + r;
+ if (validW < 0) {
+ validW = 0;
+ }
+ if (validW > width - 1) {
+ validW = width - 1;
+ }
+
+ currentPixel = (float) input[validW];
+ blurredPixel += currentPixel * gPtr[0];
+ gPtr++;
+ }
+ }
+ *output = (uint8_t)blurredPixel;
+ output ++;
+ }
+ }
+}
+
+void Blur::vertical(float* weights, int32_t radius,
+ const uint8_t* source, uint8_t* dest, int32_t width, int32_t height) {
+ float blurredPixel = 0.0f;
+ float currentPixel = 0.0f;
+
+ for (int32_t y = 0; y < height; y ++) {
+ uint8_t* output = dest + y * width;
+
+ for (int32_t x = 0; x < width; x ++) {
+ blurredPixel = 0.0f;
+ const float* gPtr = weights;
+ const uint8_t* input = source + x;
+ // Optimization for non-border pixels
+ if (y > radius && y < (height - radius)) {
+ const uint8_t *i = input + ((y - radius) * width);
+ for (int32_t r = -radius; r <= radius; r ++) {
+ currentPixel = (float) (*i);
+ blurredPixel += currentPixel * gPtr[0];
+ gPtr++;
+ i += width;
+ }
+ } else {
+ for (int32_t r = -radius; r <= radius; r ++) {
+ int validH = y + r;
+ // Clamp to zero and width
+ if (validH < 0) {
+ validH = 0;
+ }
+ if (validH > height - 1) {
+ validH = height - 1;
+ }
+
+ const uint8_t *i = input + validH * width;
+ currentPixel = (float) (*i);
+ blurredPixel += currentPixel * gPtr[0];
+ gPtr++;
+ }
+ }
+ *output = (uint8_t) blurredPixel;
+ output++;
+ }
+ }
+}
+
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/utils/Blur.h b/libs/hwui/utils/Blur.h
new file mode 100644
index 0000000..6c176e9
--- /dev/null
+++ b/libs/hwui/utils/Blur.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HWUI_BLUR_H
+#define ANDROID_HWUI_BLUR_H
+
+#include <stdint.h>
+
+namespace android {
+namespace uirenderer {
+
+class Blur {
+public:
+ static void generateGaussianWeights(float* weights, int32_t radius);
+ static void horizontal(float* weights, int32_t radius, const uint8_t* source,
+ uint8_t* dest, int32_t width, int32_t height);
+ static void vertical(float* weights, int32_t radius, const uint8_t* source,
+ uint8_t* dest, int32_t width, int32_t height);
+};
+
+}; // namespace uirenderer
+}; // namespace android
+
+#endif // ANDROID_HWUI_BLUR_H
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 86976b8..135d2c8 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -2171,15 +2171,36 @@
/**
* @hide
* Registers a remote control display that will be sent information by remote control clients.
- * @param rcd
+ * Use this method if your IRemoteControlDisplay is not going to display artwork, otherwise
+ * use {@link #registerRemoteControlDisplay(IRemoteControlDisplay, int, int)} to pass the
+ * artwork size directly, or
+ * {@link #remoteControlDisplayUsesBitmapSize(IRemoteControlDisplay, int, int)} later if artwork
+ * is not yet needed.
+ * @param rcd the IRemoteControlDisplay
*/
public void registerRemoteControlDisplay(IRemoteControlDisplay rcd) {
+ // passing a negative value for art work width and height as they are unknown at this stage
+ registerRemoteControlDisplay(rcd, /*w*/-1, /*h*/ -1);
+ }
+
+ /**
+ * @hide
+ * Registers a remote control display that will be sent information by remote control clients.
+ * @param rcd
+ * @param w the maximum width of the expected bitmap. Negative values indicate it is
+ * useless to send artwork.
+ * @param h the maximum height of the expected bitmap. Negative values indicate it is
+ * useless to send artwork.
+ */
+ public void registerRemoteControlDisplay(IRemoteControlDisplay rcd, int w, int h) {
if (rcd == null) {
return;
}
IAudioService service = getService();
try {
- service.registerRemoteControlDisplay(rcd);
+ // passing a negative value for art work width and height as they are unknown at
+ // this stage
+ service.registerRemoteControlDisplay(rcd, w, h);
} catch (RemoteException e) {
Log.e(TAG, "Dead object in registerRemoteControlDisplay " + e);
}
@@ -2223,63 +2244,6 @@
}
}
- // FIXME remove because we are not using intents anymore between AudioService and RcDisplay
- /**
- * @hide
- * Broadcast intent action indicating that the displays on the remote controls
- * should be updated because a new remote control client is now active. If there is no
- * {@link #EXTRA_REMOTE_CONTROL_CLIENT}, the remote control display should be cleared
- * because there is no valid client to supply it with information.
- *
- * @see #EXTRA_REMOTE_CONTROL_CLIENT
- */
- public static final String REMOTE_CONTROL_CLIENT_CHANGED =
- "android.media.REMOTE_CONTROL_CLIENT_CHANGED";
-
- // FIXME remove because we are not using intents anymore between AudioService and RcDisplay
- /**
- * @hide
- * The IRemoteControlClientDispatcher monotonically increasing generation counter.
- *
- * @see #REMOTE_CONTROL_CLIENT_CHANGED_ACTION
- */
- public static final String EXTRA_REMOTE_CONTROL_CLIENT_GENERATION =
- "android.media.EXTRA_REMOTE_CONTROL_CLIENT_GENERATION";
-
- // FIXME remove because we are not using intents anymore between AudioService and RcDisplay
- /**
- * @hide
- * The name of the RemoteControlClient.
- * This String is passed as the client name when calling methods from the
- * IRemoteControlClientDispatcher interface.
- *
- * @see #REMOTE_CONTROL_CLIENT_CHANGED_ACTION
- */
- public static final String EXTRA_REMOTE_CONTROL_CLIENT_NAME =
- "android.media.EXTRA_REMOTE_CONTROL_CLIENT_NAME";
-
- // FIXME remove because we are not using intents anymore between AudioService and RcDisplay
- /**
- * @hide
- * The media button event receiver associated with the RemoteControlClient.
- * The {@link android.content.ComponentName} value of the event receiver can be retrieved with
- * {@link android.content.ComponentName#unflattenFromString(String)}
- *
- * @see #REMOTE_CONTROL_CLIENT_CHANGED_ACTION
- */
- public static final String EXTRA_REMOTE_CONTROL_EVENT_RECEIVER =
- "android.media.EXTRA_REMOTE_CONTROL_EVENT_RECEIVER";
-
- // FIXME remove because we are not using intents anymore between AudioService and RcDisplay
- /**
- * @hide
- * The flags describing what information has changed in the current remote control client.
- *
- * @see #REMOTE_CONTROL_CLIENT_CHANGED_ACTION
- */
- public static final String EXTRA_REMOTE_CONTROL_CLIENT_INFO_CHANGED =
- "android.media.EXTRA_REMOTE_CONTROL_CLIENT_INFO_CHANGED";
-
/**
* @hide
* Reload audio settings. This method is called by Settings backup
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index ed2a8da..f0a5c28 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -158,6 +158,8 @@
private static final int MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED = 27;
private static final int MSG_PERSIST_SAFE_VOLUME_STATE = 28;
private static final int MSG_PROMOTE_RCC = 29;
+ private static final int MSG_BROADCAST_BT_CONNECTION_STATE = 30;
+
// flags for MSG_PERSIST_VOLUME indicating if current and/or last audible volume should be
// persisted
@@ -1947,7 +1949,14 @@
return;
}
ScoClient client = getScoClient(cb, true);
+ // The calling identity must be cleared before calling ScoClient.incCount().
+ // inCount() calls requestScoState() which in turn can call BluetoothHeadset APIs
+ // and this must be done on behalf of system server to make sure permissions are granted.
+ // The caller identity must be cleared after getScoClient() because it is needed if a new
+ // client is created.
+ final long ident = Binder.clearCallingIdentity();
client.incCount();
+ Binder.restoreCallingIdentity(ident);
}
/** @see AudioManager#stopBluetoothSco() */
@@ -1957,9 +1966,14 @@
return;
}
ScoClient client = getScoClient(cb, false);
+ // The calling identity must be cleared before calling ScoClient.decCount().
+ // decCount() calls requestScoState() which in turn can call BluetoothHeadset APIs
+ // and this must be done on behalf of system server to make sure permissions are granted.
+ final long ident = Binder.clearCallingIdentity();
if (client != null) {
client.decCount();
}
+ Binder.restoreCallingIdentity(ident);
}
@@ -2209,6 +2223,11 @@
}
private void broadcastScoConnectionState(int state) {
+ sendMsg(mAudioHandler, MSG_BROADCAST_BT_CONNECTION_STATE,
+ SENDMSG_QUEUE, state, 0, null, 0);
+ }
+
+ private void onBroadcastScoConnectionState(int state) {
if (state != mScoConnectionState) {
Intent newIntent = new Intent(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED);
newIntent.putExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, state);
@@ -3532,6 +3551,10 @@
case MSG_PROMOTE_RCC:
onPromoteRcc(msg.arg1);
break;
+
+ case MSG_BROADCAST_BT_CONNECTION_STATE:
+ onBroadcastScoConnectionState(msg.arg1);
+ break;
}
}
}
@@ -4890,7 +4913,6 @@
" -- vol: " + rcse.mPlaybackVolume +
" -- volMax: " + rcse.mPlaybackVolumeMax +
" -- volObs: " + rcse.mRemoteVolumeObs);
-
}
}
synchronized (mMainRemote) {
@@ -4908,6 +4930,23 @@
/**
* Helper function:
+ * Display in the log the current entries in the list of remote control displays
+ */
+ private void dumpRCDList(PrintWriter pw) {
+ pw.println("\nRemote Control Display list entries:");
+ synchronized(mRCStack) {
+ final Iterator<DisplayInfoForServer> displayIterator = mRcDisplays.iterator();
+ while (displayIterator.hasNext()) {
+ final DisplayInfoForServer di = (DisplayInfoForServer) displayIterator.next();
+ pw.println(" IRCD: " + di.mRcDisplay +
+ " -- w:" + di.mArtworkExpectedWidth +
+ " -- h:" + di.mArtworkExpectedHeight);
+ }
+ }
+ }
+
+ /**
+ * Helper function:
* Remove any entry in the remote control stack that has the same package name as packageName
* Pre-condition: packageName != null
*/
@@ -5044,16 +5083,20 @@
*/
private void setNewRcClientOnDisplays_syncRcsCurrc(int newClientGeneration,
PendingIntent newMediaIntent, boolean clearing) {
- // NOTE: Only one IRemoteControlDisplay supported in this implementation
- if (mRcDisplay != null) {
- try {
- mRcDisplay.setCurrentClientId(
- newClientGeneration, newMediaIntent, clearing);
- } catch (RemoteException e) {
- Log.e(TAG, "Dead display in setNewRcClientOnDisplays_syncRcsCurrc() "+e);
- // if we had a display before, stop monitoring its death
- rcDisplay_stopDeathMonitor_syncRcStack();
- mRcDisplay = null;
+ synchronized(mRCStack) {
+ if (mRcDisplays.size() > 0) {
+ final Iterator<DisplayInfoForServer> displayIterator = mRcDisplays.iterator();
+ while (displayIterator.hasNext()) {
+ final DisplayInfoForServer di = displayIterator.next();
+ try {
+ di.mRcDisplay.setCurrentClientId(
+ newClientGeneration, newMediaIntent, clearing);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Dead display in setNewRcClientOnDisplays_syncRcsCurrc()",e);
+ di.release();
+ displayIterator.remove();
+ }
+ }
}
}
}
@@ -5071,7 +5114,7 @@
try {
se.mRcClient.setCurrentClientGenerationId(newClientGeneration);
} catch (RemoteException e) {
- Log.w(TAG, "Dead client in setNewRcClientGenerationOnClients_syncRcsCurrc()"+e);
+ Log.w(TAG, "Dead client in setNewRcClientGenerationOnClients_syncRcsCurrc()",e);
stackIterator.remove();
se.unlinkToRcClientDeath();
}
@@ -5129,8 +5172,7 @@
// tell the current client that it needs to send info
try {
- mCurrentRcClient.onInformationRequested(mCurrentRcClientGen,
- flags, mArtworkExpectedWidth, mArtworkExpectedHeight);
+ mCurrentRcClient.onInformationRequested(mCurrentRcClientGen, flags);
} catch (RemoteException e) {
Log.e(TAG, "Current valid remote client is dead: "+e);
mCurrentRcClient = null;
@@ -5394,13 +5436,9 @@
rccId = rcse.mRccId;
// there is a new (non-null) client:
- // 1/ give the new client the current display (if any)
- if (mRcDisplay != null) {
- try {
- rcse.mRcClient.plugRemoteControlDisplay(mRcDisplay);
- } catch (RemoteException e) {
- Log.e(TAG, "Error connecting RCD to RCC in RCC registration",e);
- }
+ // 1/ give the new client the displays (if any)
+ if (mRcDisplays.size() > 0) {
+ plugRemoteControlDisplaysIntoClient_syncRcStack(rcse.mRcClient);
}
// 2/ monitor the new client's death
IBinder b = rcse.mRcClient.asBinder();
@@ -5470,102 +5508,141 @@
}
}
- /**
- * The remote control displays.
- * Access synchronized on mRCStack
- * NOTE: Only one IRemoteControlDisplay supported in this implementation
- */
- private IRemoteControlDisplay mRcDisplay;
- private RcDisplayDeathHandler mRcDisplayDeathHandler;
- private int mArtworkExpectedWidth = -1;
- private int mArtworkExpectedHeight = -1;
- /**
- * Inner class to monitor remote control display deaths, and unregister them from the list
- * of displays if necessary.
- */
- private class RcDisplayDeathHandler implements IBinder.DeathRecipient {
- private IBinder mCb; // To be notified of client's death
- public RcDisplayDeathHandler(IBinder b) {
- if (DEBUG_RC) Log.i(TAG, "new RcDisplayDeathHandler for "+b);
- mCb = b;
+ /**
+ * A class to encapsulate all the information about a remote control display.
+ * After instanciation, init() must always be called before the object is added in the list
+ * of displays.
+ * Before being removed from the list of displays, release() must always be called (otherwise
+ * it will leak death handlers).
+ */
+ private class DisplayInfoForServer implements IBinder.DeathRecipient {
+ /** may never be null */
+ private IRemoteControlDisplay mRcDisplay;
+ private IBinder mRcDisplayBinder;
+ private int mArtworkExpectedWidth = -1;
+ private int mArtworkExpectedHeight = -1;
+
+ public DisplayInfoForServer(IRemoteControlDisplay rcd, int w, int h) {
+ if (DEBUG_RC) Log.i(TAG, "new DisplayInfoForServer for " + rcd + " w=" + w + " h=" + h);
+ mRcDisplay = rcd;
+ mRcDisplayBinder = rcd.asBinder();
+ mArtworkExpectedWidth = w;
+ mArtworkExpectedHeight = h;
+ }
+
+ public boolean init() {
+ try {
+ mRcDisplayBinder.linkToDeath(this, 0);
+ } catch (RemoteException e) {
+ // remote control display is DOA, disqualify it
+ Log.w(TAG, "registerRemoteControlDisplay() has a dead client " + mRcDisplayBinder);
+ return false;
+ }
+ return true;
+ }
+
+ public void release() {
+ try {
+ mRcDisplayBinder.unlinkToDeath(this, 0);
+ } catch (java.util.NoSuchElementException e) {
+ // not much we can do here, the display should have been unregistered anyway
+ Log.e(TAG, "Error in DisplaInfoForServer.relase()", e);
+ }
}
public void binderDied() {
synchronized(mRCStack) {
- Log.w(TAG, "RemoteControl: display died");
- mRcDisplay = null;
+ Log.w(TAG, "RemoteControl: display " + mRcDisplay + " died");
+ // remove the display from the list
+ final Iterator<DisplayInfoForServer> displayIterator = mRcDisplays.iterator();
+ while (displayIterator.hasNext()) {
+ final DisplayInfoForServer di = (DisplayInfoForServer) displayIterator.next();
+ if (di.mRcDisplay == mRcDisplay) {
+ if (DEBUG_RC) Log.w(TAG, " RCD removed from list");
+ displayIterator.remove();
+ return;
+ }
+ }
}
}
-
- public void unlinkToRcDisplayDeath() {
- if (DEBUG_RC) Log.i(TAG, "unlinkToRcDisplayDeath for "+mCb);
- try {
- mCb.unlinkToDeath(this, 0);
- } catch (java.util.NoSuchElementException e) {
- // not much we can do here, the display was being unregistered anyway
- Log.e(TAG, "Encountered " + e + " in unlinkToRcDisplayDeath()");
- e.printStackTrace();
- }
- }
-
- }
-
- private void rcDisplay_stopDeathMonitor_syncRcStack() {
- if (mRcDisplay != null) { // implies (mRcDisplayDeathHandler != null)
- // we had a display before, stop monitoring its death
- mRcDisplayDeathHandler.unlinkToRcDisplayDeath();
- }
}
- private void rcDisplay_startDeathMonitor_syncRcStack() {
- if (mRcDisplay != null) {
- // new non-null display, monitor its death
- IBinder b = mRcDisplay.asBinder();
- mRcDisplayDeathHandler = new RcDisplayDeathHandler(b);
+ /**
+ * The remote control displays.
+ * Access synchronized on mRCStack
+ */
+ private ArrayList<DisplayInfoForServer> mRcDisplays = new ArrayList<DisplayInfoForServer>(1);
+
+ /**
+ * Plug each registered display into the specified client
+ * @param rcc, guaranteed non null
+ */
+ private void plugRemoteControlDisplaysIntoClient_syncRcStack(IRemoteControlClient rcc) {
+ final Iterator<DisplayInfoForServer> displayIterator = mRcDisplays.iterator();
+ while (displayIterator.hasNext()) {
+ final DisplayInfoForServer di = (DisplayInfoForServer) displayIterator.next();
try {
- b.linkToDeath(mRcDisplayDeathHandler, 0);
+ rcc.plugRemoteControlDisplay(di.mRcDisplay, di.mArtworkExpectedWidth,
+ di.mArtworkExpectedHeight);
} catch (RemoteException e) {
- // remote control display is DOA, disqualify it
- Log.w(TAG, "registerRemoteControlDisplay() has a dead client " + b);
- mRcDisplay = null;
+ Log.e(TAG, "Error connecting RCD to RCC in RCC registration",e);
}
}
}
/**
+ * Is the remote control display interface already registered
+ * @param rcd
+ * @return true if the IRemoteControlDisplay is already in the list of displays
+ */
+ private boolean rcDisplayIsPluggedIn_syncRcStack(IRemoteControlDisplay rcd) {
+ final Iterator<DisplayInfoForServer> displayIterator = mRcDisplays.iterator();
+ while (displayIterator.hasNext()) {
+ final DisplayInfoForServer di = (DisplayInfoForServer) displayIterator.next();
+ if (di.mRcDisplay.asBinder().equals(rcd.asBinder())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
* Register an IRemoteControlDisplay.
* Notify all IRemoteControlClient of the new display and cause the RemoteControlClient
* at the top of the stack to update the new display with its information.
- * Since only one IRemoteControlDisplay is supported, this will unregister the previous display.
+ * @see android.media.IAudioService#registerRemoteControlDisplay(android.media.IRemoteControlDisplay, int, int)
* @param rcd the IRemoteControlDisplay to register. No effect if null.
+ * @param w the maximum width of the expected bitmap. Negative or zero values indicate this
+ * display doesn't need to receive artwork.
+ * @param h the maximum height of the expected bitmap. Negative or zero values indicate this
+ * display doesn't need to receive artwork.
*/
- public void registerRemoteControlDisplay(IRemoteControlDisplay rcd) {
+ public void registerRemoteControlDisplay(IRemoteControlDisplay rcd, int w, int h) {
if (DEBUG_RC) Log.d(TAG, ">>> registerRemoteControlDisplay("+rcd+")");
synchronized(mAudioFocusLock) {
synchronized(mRCStack) {
- if ((mRcDisplay == rcd) || (rcd == null)) {
+ if ((rcd == null) || rcDisplayIsPluggedIn_syncRcStack(rcd)) {
return;
}
- // if we had a display before, stop monitoring its death
- rcDisplay_stopDeathMonitor_syncRcStack();
- mRcDisplay = rcd;
- // new display, start monitoring its death
- rcDisplay_startDeathMonitor_syncRcStack();
+ DisplayInfoForServer di = new DisplayInfoForServer(rcd, w, h);
+ if (!di.init()) {
+ if (DEBUG_RC) Log.e(TAG, " error registering RCD");
+ return;
+ }
+ // add RCD to list of displays
+ mRcDisplays.add(di);
- // let all the remote control clients know there is a new display, so the remote
- // control stack traversal order doesn't matter.
- // No need to unplug the previous because we only support one display
- // and the clients don't track the death of the display
+ // let all the remote control clients know there is a new display (so the remote
+ // control stack traversal order doesn't matter).
Iterator<RemoteControlStackEntry> stackIterator = mRCStack.iterator();
while(stackIterator.hasNext()) {
RemoteControlStackEntry rcse = stackIterator.next();
if(rcse.mRcClient != null) {
try {
- rcse.mRcClient.plugRemoteControlDisplay(mRcDisplay);
+ rcse.mRcClient.plugRemoteControlDisplay(rcd, w, h);
} catch (RemoteException e) {
- Log.e(TAG, "Error connecting remote control display to client: " + e);
- e.printStackTrace();
+ Log.e(TAG, "Error connecting RCD to client: ", e);
}
}
}
@@ -5578,44 +5655,86 @@
/**
* Unregister an IRemoteControlDisplay.
- * Since only one IRemoteControlDisplay is supported, this has no effect if the one to
- * unregister is not the current one.
+ * No effect if the IRemoteControlDisplay hasn't been successfully registered.
+ * @see android.media.IAudioService#unregisterRemoteControlDisplay(android.media.IRemoteControlDisplay)
* @param rcd the IRemoteControlDisplay to unregister. No effect if null.
*/
public void unregisterRemoteControlDisplay(IRemoteControlDisplay rcd) {
if (DEBUG_RC) Log.d(TAG, "<<< unregisterRemoteControlDisplay("+rcd+")");
synchronized(mRCStack) {
- // only one display here, so you can only unregister the current display
- if ((rcd == null) || (rcd != mRcDisplay)) {
- if (DEBUG_RC) Log.w(TAG, " trying to unregister unregistered RCD");
+ if (rcd == null) {
return;
}
- // if we had a display before, stop monitoring its death
- rcDisplay_stopDeathMonitor_syncRcStack();
- mRcDisplay = null;
- // disconnect this remote control display from all the clients, so the remote
- // control stack traversal order doesn't matter
- Iterator<RemoteControlStackEntry> stackIterator = mRCStack.iterator();
- while(stackIterator.hasNext()) {
- RemoteControlStackEntry rcse = stackIterator.next();
- if(rcse.mRcClient != null) {
- try {
- rcse.mRcClient.unplugRemoteControlDisplay(rcd);
- } catch (RemoteException e) {
- Log.e(TAG, "Error disconnecting remote control display to client: " + e);
- e.printStackTrace();
+ boolean displayWasPluggedIn = false;
+ final Iterator<DisplayInfoForServer> displayIterator = mRcDisplays.iterator();
+ while (displayIterator.hasNext() && !displayWasPluggedIn) {
+ final DisplayInfoForServer di = (DisplayInfoForServer) displayIterator.next();
+ if (di.mRcDisplay.asBinder().equals(rcd.asBinder())) {
+ displayWasPluggedIn = true;
+ di.release();
+ displayIterator.remove();
+ }
+ }
+
+ if (displayWasPluggedIn) {
+ // disconnect this remote control display from all the clients, so the remote
+ // control stack traversal order doesn't matter
+ final Iterator<RemoteControlStackEntry> stackIterator = mRCStack.iterator();
+ while(stackIterator.hasNext()) {
+ final RemoteControlStackEntry rcse = stackIterator.next();
+ if(rcse.mRcClient != null) {
+ try {
+ rcse.mRcClient.unplugRemoteControlDisplay(rcd);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error disconnecting remote control display to client: ", e);
+ }
}
}
+ } else {
+ if (DEBUG_RC) Log.w(TAG, " trying to unregister unregistered RCD");
}
}
}
+ /**
+ * Update the size of the artwork used by an IRemoteControlDisplay.
+ * @see android.media.IAudioService#remoteControlDisplayUsesBitmapSize(android.media.IRemoteControlDisplay, int, int)
+ * @param rcd the IRemoteControlDisplay with the new artwork size requirement
+ * @param w the maximum width of the expected bitmap. Negative or zero values indicate this
+ * display doesn't need to receive artwork.
+ * @param h the maximum height of the expected bitmap. Negative or zero values indicate this
+ * display doesn't need to receive artwork.
+ */
public void remoteControlDisplayUsesBitmapSize(IRemoteControlDisplay rcd, int w, int h) {
synchronized(mRCStack) {
- // NOTE: Only one IRemoteControlDisplay supported in this implementation
- mArtworkExpectedWidth = w;
- mArtworkExpectedHeight = h;
+ final Iterator<DisplayInfoForServer> displayIterator = mRcDisplays.iterator();
+ boolean artworkSizeUpdate = false;
+ while (displayIterator.hasNext() && !artworkSizeUpdate) {
+ final DisplayInfoForServer di = (DisplayInfoForServer) displayIterator.next();
+ if (di.mRcDisplay.asBinder().equals(rcd.asBinder())) {
+ if ((di.mArtworkExpectedWidth != w) || (di.mArtworkExpectedHeight != h)) {
+ di.mArtworkExpectedWidth = w;
+ di.mArtworkExpectedHeight = h;
+ artworkSizeUpdate = true;
+ }
+ }
+ }
+ if (artworkSizeUpdate) {
+ // RCD is currently plugged in and its artwork size has changed, notify all RCCs,
+ // stack traversal order doesn't matter
+ final Iterator<RemoteControlStackEntry> stackIterator = mRCStack.iterator();
+ while(stackIterator.hasNext()) {
+ final RemoteControlStackEntry rcse = stackIterator.next();
+ if(rcse.mRcClient != null) {
+ try {
+ rcse.mRcClient.setBitmapSizeForDisplay(rcd, w, h);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error setting bitmap size for RCD on RCC: ", e);
+ }
+ }
+ }
+ }
}
}
@@ -6218,6 +6337,7 @@
dumpFocusStack(pw);
dumpRCStack(pw);
dumpRCCStack(pw);
+ dumpRCDList(pw);
dumpStreamStates(pw);
dumpRingerMode(pw);
pw.println("\nAudio routes:");
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index ea99069..312c252 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -131,8 +131,31 @@
oneway void unregisterRemoteControlClient(in PendingIntent mediaIntent,
in IRemoteControlClient rcClient);
- oneway void registerRemoteControlDisplay(in IRemoteControlDisplay rcd);
+ /**
+ * Register an IRemoteControlDisplay.
+ * Notify all IRemoteControlClient of the new display and cause the RemoteControlClient
+ * at the top of the stack to update the new display with its information.
+ * @param rcd the IRemoteControlDisplay to register. No effect if null.
+ * @param w the maximum width of the expected bitmap. Negative or zero values indicate this
+ * display doesn't need to receive artwork.
+ * @param h the maximum height of the expected bitmap. Negative or zero values indicate this
+ * display doesn't need to receive artwork.
+ */
+ oneway void registerRemoteControlDisplay(in IRemoteControlDisplay rcd, int w, int h);
+ /**
+ * Unregister an IRemoteControlDisplay.
+ * No effect if the IRemoteControlDisplay hasn't been successfully registered.
+ * @param rcd the IRemoteControlDisplay to unregister. No effect if null.
+ */
oneway void unregisterRemoteControlDisplay(in IRemoteControlDisplay rcd);
+ /**
+ * Update the size of the artwork used by an IRemoteControlDisplay.
+ * @param rcd the IRemoteControlDisplay with the new artwork size requirement
+ * @param w the maximum width of the expected bitmap. Negative or zero values indicate this
+ * display doesn't need to receive artwork.
+ * @param h the maximum height of the expected bitmap. Negative or zero values indicate this
+ * display doesn't need to receive artwork.
+ */
oneway void remoteControlDisplayUsesBitmapSize(in IRemoteControlDisplay rcd, int w, int h);
oneway void setPlaybackInfoForRcc(int rccId, int what, int value);
diff --git a/media/java/android/media/IRemoteControlClient.aidl b/media/java/android/media/IRemoteControlClient.aidl
index 0fbba20..5600263 100644
--- a/media/java/android/media/IRemoteControlClient.aidl
+++ b/media/java/android/media/IRemoteControlClient.aidl
@@ -34,18 +34,17 @@
* parameters are valid.
* @param generationId
* @param infoFlags
- * @param artWidth if > 0, artHeight must be > 0 too.
- * @param artHeight
* FIXME: is infoFlags required? since the RCC pushes info, this might always be called
* with RC_INFO_ALL
*/
- void onInformationRequested(int generationId, int infoFlags, int artWidth, int artHeight);
+ void onInformationRequested(int generationId, int infoFlags);
/**
* Sets the generation counter of the current client that is displayed on the remote control.
*/
void setCurrentClientGenerationId(int clientGeneration);
- void plugRemoteControlDisplay(IRemoteControlDisplay rcd);
+ void plugRemoteControlDisplay(IRemoteControlDisplay rcd, int w, int h);
void unplugRemoteControlDisplay(IRemoteControlDisplay rcd);
+ void setBitmapSizeForDisplay(IRemoteControlDisplay rcd, int w, int h);
}
\ No newline at end of file
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index e155385..b6b49a2 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -263,12 +263,11 @@
Surface surface, MediaCrypto crypto, int flags);
/**
- * Requests a Surface to use instead of input buffers. This may only be called after
- * {@link #configure} and before {@link #start}.
+ * Requests a Surface to use as the input to an encoder, in place of input buffers. This
+ * may only be called after {@link #configure} and before {@link #start}.
* <p>
* The application is responsible for calling release() on the Surface when
* done.
- * @hide -- TODO(fadden): make this public before release
*/
public native final Surface createInputSurface();
@@ -471,7 +470,6 @@
* Signals end-of-stream on input. Equivalent to submitting an empty buffer with
* {@link #BUFFER_FLAG_END_OF_STREAM} set. This may only be used with
* encoders receiving input from a Surface created by {@link #createInputSurface}.
- * @hide -- TODO(fadden): make this public before release
*/
public native final void signalEndOfInputStream();
diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java
index 6c1b87a..1501c79 100644
--- a/media/java/android/media/MediaCodecInfo.java
+++ b/media/java/android/media/MediaCodecInfo.java
@@ -93,8 +93,9 @@
public final static int COLOR_Format24BitABGR6666 = 43;
public final static int COLOR_TI_FormatYUV420PackedSemiPlanar = 0x7f000100;
- /** @hide -- TODO(fadden): make this public before release */
- public final static int COLOR_FormatAndroidOpaque = 0x7F000789;
+ // COLOR_FormatSurface indicates that the data will be a GraphicBuffer metadata reference.
+ // In OMX this is called OMX_COLOR_FormatAndroidOpaque.
+ public final static int COLOR_FormatSurface = 0x7F000789;
public final static int COLOR_QCOM_FormatYUV420SemiPlanar = 0x7fa30c00;
/**
diff --git a/media/java/android/media/MediaMuxer.java b/media/java/android/media/MediaMuxer.java
new file mode 100644
index 0000000..dfd0e94
--- /dev/null
+++ b/media/java/android/media/MediaMuxer.java
@@ -0,0 +1,288 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+import android.media.MediaCodec.BufferInfo;
+
+import dalvik.system.CloseGuard;
+
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.Map;
+
+/**
+ * MediaMuxer facilitates muxing elementary streams. Currently only supports an
+ * mp4 file as the output and at most one audio and/or one video elementary
+ * stream.
+ * <p>
+ * It is generally used like this:
+ *
+ * <pre>
+ * MediaMuxer muxer = new MediaMuxer(...);
+ * MediaFormat audioFormat = new MediaFormat(...);
+ * MediaFormat videoFormat = new MediaFormat(...);
+ * int audioTrackIndex = muxer.addTrack(audioFormat);
+ * int videoTrackIndex = muxer.addTrack(videoFormat);
+ * ByteBuffer inputBuffer = ByteBuffer.allocate(...);
+ * muxer.start();
+ * while(inputBuffer has new data) {
+ * if (new data is audio sample) {
+ * muxer.writeSampleData(audioTrackIndex, inputBuffer, ...);
+ * } else if (new data is video sample) {
+ * muxer.writeSampleData(videoTrackIndex, inputBuffer, ...);
+ * }
+ * }
+ * muxer.stop();
+ * muxer.release();
+ * </pre>
+ */
+
+final public class MediaMuxer {
+
+ private int mNativeContext;
+
+ static {
+ System.loadLibrary("media_jni");
+ }
+
+ /**
+ * Defines the output format. These constants are used with constructor.
+ */
+ public static final class OutputFormat {
+ /* Do not change these values without updating their counterparts
+ * in include/media/stagefright/MediaMuxer.h!
+ */
+ private OutputFormat() {}
+ /** MPEG4 media file format*/
+ public static final int MUXER_OUTPUT_MPEG_4 = 0;
+ };
+
+ /**
+ * The sample is a sync sample, which does not require other video samples
+ * to decode. This flag is used in {@link #writeSampleData} to indicate
+ * which sample is a sync sample.
+ */
+ /* Keep this flag in sync with its equivalent in
+ * include/media/stagefright/MediaMuxer.h.
+ */
+ public static final int SAMPLE_FLAG_SYNC = 1;
+
+ // All the native functions are listed here.
+ private static native int nativeSetup(FileDescriptor fd, int format);
+ private static native void nativeRelease(int nativeObject);
+ private static native void nativeStart(int nativeObject);
+ private static native void nativeStop(int nativeObject);
+ private static native int nativeAddTrack(int nativeObject, String[] keys,
+ Object[] values);
+ private static native void nativeWriteSampleData(int nativeObject,
+ int trackIndex, ByteBuffer byteBuf,
+ int offset, int size, long presentationTimeUs, int flags);
+
+ // Muxer internal states.
+ private static final int MUXER_STATE_UNINITIALIZED = -1;
+ private static final int MUXER_STATE_INITIALIZED = 0;
+ private static final int MUXER_STATE_STARTED = 1;
+ private static final int MUXER_STATE_STOPPED = 2;
+
+ private int mState = MUXER_STATE_UNINITIALIZED;
+
+ private final CloseGuard mCloseGuard = CloseGuard.get();
+ private int mLastTrackIndex = -1;
+
+ private int mNativeObject;
+
+ /**
+ * Constructor
+ * Creates a media muxer that writes to the specified path.
+ * @param path The path of the output media file.
+ * @param format The format of the output media file.
+ * @see android.media.MediaMuxer.OutputFormat
+ * @throws IOException if failed to open the file for write
+ */
+ public MediaMuxer(String path, int format) throws IOException {
+ if (path == null) {
+ throw new IllegalArgumentException("path must not be null");
+ }
+ if (format != OutputFormat.MUXER_OUTPUT_MPEG_4) {
+ throw new IllegalArgumentException("format is invalid");
+ }
+ FileOutputStream fos = null;
+ try {
+ File file = new File(path);
+ fos = new FileOutputStream(file);
+ FileDescriptor fd = fos.getFD();
+ mNativeObject = nativeSetup(fd, format);
+ mState = MUXER_STATE_INITIALIZED;
+ mCloseGuard.open("release");
+ } finally {
+ if (fos != null) {
+ fos.close();
+ }
+ }
+ }
+
+ /**
+ * Starts the muxer.
+ * <p>Make sure this is called after {@link #addTrack} and before
+ * {@link #writeSampleData}.</p>
+ */
+ public void start() {
+ if (mNativeObject == 0) {
+ throw new IllegalStateException("Muxer has been released!");
+ }
+ if (mState == MUXER_STATE_INITIALIZED) {
+ nativeStart(mNativeObject);
+ mState = MUXER_STATE_STARTED;
+ } else {
+ throw new IllegalStateException("Can't start due to wrong state.");
+ }
+ }
+
+ /**
+ * Stops the muxer.
+ * <p>Once the muxer stops, it can not be restarted.</p>
+ */
+ public void stop() {
+ if (mState == MUXER_STATE_STARTED) {
+ nativeStop(mNativeObject);
+ mState = MUXER_STATE_STOPPED;
+ } else {
+ throw new IllegalStateException("Can't stop due to wrong state.");
+ }
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ try {
+ if (mCloseGuard != null) {
+ mCloseGuard.warnIfOpen();
+ }
+ if (mNativeObject != 0) {
+ nativeRelease(mNativeObject);
+ mNativeObject = 0;
+ }
+ } finally {
+ super.finalize();
+ }
+ }
+
+ /**
+ * Adds a track with the specified format.
+ * @param format The media format for the track.
+ * @return The track index for this newly added track, and it should be used
+ * in the {@link #writeSampleData}.
+ */
+ public int addTrack(MediaFormat format) {
+ if (format == null) {
+ throw new IllegalArgumentException("format must not be null.");
+ }
+ if (mState != MUXER_STATE_INITIALIZED) {
+ throw new IllegalStateException("Muxer is not initialized.");
+ }
+ if (mNativeObject == 0) {
+ throw new IllegalStateException("Muxer has been released!");
+ }
+ int trackIndex = -1;
+ // Convert the MediaFormat into key-value pairs and send to the native.
+ Map<String, Object> formatMap = format.getMap();
+
+ String[] keys = null;
+ Object[] values = null;
+ int mapSize = formatMap.size();
+ if (mapSize > 0) {
+ keys = new String[mapSize];
+ values = new Object[mapSize];
+ int i = 0;
+ for (Map.Entry<String, Object> entry : formatMap.entrySet()) {
+ keys[i] = entry.getKey();
+ values[i] = entry.getValue();
+ ++i;
+ }
+ trackIndex = nativeAddTrack(mNativeObject, keys, values);
+ } else {
+ throw new IllegalArgumentException("format must not be empty.");
+ }
+
+ // Track index number is expected to incremented as addTrack succeed.
+ // However, if format is invalid, it will get a negative trackIndex.
+ if (mLastTrackIndex >= trackIndex) {
+ throw new IllegalArgumentException("Invalid format.");
+ }
+ mLastTrackIndex = trackIndex;
+ return trackIndex;
+ }
+
+ /**
+ * Writes an encoded sample into the muxer. The application needs to make
+ * sure that the samples are written into the right tracks.
+ * @param byteBuf The encoded sample.
+ * @param trackIndex The track index for this sample.
+ * @param bufferInfo The buffer information related to this sample.
+ */
+ public void writeSampleData(int trackIndex, ByteBuffer byteBuf,
+ BufferInfo bufferInfo) {
+ if (trackIndex < 0 || trackIndex > mLastTrackIndex) {
+ throw new IllegalArgumentException("trackIndex is invalid");
+ }
+
+ if (byteBuf == null) {
+ throw new IllegalArgumentException("byteBuffer must not be null");
+ }
+
+ if (bufferInfo == null) {
+ throw new IllegalArgumentException("bufferInfo must not be null");
+ }
+ if (bufferInfo.size < 0 || bufferInfo.offset < 0
+ || (bufferInfo.offset + bufferInfo.size) > byteBuf.capacity()
+ || bufferInfo.presentationTimeUs < 0) {
+ throw new IllegalArgumentException("bufferInfo must specify a" +
+ " valid buffer offset, size and presentation time");
+ }
+
+ if (mNativeObject == 0) {
+ throw new IllegalStateException("Muxer has been released!");
+ }
+
+ if (mState != MUXER_STATE_STARTED) {
+ throw new IllegalStateException("Can't write, muxer is not started");
+ }
+
+ nativeWriteSampleData(mNativeObject, trackIndex, byteBuf,
+ bufferInfo.offset, bufferInfo.size,
+ bufferInfo.presentationTimeUs, bufferInfo.flags);
+ }
+
+ /**
+ * Make sure you call this when you're done to free up any resources
+ * instead of relying on the garbage collector to do this for you at
+ * some point in the future.
+ */
+ public void release() {
+ if (mState == MUXER_STATE_STARTED) {
+ throw new IllegalStateException("Can't release when muxer is started");
+ }
+ if (mNativeObject != 0) {
+ nativeRelease(mNativeObject);
+ mNativeObject = 0;
+ mCloseGuard.close();
+ }
+ mState = MUXER_STATE_UNINITIALIZED;
+ }
+}
diff --git a/media/java/android/media/MediaRouter.java b/media/java/android/media/MediaRouter.java
index 8b489b1..795c3c2 100644
--- a/media/java/android/media/MediaRouter.java
+++ b/media/java/android/media/MediaRouter.java
@@ -299,16 +299,21 @@
}
/**
- * @hide for use by framework routing UI
+ * Gets the default route for playing media content on the system.
+ * <p>
+ * The system always provides a default route.
+ * </p>
+ *
+ * @return The default route, which is guaranteed to never be null.
*/
- public RouteInfo getSystemAudioRoute() {
+ public RouteInfo getDefaultRoute() {
return sStatic.mDefaultAudioVideo;
}
/**
* @hide for use by framework routing UI
*/
- public RouteCategory getSystemAudioCategory() {
+ public RouteCategory getSystemCategory() {
return sStatic.mSystemCategory;
}
@@ -372,14 +377,17 @@
/**
* Select the specified route to use for output of the given media types.
+ * <p class="note">
+ * As API version 18, this function may be used to select any route.
+ * In prior versions, this function could only be used to select user
+ * routes and would ignore any attempt to select a system route.
+ * </p>
*
* @param types type flags indicating which types this route should be used for.
* The route must support at least a subset.
* @param route Route to select
*/
public void selectRoute(int types, RouteInfo route) {
- // Applications shouldn't programmatically change anything but user routes.
- types &= ROUTE_TYPE_USER;
selectRouteStatic(types, route);
}
@@ -454,7 +462,7 @@
* App-specified route definitions are created using {@link #createUserRoute(RouteCategory)}
*
* @param info Definition of the route to add
- * @see #createUserRoute()
+ * @see #createUserRoute(RouteCategory)
* @see #removeUserRoute(UserRouteInfo)
*/
public void addUserRoute(UserRouteInfo info) {
diff --git a/media/java/android/media/RemoteControlClient.java b/media/java/android/media/RemoteControlClient.java
index 4c71ace..9a0ecdf 100644
--- a/media/java/android/media/RemoteControlClient.java
+++ b/media/java/android/media/RemoteControlClient.java
@@ -36,6 +36,8 @@
import android.util.Log;
import java.lang.IllegalArgumentException;
+import java.util.ArrayList;
+import java.util.Iterator;
/**
* RemoteControlClient enables exposing information meant to be consumed by remote controls
@@ -498,13 +500,7 @@
if (key != BITMAP_KEY_ARTWORK) {
throw(new IllegalArgumentException("Invalid type 'Bitmap' for key "+ key));
}
- if ((mArtworkExpectedWidth > 0) && (mArtworkExpectedHeight > 0)) {
- mEditorArtwork = scaleBitmapIfTooBig(bitmap,
- mArtworkExpectedWidth, mArtworkExpectedHeight);
- } else {
- // no valid resize dimensions, store as is
- mEditorArtwork = bitmap;
- }
+ mEditorArtwork = bitmap;
mArtworkChanged = true;
return this;
}
@@ -536,10 +532,10 @@
synchronized(mCacheLock) {
// assign the edited data
mMetadata = new Bundle(mEditorMetadata);
- if ((mArtwork != null) && (!mArtwork.equals(mEditorArtwork))) {
- mArtwork.recycle();
+ if ((mOriginalArtwork != null) && (!mOriginalArtwork.equals(mEditorArtwork))) {
+ mOriginalArtwork.recycle();
}
- mArtwork = mEditorArtwork;
+ mOriginalArtwork = mEditorArtwork;
mEditorArtwork = null;
if (mMetadataChanged & mArtworkChanged) {
// send to remote control display if conditions are met
@@ -571,7 +567,7 @@
editor.mArtworkChanged = true;
} else {
editor.mEditorMetadata = new Bundle(mMetadata);
- editor.mEditorArtwork = mArtwork;
+ editor.mEditorArtwork = mOriginalArtwork;
editor.mMetadataChanged = false;
editor.mArtworkChanged = false;
}
@@ -766,11 +762,7 @@
* accessed to be resized, in which case a copy will be made. This would add overhead in
* Bundle operations.
*/
- private Bitmap mArtwork;
- private final int ARTWORK_DEFAULT_SIZE = 256;
- private final int ARTWORK_INVALID_SIZE = -1;
- private int mArtworkExpectedWidth = ARTWORK_DEFAULT_SIZE;
- private int mArtworkExpectedHeight = ARTWORK_DEFAULT_SIZE;
+ private Bitmap mOriginalArtwork;
/**
* Cache for the transport control mask.
* Access synchronized on mCacheLock
@@ -802,10 +794,27 @@
private final PendingIntent mRcMediaIntent;
/**
- * The remote control display to which this client will send information.
- * NOTE: Only one IRemoteControlDisplay supported in this implementation
+ * A class to encapsulate all the information about a remote control display.
+ * A RemoteControlClient's metadata and state may be displayed on multiple IRemoteControlDisplay
*/
- private IRemoteControlDisplay mRcDisplay;
+ private class DisplayInfoForClient {
+ /** may never be null */
+ private IRemoteControlDisplay mRcDisplay;
+ private int mArtworkExpectedWidth;
+ private int mArtworkExpectedHeight;
+
+ DisplayInfoForClient(IRemoteControlDisplay rcd, int w, int h) {
+ mRcDisplay = rcd;
+ mArtworkExpectedWidth = w;
+ mArtworkExpectedHeight = h;
+ }
+ }
+
+ /**
+ * The list of remote control displays to which this client will send information.
+ * Accessed and modified synchronized on mCacheLock
+ */
+ private ArrayList<DisplayInfoForClient> mRcDisplays = new ArrayList<DisplayInfoForClient>(1);
/**
* @hide
@@ -827,17 +836,14 @@
*/
private final IRemoteControlClient mIRCC = new IRemoteControlClient.Stub() {
- public void onInformationRequested(int clientGeneration, int infoFlags,
- int artWidth, int artHeight) {
+ public void onInformationRequested(int clientGeneration, int infoFlags) {
// only post messages, we can't block here
if (mEventHandler != null) {
// signal new client
mEventHandler.removeMessages(MSG_NEW_INTERNAL_CLIENT_GEN);
mEventHandler.dispatchMessage(
- mEventHandler.obtainMessage(
- MSG_NEW_INTERNAL_CLIENT_GEN,
- artWidth, artHeight,
- new Integer(clientGeneration)));
+ mEventHandler.obtainMessage(MSG_NEW_INTERNAL_CLIENT_GEN,
+ /*arg1*/ clientGeneration, /*arg2, ignored*/ 0));
// send the information
mEventHandler.removeMessages(MSG_REQUEST_PLAYBACK_STATE);
mEventHandler.removeMessages(MSG_REQUEST_METADATA);
@@ -861,21 +867,29 @@
}
}
- public void plugRemoteControlDisplay(IRemoteControlDisplay rcd) {
+ public void plugRemoteControlDisplay(IRemoteControlDisplay rcd, int w, int h) {
// only post messages, we can't block here
- if (mEventHandler != null) {
+ if ((mEventHandler != null) && (rcd != null)) {
mEventHandler.dispatchMessage(mEventHandler.obtainMessage(
- MSG_PLUG_DISPLAY, rcd));
+ MSG_PLUG_DISPLAY, w, h, rcd));
}
}
public void unplugRemoteControlDisplay(IRemoteControlDisplay rcd) {
// only post messages, we can't block here
- if (mEventHandler != null) {
+ if ((mEventHandler != null) && (rcd != null)) {
mEventHandler.dispatchMessage(mEventHandler.obtainMessage(
MSG_UNPLUG_DISPLAY, rcd));
}
}
+
+ public void setBitmapSizeForDisplay(IRemoteControlDisplay rcd, int w, int h) {
+ // only post messages, we can't block here
+ if ((mEventHandler != null) && (rcd != null)) {
+ mEventHandler.dispatchMessage(mEventHandler.obtainMessage(
+ MSG_UPDATE_DISPLAY_ARTWORK_SIZE, w, h, rcd));
+ }
+ }
};
/**
@@ -915,6 +929,7 @@
private final static int MSG_NEW_CURRENT_CLIENT_GEN = 6;
private final static int MSG_PLUG_DISPLAY = 7;
private final static int MSG_UNPLUG_DISPLAY = 8;
+ private final static int MSG_UPDATE_DISPLAY_ARTWORK_SIZE = 9;
private class EventHandler extends Handler {
public EventHandler(RemoteControlClient rcc, Looper looper) {
@@ -945,17 +960,20 @@
}
break;
case MSG_NEW_INTERNAL_CLIENT_GEN:
- onNewInternalClientGen((Integer)msg.obj, msg.arg1, msg.arg2);
+ onNewInternalClientGen(msg.arg1);
break;
case MSG_NEW_CURRENT_CLIENT_GEN:
onNewCurrentClientGen(msg.arg1);
break;
case MSG_PLUG_DISPLAY:
- onPlugDisplay((IRemoteControlDisplay)msg.obj);
+ onPlugDisplay((IRemoteControlDisplay)msg.obj, msg.arg1, msg.arg2);
break;
case MSG_UNPLUG_DISPLAY:
onUnplugDisplay((IRemoteControlDisplay)msg.obj);
break;
+ case MSG_UPDATE_DISPLAY_ARTWORK_SIZE:
+ onUpdateDisplayArtworkSize((IRemoteControlDisplay)msg.obj, msg.arg1, msg.arg2);
+ break;
default:
Log.e(TAG, "Unknown event " + msg.what + " in RemoteControlClient handler");
}
@@ -963,75 +981,106 @@
}
//===========================================================
- // Communication with IRemoteControlDisplay
-
- private void detachFromDisplay_syncCacheLock() {
- mRcDisplay = null;
- mArtworkExpectedWidth = ARTWORK_INVALID_SIZE;
- mArtworkExpectedHeight = ARTWORK_INVALID_SIZE;
- }
+ // Communication with the IRemoteControlDisplay (the displays known to the system)
private void sendPlaybackState_syncCacheLock() {
- if ((mCurrentClientGenId == mInternalClientGenId) && (mRcDisplay != null)) {
- try {
- mRcDisplay.setPlaybackState(mInternalClientGenId, mPlaybackState,
- mPlaybackStateChangeTimeMs);
- } catch (RemoteException e) {
- Log.e(TAG, "Error in setPlaybackState(), dead display "+e);
- detachFromDisplay_syncCacheLock();
+ if (mCurrentClientGenId == mInternalClientGenId) {
+ final Iterator<DisplayInfoForClient> displayIterator = mRcDisplays.iterator();
+ while (displayIterator.hasNext()) {
+ final DisplayInfoForClient di = (DisplayInfoForClient) displayIterator.next();
+ try {
+ di.mRcDisplay.setPlaybackState(mInternalClientGenId,
+ mPlaybackState, mPlaybackStateChangeTimeMs);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error in setPlaybackState(), dead display " + di.mRcDisplay, e);
+ displayIterator.remove();
+ }
}
}
}
private void sendMetadata_syncCacheLock() {
- if ((mCurrentClientGenId == mInternalClientGenId) && (mRcDisplay != null)) {
- try {
- mRcDisplay.setMetadata(mInternalClientGenId, mMetadata);
- } catch (RemoteException e) {
- Log.e(TAG, "Error in sendPlaybackState(), dead display "+e);
- detachFromDisplay_syncCacheLock();
+ if (mCurrentClientGenId == mInternalClientGenId) {
+ final Iterator<DisplayInfoForClient> displayIterator = mRcDisplays.iterator();
+ while (displayIterator.hasNext()) {
+ final DisplayInfoForClient di = (DisplayInfoForClient) displayIterator.next();
+ try {
+ di.mRcDisplay.setMetadata(mInternalClientGenId, mMetadata);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error in setMetadata(), dead display " + di.mRcDisplay, e);
+ displayIterator.remove();
+ }
}
}
}
private void sendTransportControlFlags_syncCacheLock() {
- if ((mCurrentClientGenId == mInternalClientGenId) && (mRcDisplay != null)) {
- try {
- mRcDisplay.setTransportControlFlags(mInternalClientGenId,
- mTransportControlFlags);
- } catch (RemoteException e) {
- Log.e(TAG, "Error in sendTransportControlFlags(), dead display "+e);
- detachFromDisplay_syncCacheLock();
+ if (mCurrentClientGenId == mInternalClientGenId) {
+ final Iterator<DisplayInfoForClient> displayIterator = mRcDisplays.iterator();
+ while (displayIterator.hasNext()) {
+ final DisplayInfoForClient di = (DisplayInfoForClient) displayIterator.next();
+ try {
+ di.mRcDisplay.setTransportControlFlags(mInternalClientGenId,
+ mTransportControlFlags);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error in setTransportControlFlags(), dead display " + di.mRcDisplay,
+ e);
+ displayIterator.remove();
+ }
}
}
}
private void sendArtwork_syncCacheLock() {
- if ((mCurrentClientGenId == mInternalClientGenId) && (mRcDisplay != null)) {
- // even though we have already scaled in setArtwork(), when this client needs to
- // send the bitmap, there might be newer and smaller expected dimensions, so we have
- // to check again.
- mArtwork = scaleBitmapIfTooBig(mArtwork, mArtworkExpectedWidth, mArtworkExpectedHeight);
- try {
- mRcDisplay.setArtwork(mInternalClientGenId, mArtwork);
- } catch (RemoteException e) {
- Log.e(TAG, "Error in sendArtwork(), dead display "+e);
- detachFromDisplay_syncCacheLock();
+ // FIXME modify to cache all requested sizes?
+ if (mCurrentClientGenId == mInternalClientGenId) {
+ final Iterator<DisplayInfoForClient> displayIterator = mRcDisplays.iterator();
+ while (displayIterator.hasNext()) {
+ if (!sendArtworkToDisplay((DisplayInfoForClient) displayIterator.next())) {
+ displayIterator.remove();
+ }
}
}
}
- private void sendMetadataWithArtwork_syncCacheLock() {
- if ((mCurrentClientGenId == mInternalClientGenId) && (mRcDisplay != null)) {
- // even though we have already scaled in setArtwork(), when this client needs to
- // send the bitmap, there might be newer and smaller expected dimensions, so we have
- // to check again.
- mArtwork = scaleBitmapIfTooBig(mArtwork, mArtworkExpectedWidth, mArtworkExpectedHeight);
+ /**
+ * Send artwork to an IRemoteControlDisplay.
+ * @param di encapsulates the IRemoteControlDisplay that will receive the artwork, and its
+ * dimension requirements.
+ * @return false if there was an error communicating with the IRemoteControlDisplay.
+ */
+ private boolean sendArtworkToDisplay(DisplayInfoForClient di) {
+ if ((di.mArtworkExpectedWidth > 0) && (di.mArtworkExpectedHeight > 0)) {
+ Bitmap artwork = scaleBitmapIfTooBig(mOriginalArtwork,
+ di.mArtworkExpectedWidth, di.mArtworkExpectedHeight);
try {
- mRcDisplay.setAllMetadata(mInternalClientGenId, mMetadata, mArtwork);
+ di.mRcDisplay.setArtwork(mInternalClientGenId, artwork);
} catch (RemoteException e) {
- Log.e(TAG, "Error in setAllMetadata(), dead display "+e);
- detachFromDisplay_syncCacheLock();
+ Log.e(TAG, "Error in sendArtworkToDisplay(), dead display " + di.mRcDisplay, e);
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private void sendMetadataWithArtwork_syncCacheLock() {
+ // FIXME modify to cache all requested sizes?
+ if (mCurrentClientGenId == mInternalClientGenId) {
+ final Iterator<DisplayInfoForClient> displayIterator = mRcDisplays.iterator();
+ while (displayIterator.hasNext()) {
+ final DisplayInfoForClient di = (DisplayInfoForClient) displayIterator.next();
+ try {
+ if ((di.mArtworkExpectedWidth > 0) && (di.mArtworkExpectedHeight > 0)) {
+ Bitmap artwork = scaleBitmapIfTooBig(mOriginalArtwork,
+ di.mArtworkExpectedWidth, di.mArtworkExpectedHeight);
+ di.mRcDisplay.setAllMetadata(mInternalClientGenId, mMetadata, artwork);
+ } else {
+ di.mRcDisplay.setMetadata(mInternalClientGenId, mMetadata);
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error when setting metadata, dead display " + di.mRcDisplay, e);
+ displayIterator.remove();
+ }
}
}
}
@@ -1067,15 +1116,11 @@
//===========================================================
// Message handlers
- private void onNewInternalClientGen(Integer clientGeneration, int artWidth, int artHeight) {
+ private void onNewInternalClientGen(int clientGeneration) {
synchronized (mCacheLock) {
// this remote control client is told it is the "focused" one:
// it implies that now (mCurrentClientGenId == mInternalClientGenId) is true
- mInternalClientGenId = clientGeneration.intValue();
- if (artWidth > 0) {
- mArtworkExpectedWidth = artWidth;
- mArtworkExpectedHeight = artHeight;
- }
+ mInternalClientGenId = clientGeneration;
}
}
@@ -1085,18 +1130,62 @@
}
}
- private void onPlugDisplay(IRemoteControlDisplay rcd) {
+ /** pre-condition rcd != null */
+ private void onPlugDisplay(IRemoteControlDisplay rcd, int w, int h) {
synchronized(mCacheLock) {
- mRcDisplay = rcd;
+ // do we have this display already?
+ boolean displayKnown = false;
+ final Iterator<DisplayInfoForClient> displayIterator = mRcDisplays.iterator();
+ while (displayIterator.hasNext() && !displayKnown) {
+ final DisplayInfoForClient di = (DisplayInfoForClient) displayIterator.next();
+ displayKnown = di.mRcDisplay.asBinder().equals(rcd.asBinder());
+ if (displayKnown) {
+ // this display was known but the change in artwork size will cause the
+ // artwork to be refreshed
+ if ((di.mArtworkExpectedWidth != w) || (di.mArtworkExpectedHeight != h)) {
+ di.mArtworkExpectedWidth = w;
+ di.mArtworkExpectedHeight = h;
+ if (!sendArtworkToDisplay(di)) {
+ displayIterator.remove();
+ }
+ }
+ }
+ }
+ if (!displayKnown) {
+ mRcDisplays.add(new DisplayInfoForClient(rcd, w, h));
+ }
}
}
+ /** pre-condition rcd != null */
private void onUnplugDisplay(IRemoteControlDisplay rcd) {
synchronized(mCacheLock) {
- if ((mRcDisplay != null) && (mRcDisplay.asBinder().equals(rcd.asBinder()))) {
- mRcDisplay = null;
- mArtworkExpectedWidth = ARTWORK_DEFAULT_SIZE;
- mArtworkExpectedHeight = ARTWORK_DEFAULT_SIZE;
+ final Iterator<DisplayInfoForClient> displayIterator = mRcDisplays.iterator();
+ while (displayIterator.hasNext()) {
+ final DisplayInfoForClient di = (DisplayInfoForClient) displayIterator.next();
+ if (di.mRcDisplay.asBinder().equals(rcd.asBinder())) {
+ displayIterator.remove();
+ return;
+ }
+ }
+ }
+ }
+
+ /** pre-condition rcd != null */
+ private void onUpdateDisplayArtworkSize(IRemoteControlDisplay rcd, int w, int h) {
+ synchronized(mCacheLock) {
+ final Iterator<DisplayInfoForClient> displayIterator = mRcDisplays.iterator();
+ while (displayIterator.hasNext()) {
+ final DisplayInfoForClient di = (DisplayInfoForClient) displayIterator.next();
+ if (di.mRcDisplay.asBinder().equals(rcd.asBinder()) &&
+ ((di.mArtworkExpectedWidth != w) || (di.mArtworkExpectedHeight != h))) {
+ di.mArtworkExpectedWidth = w;
+ di.mArtworkExpectedHeight = h;
+ if (!sendArtworkToDisplay(di)) {
+ displayIterator.remove();
+ }
+ break;
+ }
}
}
}
diff --git a/media/jni/Android.mk b/media/jni/Android.mk
index 6aaab220..ac8fb74 100644
--- a/media/jni/Android.mk
+++ b/media/jni/Android.mk
@@ -6,6 +6,7 @@
android_media_MediaCodec.cpp \
android_media_MediaCodecList.cpp \
android_media_MediaExtractor.cpp \
+ android_media_MediaMuxer.cpp \
android_media_MediaPlayer.cpp \
android_media_MediaRecorder.cpp \
android_media_MediaScanner.cpp \
diff --git a/media/jni/android_media_MediaMuxer.cpp b/media/jni/android_media_MediaMuxer.cpp
new file mode 100644
index 0000000..30ebb00
--- /dev/null
+++ b/media/jni/android_media_MediaMuxer.cpp
@@ -0,0 +1,233 @@
+/*
+ * Copyright 2013, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "MediaMuxer-JNI"
+#include <utils/Log.h>
+
+#include "android_media_Utils.h"
+#include "android_runtime/AndroidRuntime.h"
+#include "jni.h"
+#include "JNIHelp.h"
+
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/MediaMuxer.h>
+
+namespace android {
+
+struct fields_t {
+ jfieldID context;
+ jmethodID arrayID;
+};
+
+static fields_t gFields;
+
+}
+
+using namespace android;
+
+static jint android_media_MediaMuxer_addTrack(
+ JNIEnv *env, jclass clazz, jint nativeObject, jobjectArray keys,
+ jobjectArray values) {
+ sp<MediaMuxer> muxer(reinterpret_cast<MediaMuxer *>(nativeObject));
+ if (muxer == NULL) {
+ jniThrowException(env, "java/lang/IllegalStateException",
+ "Muxer was not set up correctly");
+ return -1;
+ }
+
+ sp<AMessage> trackformat;
+ status_t err = ConvertKeyValueArraysToMessage(env, keys, values,
+ &trackformat);
+ if (err != OK) {
+ jniThrowException(env, "java/lang/IllegalArgumentException",
+ "ConvertKeyValueArraysToMessage got an error");
+ return err;
+ }
+
+ // Return negative value when errors happen in addTrack.
+ jint trackIndex = muxer->addTrack(trackformat);
+
+ if (trackIndex < 0) {
+ jniThrowException(env, "java/lang/IllegalStateException",
+ "Failed to add the track to the muxer");
+ return -1;
+ }
+ return trackIndex;
+}
+
+static void android_media_MediaMuxer_writeSampleData(
+ JNIEnv *env, jclass clazz, jint nativeObject, jint trackIndex,
+ jobject byteBuf, jint offset, jint size, jlong timeUs, jint flags) {
+ sp<MediaMuxer> muxer(reinterpret_cast<MediaMuxer *>(nativeObject));
+ if (muxer == NULL) {
+ jniThrowException(env, "java/lang/IllegalStateException",
+ "Muxer was not set up correctly");
+ return;
+ }
+
+ // Try to convert the incoming byteBuffer into ABuffer
+ void *dst = env->GetDirectBufferAddress(byteBuf);
+
+ jlong dstSize;
+ jbyteArray byteArray = NULL;
+
+ if (dst == NULL) {
+
+ byteArray =
+ (jbyteArray)env->CallObjectMethod(byteBuf, gFields.arrayID);
+
+ if (byteArray == NULL) {
+ jniThrowException(env, "java/lang/IllegalArgumentException",
+ "byteArray is null");
+ return;
+ }
+
+ jboolean isCopy;
+ dst = env->GetByteArrayElements(byteArray, &isCopy);
+
+ dstSize = env->GetArrayLength(byteArray);
+ } else {
+ dstSize = env->GetDirectBufferCapacity(byteBuf);
+ }
+
+ if (dstSize < (offset + size)) {
+ ALOGE("writeSampleData saw wrong dstSize %lld, size %d, offset %d",
+ dstSize, size, offset);
+ if (byteArray != NULL) {
+ env->ReleaseByteArrayElements(byteArray, (jbyte *)dst, 0);
+ }
+ jniThrowException(env, "java/lang/IllegalArgumentException",
+ "sample has a wrong size");
+ return;
+ }
+
+ sp<ABuffer> buffer = new ABuffer((char *)dst + offset, size);
+
+ status_t err = muxer->writeSampleData(buffer, trackIndex, timeUs, flags);
+
+ if (byteArray != NULL) {
+ env->ReleaseByteArrayElements(byteArray, (jbyte *)dst, 0);
+ }
+
+ if (err != OK) {
+ jniThrowException(env, "java/lang/IllegalStateException",
+ "writeSampleData returned an error");
+ }
+ return;
+}
+
+// Constructor counterpart.
+static jint android_media_MediaMuxer_native_setup(
+ JNIEnv *env, jclass clazz, jobject fileDescriptor,
+ jint format) {
+ int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
+ ALOGV("native_setup: fd %d", fd);
+
+ MediaMuxer::OutputFormat fileFormat =
+ static_cast<MediaMuxer::OutputFormat>(format);
+ sp<MediaMuxer> muxer = new MediaMuxer(fd, fileFormat);
+ muxer->incStrong(clazz);
+ return int(muxer.get());
+}
+
+static void android_media_MediaMuxer_start(JNIEnv *env, jclass clazz,
+ jint nativeObject) {
+ sp<MediaMuxer> muxer(reinterpret_cast<MediaMuxer *>(nativeObject));
+ if (muxer == NULL) {
+ jniThrowException(env, "java/lang/IllegalStateException",
+ "Muxer was not set up correctly");
+ return;
+ }
+ status_t err = muxer->start();
+
+ if (err != OK) {
+ jniThrowException(env, "java/lang/IllegalStateException",
+ "Failed to start the muxer");
+ return;
+ }
+
+}
+
+static void android_media_MediaMuxer_stop(JNIEnv *env, jclass clazz,
+ jint nativeObject) {
+ sp<MediaMuxer> muxer(reinterpret_cast<MediaMuxer *>(nativeObject));
+ if (muxer == NULL) {
+ jniThrowException(env, "java/lang/IllegalStateException",
+ "Muxer was not set up correctly");
+ return;
+ }
+
+ status_t err = muxer->stop();
+
+ if (err != OK) {
+ jniThrowException(env, "java/lang/IllegalStateException",
+ "Failed to stop the muxer");
+ return;
+ }
+}
+
+static void android_media_MediaMuxer_native_release(
+ JNIEnv *env, jclass clazz, jint nativeObject) {
+ sp<MediaMuxer> muxer(reinterpret_cast<MediaMuxer *>(nativeObject));
+ if (muxer != NULL) {
+ muxer->decStrong(clazz);
+ }
+}
+
+static JNINativeMethod gMethods[] = {
+
+ { "nativeAddTrack", "(I[Ljava/lang/String;[Ljava/lang/Object;)I",
+ (void *)android_media_MediaMuxer_addTrack },
+
+ { "nativeStart", "(I)V", (void *)android_media_MediaMuxer_start},
+
+ { "nativeWriteSampleData", "(IILjava/nio/ByteBuffer;IIJI)V",
+ (void *)android_media_MediaMuxer_writeSampleData },
+
+ { "nativeStop", "(I)V", (void *)android_media_MediaMuxer_stop},
+
+ { "nativeSetup", "(Ljava/io/FileDescriptor;I)I",
+ (void *)android_media_MediaMuxer_native_setup },
+
+ { "nativeRelease", "(I)V",
+ (void *)android_media_MediaMuxer_native_release },
+
+};
+
+// This function only registers the native methods, and is called from
+// JNI_OnLoad in android_media_MediaPlayer.cpp
+int register_android_media_MediaMuxer(JNIEnv *env) {
+ int err = AndroidRuntime::registerNativeMethods(env,
+ "android/media/MediaMuxer", gMethods, NELEM(gMethods));
+
+ jclass clazz = env->FindClass("android/media/MediaMuxer");
+ CHECK(clazz != NULL);
+
+ gFields.context = env->GetFieldID(clazz, "mNativeContext", "I");
+ CHECK(gFields.context != NULL);
+
+ jclass byteBufClass = env->FindClass("java/nio/ByteBuffer");
+ CHECK(byteBufClass != NULL);
+
+ gFields.arrayID =
+ env->GetMethodID(byteBufClass, "array", "()[B");
+ CHECK(gFields.arrayID != NULL);
+
+ return err;
+}
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index 8768e96..e9f6a1e 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -883,6 +883,7 @@
extern int register_android_media_MediaExtractor(JNIEnv *env);
extern int register_android_media_MediaCodecList(JNIEnv *env);
extern int register_android_media_MediaMetadataRetriever(JNIEnv *env);
+extern int register_android_media_MediaMuxer(JNIEnv *env);
extern int register_android_media_MediaRecorder(JNIEnv *env);
extern int register_android_media_MediaScanner(JNIEnv *env);
extern int register_android_media_ResampleInputStream(JNIEnv *env);
@@ -963,6 +964,11 @@
goto bail;
}
+ if (register_android_media_MediaMuxer(env) < 0) {
+ ALOGE("ERROR: MediaMuxer native registration failed");
+ goto bail;
+ }
+
if (register_android_media_MediaCodecList(env) < 0) {
ALOGE("ERROR: MediaCodec native registration failed");
goto bail;
diff --git a/opengl/java/android/opengl/EGL14.java b/opengl/java/android/opengl/EGL14.java
index d1e2a9ed..2c9508a 100644
--- a/opengl/java/android/opengl/EGL14.java
+++ b/opengl/java/android/opengl/EGL14.java
@@ -447,7 +447,6 @@
// C function EGLBoolean eglPresentationTimeANDROID ( EGLDisplay dpy, EGLSurface sur, EGLnsecsANDROID time )
- /** @hide -- TODO(fadden) unhide this */
public static native boolean eglPresentationTimeANDROID(
EGLDisplay dpy,
EGLSurface sur,
diff --git a/packages/SharedStorageBackup/AndroidManifest.xml b/packages/SharedStorageBackup/AndroidManifest.xml
index fc21df3..b8df88e 100644
--- a/packages/SharedStorageBackup/AndroidManifest.xml
+++ b/packages/SharedStorageBackup/AndroidManifest.xml
@@ -24,5 +24,12 @@
<application android:allowClearUserData="false"
android:permission="android.permission.CONFIRM_FULL_BACKUP"
android:backupAgent="SharedStorageAgent" >
+
+ <service android:name=".ObbBackupService"
+ android:enabled="true"
+ android:exported="true">
+ </service>
+
</application>
+
</manifest>
diff --git a/packages/SharedStorageBackup/proguard.flags b/packages/SharedStorageBackup/proguard.flags
index f43cb81..6a66a47 100644
--- a/packages/SharedStorageBackup/proguard.flags
+++ b/packages/SharedStorageBackup/proguard.flags
@@ -1 +1,2 @@
-keep class com.android.sharedstoragebackup.SharedStorageAgent
+-keep class com.android.sharedstoragebackup.ObbBackupService
diff --git a/packages/SharedStorageBackup/src/com/android/sharedstoragebackup/ObbBackupService.java b/packages/SharedStorageBackup/src/com/android/sharedstoragebackup/ObbBackupService.java
new file mode 100644
index 0000000..7ebe096
--- /dev/null
+++ b/packages/SharedStorageBackup/src/com/android/sharedstoragebackup/ObbBackupService.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.sharedstoragebackup;
+
+import android.app.Service;
+import android.app.backup.BackupDataOutput;
+import android.app.backup.FullBackup;
+import android.app.backup.IBackupManager;
+import android.content.Intent;
+import android.os.Environment;
+import android.os.IBinder;
+import android.os.ParcelFileDescriptor;
+import android.os.RemoteException;
+import android.util.Log;
+
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+
+import com.android.internal.backup.IObbBackupService;
+
+/**
+ * Service that the Backup Manager Services delegates OBB backup/restore operations to,
+ * because those require accessing external storage.
+ *
+ * {@hide}
+ */
+public class ObbBackupService extends Service {
+ static final String TAG = "ObbBackupService";
+ static final boolean DEBUG = true;
+
+ /**
+ * IObbBackupService interface implementation
+ */
+ IObbBackupService mService = new IObbBackupService.Stub() {
+ /*
+ * Back up a package's OBB directory tree
+ */
+ @Override
+ public void backupObbs(String packageName, ParcelFileDescriptor data,
+ int token, IBackupManager callbackBinder) {
+ final FileDescriptor outFd = data.getFileDescriptor();
+ try {
+ File obbDir = Environment.getExternalStorageAppObbDirectory(packageName);
+ if (obbDir != null) {
+ if (obbDir.exists()) {
+ ArrayList<File> obbList = allFileContents(obbDir);
+ if (obbList != null) {
+ // okay, there's at least something there
+ if (DEBUG) {
+ Log.i(TAG, obbList.size() + " files to back up");
+ }
+ final String rootPath = obbDir.getCanonicalPath();
+ final BackupDataOutput out = new BackupDataOutput(outFd);
+ for (File f : obbList) {
+ final String filePath = f.getCanonicalPath();
+ if (DEBUG) {
+ Log.i(TAG, "storing: " + filePath);
+ }
+ FullBackup.backupToTar(packageName, FullBackup.OBB_TREE_TOKEN, null,
+ rootPath, filePath, out);
+ }
+ }
+ }
+ }
+ } catch (IOException e) {
+ Log.w(TAG, "Exception backing up OBBs for " + packageName, e);
+ } finally {
+ // Send the EOD marker indicating that there is no more data
+ try {
+ FileOutputStream out = new FileOutputStream(outFd);
+ byte[] buf = new byte[4];
+ out.write(buf);
+ } catch (IOException e) {
+ Log.e(TAG, "Unable to finalize obb backup stream!");
+ }
+
+ try {
+ callbackBinder.opComplete(token);
+ } catch (RemoteException e) {
+ }
+ }
+ }
+
+ /*
+ * Restore an OBB file for the given package from the incoming stream
+ */
+ @Override
+ public void restoreObbFile(String packageName, ParcelFileDescriptor data,
+ long fileSize, int type, String path, long mode, long mtime,
+ int token, IBackupManager callbackBinder) {
+ try {
+ File outFile = Environment.getExternalStorageAppObbDirectory(packageName);
+ if (outFile != null) {
+ outFile = new File(outFile, path);
+ }
+ // outFile is null here if we couldn't get access to external storage,
+ // in which case restoreFile() will discard the data cleanly and let
+ // us proceed with the next file segment in the stream. We pass -1
+ // for the file mode to suppress attempts to chmod() on shared storage.
+ FullBackup.restoreFile(data, fileSize, type, -1, mtime, outFile);
+ } catch (IOException e) {
+ Log.i(TAG, "Exception restoring OBB " + path, e);
+ } finally {
+ try {
+ callbackBinder.opComplete(token);
+ } catch (RemoteException e) {
+ }
+ }
+ }
+
+ ArrayList<File> allFileContents(File rootDir) {
+ final ArrayList<File> files = new ArrayList<File>();
+ final ArrayList<File> dirs = new ArrayList<File>();
+
+ dirs.add(rootDir);
+ while (!dirs.isEmpty()) {
+ File dir = dirs.remove(0);
+ File[] contents = dir.listFiles();
+ if (contents != null) {
+ for (File f : contents) {
+ if (f.isDirectory()) dirs.add(f);
+ else if (f.isFile()) files.add(f);
+ }
+ }
+ }
+ return files;
+ }
+ };
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return mService.asBinder();
+ }
+}
diff --git a/packages/SystemUI/res/layout-land/status_bar_help.xml b/packages/SystemUI/res/layout-land/status_bar_help.xml
index 83b9829..a885b86 100644
--- a/packages/SystemUI/res/layout-land/status_bar_help.xml
+++ b/packages/SystemUI/res/layout-land/status_bar_help.xml
@@ -22,8 +22,8 @@
xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/status_bar_cling"
- android:paddingLeft="40dp"
- android:paddingRight="40dp"
+ android:paddingStart="40dp"
+ android:paddingEnd="40dp"
android:background="#DD000000"
android:focusable="true"
android:orientation="horizontal"
@@ -34,7 +34,7 @@
android:layout_width="wrap_content"
android:layout_weight="0"
android:layout_height="wrap_content"
- android:layout_marginRight="50dp"
+ android:layout_marginEnd="50dp"
android:gravity="center"
android:src="@drawable/arrow_dashed"
tools:ignore="ContentDescription" />
@@ -64,8 +64,8 @@
style="@style/ClingButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:paddingLeft="50dp"
- android:paddingRight="50dp"
+ android:paddingStart="50dp"
+ android:paddingEnd="50dp"
android:text="@android:string/ok" />
</LinearLayout>
</LinearLayout>
diff --git a/packages/SystemUI/res/layout-land/status_bar_recent_item.xml b/packages/SystemUI/res/layout-land/status_bar_recent_item.xml
index 47d628b..1257641 100644
--- a/packages/SystemUI/res/layout-land/status_bar_recent_item.xml
+++ b/packages/SystemUI/res/layout-land/status_bar_recent_item.xml
@@ -22,8 +22,8 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="match_parent"
android:layout_width="wrap_content"
- android:paddingLeft="@dimen/status_bar_recents_item_padding"
- android:paddingRight="@dimen/status_bar_recents_item_padding"
+ android:paddingStart="@dimen/status_bar_recents_item_padding"
+ android:paddingEnd="@dimen/status_bar_recents_item_padding"
android:importantForAccessibility="no"
android:clipChildren="false">
@@ -72,7 +72,7 @@
android:fadingEdge="horizontal"
android:fadingEdgeLength="@dimen/status_bar_recents_text_fading_edge_length"
android:scrollHorizontally="true"
- android:layout_alignLeft="@id/app_thumbnail"
+ android:layout_alignStart="@id/app_thumbnail"
android:layout_below="@id/app_thumbnail"
android:layout_marginTop="@dimen/status_bar_recents_text_description_padding"
android:layout_marginStart="@dimen/status_bar_recents_app_label_left_margin"
diff --git a/packages/SystemUI/res/layout-land/status_bar_search_panel.xml b/packages/SystemUI/res/layout-land/status_bar_search_panel.xml
index 96b0a1f..a109191 100644
--- a/packages/SystemUI/res/layout-land/status_bar_search_panel.xml
+++ b/packages/SystemUI/res/layout-land/status_bar_search_panel.xml
@@ -36,7 +36,7 @@
android:id="@+id/search_panel_container"
android:layout_width="wrap_content"
android:layout_height="match_parent"
- android:layout_alignParentRight="true">
+ android:layout_alignParentEnd="true">
<com.android.internal.widget.multiwaveview.GlowPadView
android:id="@+id/glow_pad_view"
diff --git a/packages/SystemUI/res/layout-sw600dp/navigation_bar.xml b/packages/SystemUI/res/layout-sw600dp/navigation_bar.xml
index 0bac993..47db1c7 100644
--- a/packages/SystemUI/res/layout-sw600dp/navigation_bar.xml
+++ b/packages/SystemUI/res/layout-sw600dp/navigation_bar.xml
@@ -54,7 +54,7 @@
android:layout_weight="1"
/>
<com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/back"
- android:layout_width="128dp" android:paddingLeft="25dp" android:paddingRight="25dp"
+ android:layout_width="128dp" android:paddingStart="25dp" android:paddingEnd="25dp"
android:layout_height="match_parent"
android:src="@drawable/ic_sysbar_back"
systemui:keyCode="4"
@@ -63,7 +63,7 @@
android:contentDescription="@string/accessibility_back"
/>
<com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/home"
- android:layout_width="128dp" android:paddingLeft="25dp" android:paddingRight="25dp"
+ android:layout_width="128dp" android:paddingStart="25dp" android:paddingEnd="25dp"
android:layout_height="match_parent"
android:src="@drawable/ic_sysbar_home"
systemui:keyCode="3"
@@ -73,7 +73,7 @@
android:contentDescription="@string/accessibility_home"
/>
<com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/recent_apps"
- android:layout_width="128dp" android:paddingLeft="25dp" android:paddingRight="25dp"
+ android:layout_width="128dp" android:paddingStart="25dp" android:paddingEnd="25dp"
android:layout_height="match_parent"
android:src="@drawable/ic_sysbar_recent"
android:layout_weight="0"
@@ -112,7 +112,7 @@
android:layout_weight="1"
/>
<ImageView
- android:layout_width="128dp" android:paddingLeft="25dp" android:paddingRight="25dp"
+ android:layout_width="128dp" android:paddingStart="25dp" android:paddingEnd="25dp"
android:layout_height="match_parent"
android:layout_marginStart="40dp"
android:src="@drawable/ic_sysbar_lights_out_dot_small"
@@ -120,14 +120,14 @@
android:layout_weight="0"
/>
<ImageView
- android:layout_width="128dp" android:paddingLeft="25dp" android:paddingRight="25dp"
+ android:layout_width="128dp" android:paddingStart="25dp" android:paddingEnd="25dp"
android:layout_height="match_parent"
android:src="@drawable/ic_sysbar_lights_out_dot_large"
android:scaleType="center"
android:layout_weight="0"
/>
<ImageView
- android:layout_width="128dp" android:paddingLeft="25dp" android:paddingRight="25dp"
+ android:layout_width="128dp" android:paddingStart="25dp" android:paddingEnd="25dp"
android:layout_marginEnd="40dp"
android:layout_height="match_parent"
android:src="@drawable/ic_sysbar_lights_out_dot_small"
@@ -195,7 +195,7 @@
android:layout_weight="1"
/>
<com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/back"
- android:layout_width="162dp" android:paddingLeft="42dp" android:paddingRight="42dp"
+ android:layout_width="162dp" android:paddingStart="42dp" android:paddingEnd="42dp"
android:layout_height="match_parent"
android:src="@drawable/ic_sysbar_back"
systemui:keyCode="4"
@@ -204,7 +204,7 @@
android:contentDescription="@string/accessibility_back"
/>
<com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/home"
- android:layout_width="162dp" android:paddingLeft="42dp" android:paddingRight="42dp"
+ android:layout_width="162dp" android:paddingStart="42dp" android:paddingEnd="42dp"
android:layout_height="match_parent"
android:src="@drawable/ic_sysbar_home"
systemui:keyCode="3"
@@ -214,7 +214,7 @@
android:contentDescription="@string/accessibility_home"
/>
<com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/recent_apps"
- android:layout_width="162dp" android:paddingLeft="42dp" android:paddingRight="42dp"
+ android:layout_width="162dp" android:paddingStart="42dp" android:paddingEnd="42dp"
android:layout_height="match_parent"
android:src="@drawable/ic_sysbar_recent"
android:layout_weight="0"
@@ -253,7 +253,7 @@
android:layout_weight="1"
/>
<ImageView
- android:layout_width="162dp" android:paddingLeft="42dp" android:paddingRight="42dp"
+ android:layout_width="162dp" android:paddingStart="42dp" android:paddingEnd="42dp"
android:layout_height="match_parent"
android:layout_marginStart="40dp"
android:src="@drawable/ic_sysbar_lights_out_dot_small"
@@ -261,14 +261,14 @@
android:layout_weight="0"
/>
<ImageView
- android:layout_width="162dp" android:paddingLeft="42dp" android:paddingRight="42dp"
+ android:layout_width="162dp" android:paddingStart="42dp" android:paddingEnd="42dp"
android:layout_height="match_parent"
android:src="@drawable/ic_sysbar_lights_out_dot_large"
android:scaleType="center"
android:layout_weight="0"
/>
<ImageView
- android:layout_width="162dp" android:paddingLeft="42dp" android:paddingRight="42dp"
+ android:layout_width="162dp" android:paddingStart="42dp" android:paddingEnd="42dp"
android:layout_marginEnd="40dp"
android:layout_height="match_parent"
android:src="@drawable/ic_sysbar_lights_out_dot_small"
diff --git a/packages/SystemUI/res/layout/compat_mode_help.xml b/packages/SystemUI/res/layout/compat_mode_help.xml
index c2ed78e..566d07d 100644
--- a/packages/SystemUI/res/layout/compat_mode_help.xml
+++ b/packages/SystemUI/res/layout/compat_mode_help.xml
@@ -52,7 +52,7 @@
android:background="@drawable/compat_mode_help_divider_bottom"
android:layout_marginBottom="55dp"
android:layout_marginEnd="80dp"
- android:layout_alignLeft="@id/header"
+ android:layout_alignStart="@id/header"
android:layout_alignParentBottom="true"
>
<ImageView
@@ -82,7 +82,7 @@
android:id="@+id/button"
android:layout_width="208dp"
android:layout_height="48dp"
- android:layout_alignLeft="@id/header"
+ android:layout_alignStart="@id/header"
android:layout_alignParentBottom="true"
android:layout_marginBottom="20dp"
android:textSize="28sp"
diff --git a/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml b/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml
index b547d99..a6f4e9b 100644
--- a/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml
+++ b/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml
@@ -24,7 +24,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
- android:paddingRight="10dp"
+ android:paddingEnd="10dp"
android:src="@drawable/ic_qs_brightness_auto_off"
/>
<com.android.systemui.settings.ToggleSlider
@@ -32,7 +32,7 @@
android:layout_width="0dp"
android:layout_height="40dp"
android:layout_weight="1"
- android:layout_marginRight="2dp"
+ android:layout_marginEnd="2dp"
android:layout_gravity="center_vertical"
systemui:text="@string/status_bar_settings_auto_brightness_label"
/>
diff --git a/packages/SystemUI/res/layout/status_bar.xml b/packages/SystemUI/res/layout/status_bar.xml
index 8805175..b27536d 100644
--- a/packages/SystemUI/res/layout/status_bar.xml
+++ b/packages/SystemUI/res/layout/status_bar.xml
@@ -34,7 +34,7 @@
android:id="@+id/notification_lights_out"
android:layout_width="@dimen/status_bar_icon_size"
android:layout_height="match_parent"
- android:paddingLeft="6dip"
+ android:paddingStart="6dip"
android:paddingBottom="2dip"
android:src="@drawable/ic_sysbar_lights_out_dot_small"
android:scaleType="center"
@@ -44,8 +44,8 @@
<LinearLayout android:id="@+id/status_bar_contents"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:paddingLeft="6dip"
- android:paddingRight="6dip"
+ android:paddingStart="6dip"
+ android:paddingEnd="6dip"
android:orientation="horizontal"
>
@@ -86,7 +86,7 @@
android:id="@+id/signal_battery_cluster"
android:layout_width="wrap_content"
android:layout_height="match_parent"
- android:paddingLeft="2dp"
+ android:paddingStart="2dp"
android:orientation="horizontal"
android:gravity="center"
>
@@ -99,7 +99,7 @@
android:id="@+id/battery"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
- android:paddingLeft="4dip"
+ android:paddingStart="4dip"
/>
</LinearLayout>
@@ -109,7 +109,7 @@
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:singleLine="true"
- android:paddingLeft="6dip"
+ android:paddingStart="6dip"
android:gravity="center_vertical|start"
/>
</LinearLayout>
@@ -118,7 +118,7 @@
<LinearLayout android:id="@+id/ticker"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:paddingLeft="6dip"
+ android:paddingStart="6dip"
android:animationCache="false"
android:orientation="horizontal" >
<ImageSwitcher android:id="@+id/tickerIcon"
@@ -142,7 +142,7 @@
android:layout_weight="1"
android:layout_height="wrap_content"
android:paddingTop="2dip"
- android:paddingRight="10dip">
+ android:paddingEnd="10dip">
<TextView
android:textAppearance="@style/TextAppearance.StatusBar.PhoneTicker"
android:layout_width="match_parent"
diff --git a/packages/SystemUI/res/layout/status_bar_expanded_header.xml b/packages/SystemUI/res/layout/status_bar_expanded_header.xml
index 54c63f8..9aa7cfd 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded_header.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded_header.xml
@@ -30,8 +30,8 @@
android:id="@+id/datetime"
android:layout_width="wrap_content"
android:layout_height="match_parent"
- android:paddingLeft="8dp"
- android:paddingRight="8dp"
+ android:paddingStart="8dp"
+ android:paddingEnd="8dp"
android:background="@drawable/ic_notify_button_bg"
android:enabled="false"
>
diff --git a/packages/SystemUI/res/layout/status_bar_help.xml b/packages/SystemUI/res/layout/status_bar_help.xml
index 3c004ee..f638767 100644
--- a/packages/SystemUI/res/layout/status_bar_help.xml
+++ b/packages/SystemUI/res/layout/status_bar_help.xml
@@ -22,8 +22,8 @@
xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/status_bar_cling"
- android:paddingLeft="40dp"
- android:paddingRight="40dp"
+ android:paddingStart="40dp"
+ android:paddingEnd="40dp"
android:background="#DD000000"
android:focusable="true"
android:orientation="vertical"
@@ -56,8 +56,8 @@
style="@style/ClingButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:paddingLeft="50dp"
- android:paddingRight="50dp"
+ android:paddingStart="50dp"
+ android:paddingEnd="50dp"
android:text="@android:string/ok" />
</LinearLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/status_bar_notification_row.xml b/packages/SystemUI/res/layout/status_bar_notification_row.xml
index 2a93a2b..7a5ff3c 100644
--- a/packages/SystemUI/res/layout/status_bar_notification_row.xml
+++ b/packages/SystemUI/res/layout/status_bar_notification_row.xml
@@ -20,8 +20,8 @@
android:gravity="end"
android:layout_marginEnd="-80dp"
android:background="@null"
- android:paddingRight="8dp"
- android:paddingLeft="8dp"
+ android:paddingEnd="8dp"
+ android:paddingStart="8dp"
/>
<com.android.systemui.statusbar.LatestItemView android:id="@+id/content"
diff --git a/packages/SystemUI/res/layout/status_bar_toggle_slider.xml b/packages/SystemUI/res/layout/status_bar_toggle_slider.xml
index e3cd704..834cc2c 100644
--- a/packages/SystemUI/res/layout/status_bar_toggle_slider.xml
+++ b/packages/SystemUI/res/layout/status_bar_toggle_slider.xml
@@ -36,15 +36,15 @@
android:layout_toEndOf="@id/toggle"
android:layout_centerVertical="true"
android:layout_alignParentEnd="true"
- android:paddingLeft="20dp"
- android:paddingRight="20dp"
+ android:paddingStart="20dp"
+ android:paddingEnd="20dp"
/>
<TextView
android:id="@+id/label"
android:layout_width="0dp"
android:layout_height="wrap_content"
- android:layout_alignLeft="@id/toggle"
- android:layout_alignRight="@id/toggle"
+ android:layout_alignStart="@id/toggle"
+ android:layout_alignEnd="@id/toggle"
android:layout_centerVertical="true"
android:gravity="center"
android:paddingTop="26dp"
diff --git a/packages/SystemUI/res/layout/system_bar.xml b/packages/SystemUI/res/layout/system_bar.xml
index ac62702..28c9dc0 100644
--- a/packages/SystemUI/res/layout/system_bar.xml
+++ b/packages/SystemUI/res/layout/system_bar.xml
@@ -91,8 +91,8 @@
<com.android.systemui.statusbar.policy.EventHole android:id="@+id/fake_space_bar"
android:layout_height="match_parent"
android:layout_width="0dp"
- android:paddingLeft="8dip"
- android:paddingRight="8dip"
+ android:paddingStart="8dip"
+ android:paddingEnd="8dip"
android:layout_toEndOf="@+id/navigationArea"
android:layout_toStartOf="@+id/notificationArea"
android:visibility="gone"
diff --git a/packages/SystemUI/res/layout/system_bar_compat_mode_panel.xml b/packages/SystemUI/res/layout/system_bar_compat_mode_panel.xml
index a33741e..9ad9e05 100644
--- a/packages/SystemUI/res/layout/system_bar_compat_mode_panel.xml
+++ b/packages/SystemUI/res/layout/system_bar_compat_mode_panel.xml
@@ -22,7 +22,7 @@
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:paddingBottom="@dimen/panel_float"
- android:paddingRight="20dp"
+ android:paddingEnd="20dp"
>
<RadioGroup android:id="@+id/compat_mode_radio_group"
android:background="@*android:drawable/dialog_full_holo_dark"
diff --git a/packages/SystemUI/res/layout/system_bar_input_methods_item.xml b/packages/SystemUI/res/layout/system_bar_input_methods_item.xml
index 710406c..1a95ec1 100644
--- a/packages/SystemUI/res/layout/system_bar_input_methods_item.xml
+++ b/packages/SystemUI/res/layout/system_bar_input_methods_item.xml
@@ -24,8 +24,8 @@
android:minHeight="?android:attr/listPreferredItemHeight"
android:background="@drawable/status_bar_item_background"
android:orientation="vertical"
- android:paddingRight="6dip"
- android:paddingLeft="6dip"
+ android:paddingEnd="6dip"
+ android:paddingStart="6dip"
android:paddingTop="5dip"
android:paddingBottom="5dip"
android:gravity="center_vertical">
@@ -89,8 +89,8 @@
android:layout_height="match_parent"
android:layout_marginStart="5dip"
android:layout_gravity="center_vertical"
- android:paddingRight="10dip"
- android:paddingLeft="10dip"
+ android:paddingEnd="10dip"
+ android:paddingStart="10dip"
android:src="@drawable/ic_sysbar_quicksettings"
android:visibility="visible"
android:clickable="true"
diff --git a/packages/SystemUI/res/layout/system_bar_input_methods_panel.xml b/packages/SystemUI/res/layout/system_bar_input_methods_panel.xml
index ecc4f1e..547f937 100644
--- a/packages/SystemUI/res/layout/system_bar_input_methods_panel.xml
+++ b/packages/SystemUI/res/layout/system_bar_input_methods_panel.xml
@@ -57,8 +57,8 @@
android:minHeight="?android:attr/listPreferredItemHeight"
android:background="?android:attr/selectableItemBackground"
android:orientation="vertical"
- android:paddingRight="6dip"
- android:paddingLeft="30dip"
+ android:paddingEnd="6dip"
+ android:paddingStart="30dip"
android:paddingTop="5dip"
android:paddingBottom="5dip"
android:gravity="center_vertical"
@@ -103,8 +103,8 @@
android:minHeight="?android:attr/listPreferredItemHeight"
android:background="?android:attr/selectableItemBackground"
android:orientation="vertical"
- android:paddingRight="6dip"
- android:paddingLeft="30dip"
+ android:paddingEnd="6dip"
+ android:paddingStart="30dip"
android:paddingTop="5dip"
android:paddingBottom="5dip"
android:gravity="center_vertical"
diff --git a/packages/SystemUI/res/layout/system_bar_notification_area.xml b/packages/SystemUI/res/layout/system_bar_notification_area.xml
index 51ffda7..2fd91ef 100644
--- a/packages/SystemUI/res/layout/system_bar_notification_area.xml
+++ b/packages/SystemUI/res/layout/system_bar_notification_area.xml
@@ -84,7 +84,7 @@
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:singleLine="true"
- android:paddingLeft="6dip"
+ android:paddingStart="6dip"
android:layout_marginEnd="8dip"
android:gravity="center_vertical|start"
/>
@@ -119,14 +119,14 @@
android:id="@+id/bluetooth"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
- android:paddingLeft="4dip"
+ android:paddingStart="4dip"
android:visibility="gone"
/>
<ImageView
android:id="@+id/battery"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
- android:paddingLeft="4dip"
+ android:paddingStart="4dip"
/>
</LinearLayout>
</LinearLayout>
diff --git a/packages/SystemUI/res/layout/system_bar_notification_panel_title.xml b/packages/SystemUI/res/layout/system_bar_notification_panel_title.xml
index 97f774a..d08fbce 100644
--- a/packages/SystemUI/res/layout/system_bar_notification_panel_title.xml
+++ b/packages/SystemUI/res/layout/system_bar_notification_panel_title.xml
@@ -23,9 +23,9 @@
android:layout_height="wrap_content"
android:clickable="true"
android:orientation="vertical"
- android:paddingLeft="26dp"
+ android:paddingStart="26dp"
android:paddingTop="14dp"
- android:paddingRight="26dp"
+ android:paddingEnd="26dp"
>
<TableLayout
@@ -52,7 +52,7 @@
android:id="@+id/bluetooth"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
- android:paddingRight="16dp"
+ android:paddingEnd="16dp"
android:visibility="gone"
android:contentDescription="@null"
android:layout_gravity="center_vertical"
@@ -65,7 +65,7 @@
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_gravity="center_vertical"
- android:paddingRight="6dp"
+ android:paddingEnd="6dp"
>
<ImageView
@@ -89,7 +89,7 @@
android:layout_gravity="start|center_vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:paddingRight="12dp"
+ android:paddingEnd="12dp"
android:singleLine="true"
android:ellipsize="end"
android:text="@string/status_bar_settings_settings_button"
@@ -101,7 +101,7 @@
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_gravity="center_vertical"
- android:paddingRight="6dp"
+ android:paddingEnd="6dp"
>
<ImageView
@@ -125,7 +125,7 @@
android:layout_gravity="start|center_vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:paddingRight="12dp"
+ android:paddingEnd="12dp"
android:singleLine="true"
android:ellipsize="end"
android:text="@string/status_bar_settings_settings_button"
@@ -138,7 +138,7 @@
android:scaleType="centerInside"
android:layout_gravity="center_vertical"
android:layout_alignBaseline="@id/wifi_signal"
- android:paddingRight="6dp"
+ android:paddingEnd="6dp"
android:contentDescription="@null"
/>
@@ -148,7 +148,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="start|center_vertical"
- android:paddingRight="2dp"
+ android:paddingEnd="2dp"
android:singleLine="true"
android:text="@string/status_bar_settings_settings_button"
/>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index f0b1d7e..9f54573 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -407,6 +407,7 @@
mSystemIconArea = (LinearLayout) mStatusBarView.findViewById(R.id.system_icon_area);
mStatusIcons = (LinearLayout)mStatusBarView.findViewById(R.id.statusIcons);
mNotificationIcons = (IconMerger)mStatusBarView.findViewById(R.id.notificationIcons);
+ mMoreIcon = mStatusBarView.findViewById(R.id.moreIcon);
mNotificationIcons.setOverflowIndicator(mMoreIcon);
mStatusBarContents = (LinearLayout)mStatusBarView.findViewById(R.id.status_bar_contents);
mTickerView = mStatusBarView.findViewById(R.id.ticker);
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardTransportControlView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardTransportControlView.java
index ffa88d5..fda47d5 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardTransportControlView.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardTransportControlView.java
@@ -250,6 +250,15 @@
}
@Override
+ protected void onSizeChanged (int w, int h, int oldw, int oldh) {
+ if (mAttached) {
+ int dim = Math.min(512, Math.max(w, h));
+ if (DEBUG) Log.v(TAG, "TCV uses bitmap size=" + dim);
+ mAudioManager.remoteControlDisplayUsesBitmapSize(mIRCD, dim, dim);
+ }
+ }
+
+ @Override
public void onDetachedFromWindow() {
if (DEBUG) Log.v(TAG, "onDetachFromWindow()");
super.onDetachedFromWindow();
diff --git a/preloaded-classes b/preloaded-classes
index 10c5c9e..126dd15 100644
--- a/preloaded-classes
+++ b/preloaded-classes
@@ -199,16 +199,14 @@
android.app.backup.FileBackupHelperBase
android.app.backup.FullBackup
android.appwidget.AppWidgetManager
-android.bluetooth.BluetoothAudioGateway
android.bluetooth.BluetoothSocket
-android.bluetooth.HeadsetBase
android.bluetooth.IBluetooth
android.bluetooth.IBluetooth$Stub
android.bluetooth.IBluetoothA2dp
android.bluetooth.IBluetoothA2dp$Stub
android.content.AbstractThreadedSyncAdapter
android.content.AbstractThreadedSyncAdapter$ISyncAdapterImpl
-undroid.content.AbstractThreadedSyncAdapter$SyncThread
+android.content.AbstractThreadedSyncAdapter$SyncThread
android.content.BroadcastReceiver
android.content.BroadcastReceiver$PendingResult
android.content.ComponentCallbacks
@@ -737,9 +735,6 @@
android.provider.Settings$Secure
android.provider.Settings$System
android.renderscript.RenderScript
-android.server.BluetoothA2dpService
-android.server.BluetoothEventLoop
-android.server.BluetoothService
android.telephony.PhoneNumberUtils
android.telephony.TelephonyManager
android.text.AndroidBidi
@@ -844,7 +839,6 @@
android.util.FinitePool
android.util.FloatMath
android.util.FloatProperty
-android.util.LocaleUtil
android.util.Log
android.util.Log$1
android.util.Log$TerribleFailureHandler
@@ -1022,7 +1016,6 @@
android.view.ViewRootImpl$InputMethodCallback
android.view.ViewRootImpl$InvalidateOnAnimationRunnable
android.view.ViewRootImpl$QueuedInputEvent
-android.view.ViewRootImpl$ResizedInfo
android.view.ViewRootImpl$RunQueue
android.view.ViewRootImpl$RunQueue$HandlerAction
android.view.ViewRootImpl$TrackballAxis
@@ -1042,7 +1035,6 @@
android.view.ViewTreeObserver$OnTouchModeChangeListener
android.view.Window
android.view.Window$Callback
-android.view.Window$LocalWindowManager
android.view.WindowLeaked
android.view.WindowManager
android.view.WindowManager$LayoutParams
@@ -1050,7 +1042,6 @@
android.view.WindowManagerGlobal
android.view.WindowManagerGlobal$1
android.view.WindowManagerImpl
-android.view.WindowManagerImpl$CompatModeWrapper
android.view.accessibility.AccessibilityEvent
android.view.accessibility.AccessibilityEventSource
android.view.accessibility.AccessibilityManager
@@ -1843,7 +1834,6 @@
java.text.DateFormat
java.text.DateFormatSymbols
java.text.DecimalFormat
-java.text.DecimalFormat$1
java.text.DecimalFormatSymbols
java.text.FieldPosition
java.text.Format
@@ -1995,7 +1985,6 @@
java.util.concurrent.Future
java.util.concurrent.FutureTask
java.util.concurrent.FutureTask$WaitNode
-java.util.concurrent.FutureTask$Sync
java.util.concurrent.LinkedBlockingQueue
java.util.concurrent.LinkedBlockingQueue$Node
java.util.concurrent.RejectedExecutionHandler
@@ -2015,7 +2004,6 @@
java.util.concurrent.atomic.AtomicBoolean
java.util.concurrent.atomic.AtomicInteger
java.util.concurrent.atomic.AtomicReference
-java.util.concurrent.atomic.UnsafeAccess
java.util.concurrent.locks.AbstractOwnableSynchronizer
java.util.concurrent.locks.AbstractQueuedSynchronizer
java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject
@@ -2034,7 +2022,6 @@
java.util.concurrent.locks.ReentrantReadWriteLock$Sync
java.util.concurrent.locks.ReentrantReadWriteLock$Sync$ThreadLocalHoldCounter
java.util.concurrent.locks.ReentrantReadWriteLock$WriteLock
-java.util.concurrent.locks.UnsafeAccess
java.util.jar.Attributes
java.util.jar.Attributes$Name
java.util.jar.InitManifest
@@ -2111,7 +2098,6 @@
javax.net.ssl.X509KeyManager
javax.net.ssl.X509TrustManager
javax.security.auth.x500.X500Principal
-libcore.icu.ErrorCode
libcore.icu.ICU
libcore.icu.LocaleData
libcore.icu.NativeBreakIterator
@@ -2122,7 +2108,7 @@
libcore.icu.NativeIDN
libcore.icu.NativeNormalizer
libcore.icu.NativePluralRules
-libcore.icu.TimeZones
+libcore.icu.TimeZoneNames
libcore.internal.StringPool
libcore.io.AsynchronousCloseMonitor
libcore.io.Base64
diff --git a/services/input/InputReader.cpp b/services/input/InputReader.cpp
index bc8df18..43d76bb 100644
--- a/services/input/InputReader.cpp
+++ b/services/input/InputReader.cpp
@@ -2788,6 +2788,8 @@
mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_SCREEN;
} else if (deviceTypeString == "touchPad") {
mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_PAD;
+ } else if (deviceTypeString == "touchNavigation") {
+ mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_NAVIGATION;
} else if (deviceTypeString == "pointer") {
mParameters.deviceType = Parameters::DEVICE_TYPE_POINTER;
} else if (deviceTypeString != "default") {
@@ -2832,6 +2834,9 @@
case Parameters::DEVICE_TYPE_TOUCH_PAD:
dump.append(INDENT4 "DeviceType: touchPad\n");
break;
+ case Parameters::DEVICE_TYPE_TOUCH_NAVIGATION:
+ dump.append(INDENT4 "DeviceType: touchNavigation\n");
+ break;
case Parameters::DEVICE_TYPE_POINTER:
dump.append(INDENT4 "DeviceType: pointer\n");
break;
@@ -2885,6 +2890,9 @@
if (hasStylus()) {
mSource |= AINPUT_SOURCE_STYLUS;
}
+ } else if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_NAVIGATION) {
+ mSource = AINPUT_SOURCE_TOUCH_NAVIGATION;
+ mDeviceMode = DEVICE_MODE_UNSCALED;
} else {
mSource = AINPUT_SOURCE_TOUCHPAD;
mDeviceMode = DEVICE_MODE_UNSCALED;
diff --git a/services/input/InputReader.h b/services/input/InputReader.h
index 61b21e2..c596b37 100644
--- a/services/input/InputReader.h
+++ b/services/input/InputReader.h
@@ -1192,6 +1192,7 @@
enum DeviceType {
DEVICE_TYPE_TOUCH_SCREEN,
DEVICE_TYPE_TOUCH_PAD,
+ DEVICE_TYPE_TOUCH_NAVIGATION,
DEVICE_TYPE_POINTER,
};
diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java
index 401a25f..328b503 100644
--- a/services/java/com/android/server/BackupManagerService.java
+++ b/services/java/com/android/server/BackupManagerService.java
@@ -78,6 +78,7 @@
import com.android.internal.backup.BackupConstants;
import com.android.internal.backup.IBackupTransport;
+import com.android.internal.backup.IObbBackupService;
import com.android.internal.backup.LocalTransport;
import com.android.server.PackageManagerBackupAgent.Metadata;
@@ -363,15 +364,17 @@
class FullBackupParams extends FullParams {
public boolean includeApks;
+ public boolean includeObbs;
public boolean includeShared;
public boolean allApps;
public boolean includeSystem;
public String[] packages;
- FullBackupParams(ParcelFileDescriptor output, boolean saveApks, boolean saveShared,
- boolean doAllApps, boolean doSystem, String[] pkgList) {
+ FullBackupParams(ParcelFileDescriptor output, boolean saveApks, boolean saveObbs,
+ boolean saveShared, boolean doAllApps, boolean doSystem, String[] pkgList) {
fd = output;
includeApks = saveApks;
+ includeObbs = saveObbs;
includeShared = saveShared;
allApps = doAllApps;
includeSystem = doSystem;
@@ -550,7 +553,7 @@
// similar to normal backup/restore.
FullBackupParams params = (FullBackupParams)msg.obj;
PerformFullBackupTask task = new PerformFullBackupTask(params.fd,
- params.observer, params.includeApks,
+ params.observer, params.includeApks, params.includeObbs,
params.includeShared, params.curPassword, params.encryptPassword,
params.allApps, params.includeSystem, params.packages, params.latch);
(new Thread(task)).start();
@@ -2306,13 +2309,132 @@
}
- // ----- Full backup to a file/socket -----
+ // ----- Full backup/restore to a file/socket -----
- class PerformFullBackupTask implements Runnable {
+ abstract class ObbServiceClient {
+ public IObbBackupService mObbService;
+ public void setObbBinder(IObbBackupService binder) {
+ mObbService = binder;
+ }
+ }
+
+ class FullBackupObbConnection implements ServiceConnection {
+ volatile IObbBackupService mService;
+
+ FullBackupObbConnection() {
+ mService = null;
+ }
+
+ public void establish() {
+ if (DEBUG) Slog.i(TAG, "Initiating bind of OBB service on " + this);
+ Intent obbIntent = new Intent().setComponent(new ComponentName(
+ "com.android.sharedstoragebackup",
+ "com.android.sharedstoragebackup.ObbBackupService"));
+ BackupManagerService.this.mContext.bindService(
+ obbIntent, this, Context.BIND_AUTO_CREATE);
+ }
+
+ public void tearDown() {
+ BackupManagerService.this.mContext.unbindService(this);
+ }
+
+ public boolean backupObbs(PackageInfo pkg, OutputStream out) {
+ boolean success = false;
+ waitForConnection();
+
+ ParcelFileDescriptor[] pipes = null;
+ try {
+ pipes = ParcelFileDescriptor.createPipe();
+ int token = generateToken();
+ prepareOperationTimeout(token, TIMEOUT_FULL_BACKUP_INTERVAL, null);
+ mService.backupObbs(pkg.packageName, pipes[1], token, mBackupManagerBinder);
+ routeSocketDataToOutput(pipes[0], out);
+ success = waitUntilOperationComplete(token);
+ } catch (Exception e) {
+ Slog.w(TAG, "Unable to back up OBBs for " + pkg, e);
+ } finally {
+ try {
+ out.flush();
+ if (pipes != null) {
+ if (pipes[0] != null) pipes[0].close();
+ if (pipes[1] != null) pipes[1].close();
+ }
+ } catch (IOException e) {
+ Slog.w(TAG, "I/O error closing down OBB backup", e);
+ }
+ }
+ return success;
+ }
+
+ public void restoreObbFile(String pkgName, ParcelFileDescriptor data,
+ long fileSize, int type, String path, long mode, long mtime,
+ int token, IBackupManager callbackBinder) {
+ waitForConnection();
+
+ try {
+ mService.restoreObbFile(pkgName, data, fileSize, type, path, mode, mtime,
+ token, callbackBinder);
+ } catch (Exception e) {
+ Slog.w(TAG, "Unable to restore OBBs for " + pkgName, e);
+ }
+ }
+
+ private void waitForConnection() {
+ synchronized (this) {
+ while (mService == null) {
+ if (DEBUG) Slog.i(TAG, "...waiting for OBB service binding...");
+ try {
+ this.wait();
+ } catch (InterruptedException e) { /* never interrupted */ }
+ }
+ if (DEBUG) Slog.i(TAG, "Connected to OBB service; continuing");
+ }
+ }
+
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ synchronized (this) {
+ mService = IObbBackupService.Stub.asInterface(service);
+ if (DEBUG) Slog.i(TAG, "OBB service connection " + mService
+ + " connected on " + this);
+ this.notifyAll();
+ }
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ synchronized (this) {
+ mService = null;
+ if (DEBUG) Slog.i(TAG, "OBB service connection disconnected on " + this);
+ this.notifyAll();
+ }
+ }
+
+ }
+
+ private void routeSocketDataToOutput(ParcelFileDescriptor inPipe, OutputStream out)
+ throws IOException {
+ FileInputStream raw = new FileInputStream(inPipe.getFileDescriptor());
+ DataInputStream in = new DataInputStream(raw);
+
+ byte[] buffer = new byte[32 * 1024];
+ int chunkTotal;
+ while ((chunkTotal = in.readInt()) > 0) {
+ while (chunkTotal > 0) {
+ int toRead = (chunkTotal > buffer.length) ? buffer.length : chunkTotal;
+ int nRead = in.read(buffer, 0, toRead);
+ out.write(buffer, 0, nRead);
+ chunkTotal -= nRead;
+ }
+ }
+ }
+
+ class PerformFullBackupTask extends ObbServiceClient implements Runnable {
ParcelFileDescriptor mOutputFile;
DeflaterOutputStream mDeflater;
IFullBackupRestoreObserver mObserver;
boolean mIncludeApks;
+ boolean mIncludeObbs;
boolean mIncludeShared;
boolean mAllApps;
final boolean mIncludeSystem;
@@ -2322,6 +2444,7 @@
AtomicBoolean mLatchObject;
File mFilesDir;
File mManifestFile;
+
class FullBackupRunner implements Runnable {
PackageInfo mPackage;
@@ -2377,12 +2500,13 @@
}
PerformFullBackupTask(ParcelFileDescriptor fd, IFullBackupRestoreObserver observer,
- boolean includeApks, boolean includeShared, String curPassword,
- String encryptPassword, boolean doAllApps, boolean doSystem, String[] packages,
- AtomicBoolean latch) {
+ boolean includeApks, boolean includeObbs, boolean includeShared,
+ String curPassword, String encryptPassword, boolean doAllApps,
+ boolean doSystem, String[] packages, AtomicBoolean latch) {
mOutputFile = fd;
mObserver = observer;
mIncludeApks = includeApks;
+ mIncludeObbs = includeObbs;
mIncludeShared = includeShared;
mAllApps = doAllApps;
mIncludeSystem = doSystem;
@@ -2405,9 +2529,12 @@
@Override
public void run() {
- List<PackageInfo> packagesToBackup = new ArrayList<PackageInfo>();
-
Slog.i(TAG, "--- Performing full-dataset backup ---");
+
+ List<PackageInfo> packagesToBackup = new ArrayList<PackageInfo>();
+ FullBackupObbConnection obbConnection = new FullBackupObbConnection();
+ obbConnection.establish(); // we'll want this later
+
sendStartBackup();
// doAllApps supersedes the package set if any
@@ -2557,6 +2684,15 @@
for (int i = 0; i < N; i++) {
pkg = packagesToBackup.get(i);
backupOnePackage(pkg, out);
+
+ // after the app's agent runs to handle its private filesystem
+ // contents, back up any OBB content it has on its behalf.
+ if (mIncludeObbs) {
+ boolean obbOkay = obbConnection.backupObbs(pkg, out);
+ if (!obbOkay) {
+ throw new RuntimeException("Failure writing OBB stack for " + pkg);
+ }
+ }
}
// Done!
@@ -2581,6 +2717,7 @@
mLatchObject.notifyAll();
}
sendEndBackup();
+ obbConnection.tearDown();
if (DEBUG) Slog.d(TAG, "Full backup pass complete.");
mWakelock.release();
}
@@ -2688,20 +2825,7 @@
// Now pull data from the app and stuff it into the compressor
try {
- FileInputStream raw = new FileInputStream(pipes[0].getFileDescriptor());
- DataInputStream in = new DataInputStream(raw);
-
- byte[] buffer = new byte[16 * 1024];
- int chunkTotal;
- while ((chunkTotal = in.readInt()) > 0) {
- while (chunkTotal > 0) {
- int toRead = (chunkTotal > buffer.length)
- ? buffer.length : chunkTotal;
- int nRead = in.read(buffer, 0, toRead);
- out.write(buffer, 0, nRead);
- chunkTotal -= nRead;
- }
- }
+ routeSocketDataToOutput(pipes[0], out);
} catch (IOException e) {
Slog.i(TAG, "Caught exception reading from agent", e);
}
@@ -2900,7 +3024,7 @@
ACCEPT_IF_APK
}
- class PerformFullRestoreTask implements Runnable {
+ class PerformFullRestoreTask extends ObbServiceClient implements Runnable {
ParcelFileDescriptor mInputFile;
String mCurrentPassword;
String mDecryptPassword;
@@ -2909,6 +3033,7 @@
IBackupAgent mAgent;
String mAgentPackage;
ApplicationInfo mTargetApp;
+ FullBackupObbConnection mObbConnection = null;
ParcelFileDescriptor[] mPipes = null;
long mBytes;
@@ -2937,6 +3062,7 @@
mAgent = null;
mAgentPackage = null;
mTargetApp = null;
+ mObbConnection = new FullBackupObbConnection();
// Which packages we've already wiped data on. We prepopulate this
// with a whitelist of packages known to be unclearable.
@@ -2980,6 +3106,7 @@
@Override
public void run() {
Slog.i(TAG, "--- Performing full-dataset restore ---");
+ mObbConnection.establish();
sendStartRestore();
// Are we able to restore shared-storage data?
@@ -3067,6 +3194,7 @@
mLatchObject.set(true);
mLatchObject.notifyAll();
}
+ mObbConnection.tearDown();
sendEndRestore();
Slog.d(TAG, "Full restore pass complete.");
mWakelock.release();
@@ -3319,22 +3447,30 @@
long toCopy = info.size;
final int token = generateToken();
try {
- if (DEBUG) Slog.d(TAG, "Invoking agent to restore file "
- + info.path);
prepareOperationTimeout(token, TIMEOUT_FULL_BACKUP_INTERVAL, null);
- // fire up the app's agent listening on the socket. If
- // the agent is running in the system process we can't
- // just invoke it asynchronously, so we provide a thread
- // for it here.
- if (mTargetApp.processName.equals("system")) {
- Slog.d(TAG, "system process agent - spinning a thread");
- RestoreFileRunnable runner = new RestoreFileRunnable(
- mAgent, info, mPipes[0], token);
- new Thread(runner).start();
+ if (info.domain.equals(FullBackup.OBB_TREE_TOKEN)) {
+ if (DEBUG) Slog.d(TAG, "Restoring OBB file for " + pkg
+ + " : " + info.path);
+ mObbConnection.restoreObbFile(pkg, mPipes[0],
+ info.size, info.type, info.path, info.mode,
+ info.mtime, token, mBackupManagerBinder);
} else {
- mAgent.doRestoreFile(mPipes[0], info.size, info.type,
- info.domain, info.path, info.mode, info.mtime,
- token, mBackupManagerBinder);
+ if (DEBUG) Slog.d(TAG, "Invoking agent to restore file "
+ + info.path);
+ // fire up the app's agent listening on the socket. If
+ // the agent is running in the system process we can't
+ // just invoke it asynchronously, so we provide a thread
+ // for it here.
+ if (mTargetApp.processName.equals("system")) {
+ Slog.d(TAG, "system process agent - spinning a thread");
+ RestoreFileRunnable runner = new RestoreFileRunnable(
+ mAgent, info, mPipes[0], token);
+ new Thread(runner).start();
+ } else {
+ mAgent.doRestoreFile(mPipes[0], info.size, info.type,
+ info.domain, info.path, info.mode, info.mtime,
+ token, mBackupManagerBinder);
+ }
}
} catch (IOException e) {
// couldn't dup the socket for a process-local restore
@@ -3342,7 +3478,7 @@
agentSuccess = false;
okay = false;
} catch (RemoteException e) {
- // whoops, remote agent went away. We'll eat the content
+ // whoops, remote entity went away. We'll eat the content
// ourselves, then, and not copy it over.
Slog.e(TAG, "Agent crashed during full restore");
agentSuccess = false;
@@ -3891,18 +4027,6 @@
slash = info.path.indexOf('/');
if (slash < 0) throw new IOException("Illegal semantic path in non-manifest " + info.path);
info.domain = info.path.substring(0, slash);
- // validate that it's one of the domains we understand
- if (!info.domain.equals(FullBackup.APK_TREE_TOKEN)
- && !info.domain.equals(FullBackup.DATA_TREE_TOKEN)
- && !info.domain.equals(FullBackup.DATABASE_TREE_TOKEN)
- && !info.domain.equals(FullBackup.ROOT_TREE_TOKEN)
- && !info.domain.equals(FullBackup.SHAREDPREFS_TREE_TOKEN)
- && !info.domain.equals(FullBackup.MANAGED_EXTERNAL_TREE_TOKEN)
- && !info.domain.equals(FullBackup.OBB_TREE_TOKEN)
- && !info.domain.equals(FullBackup.CACHE_TREE_TOKEN)) {
- throw new IOException("Unrecognized domain " + info.domain);
- }
-
info.path = info.path.substring(slash + 1);
}
}
@@ -4989,7 +5113,8 @@
// Run a *full* backup pass for the given package, writing the resulting data stream
// to the supplied file descriptor. This method is synchronous and does not return
// to the caller until the backup has been completed.
- public void fullBackup(ParcelFileDescriptor fd, boolean includeApks, boolean includeShared,
+ public void fullBackup(ParcelFileDescriptor fd, boolean includeApks,
+ boolean includeObbs, boolean includeShared,
boolean doAllApps, boolean includeSystem, String[] pkgList) {
mContext.enforceCallingPermission(android.Manifest.permission.BACKUP, "fullBackup");
@@ -5020,12 +5145,12 @@
}
if (DEBUG) Slog.v(TAG, "Requesting full backup: apks=" + includeApks
- + " shared=" + includeShared + " all=" + doAllApps
+ + " obb=" + includeObbs + " shared=" + includeShared + " all=" + doAllApps
+ " pkgs=" + pkgList);
Slog.i(TAG, "Beginning full backup...");
- FullBackupParams params = new FullBackupParams(fd, includeApks, includeShared,
- doAllApps, includeSystem, pkgList);
+ FullBackupParams params = new FullBackupParams(fd, includeApks, includeObbs,
+ includeShared, doAllApps, includeSystem, pkgList);
final int token = generateToken();
synchronized (mFullConfirmations) {
mFullConfirmations.put(token, params);
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index 3257d2c..c83a919 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -1413,11 +1413,11 @@
}
private boolean addRoute(LinkProperties p, RouteInfo r, boolean toDefaultTable) {
- return modifyRoute(p.getInterfaceName(), p, r, 0, ADD, toDefaultTable);
+ return modifyRoute(p, r, 0, ADD, toDefaultTable);
}
private boolean removeRoute(LinkProperties p, RouteInfo r, boolean toDefaultTable) {
- return modifyRoute(p.getInterfaceName(), p, r, 0, REMOVE, toDefaultTable);
+ return modifyRoute(p, r, 0, REMOVE, toDefaultTable);
}
private boolean addRouteToAddress(LinkProperties lp, InetAddress addr) {
@@ -1430,24 +1430,26 @@
private boolean modifyRouteToAddress(LinkProperties lp, InetAddress addr, boolean doAdd,
boolean toDefaultTable) {
+ String iface = lp.getInterfaceName();
RouteInfo bestRoute = RouteInfo.selectBestRoute(lp.getRoutes(), addr);
if (bestRoute == null) {
- bestRoute = RouteInfo.makeHostRoute(addr);
+ bestRoute = RouteInfo.makeHostRoute(addr, iface);
} else {
if (bestRoute.getGateway().equals(addr)) {
// if there is no better route, add the implied hostroute for our gateway
- bestRoute = RouteInfo.makeHostRoute(addr);
+ bestRoute = RouteInfo.makeHostRoute(addr, iface);
} else {
// if we will connect to this through another route, add a direct route
// to it's gateway
- bestRoute = RouteInfo.makeHostRoute(addr, bestRoute.getGateway());
+ bestRoute = RouteInfo.makeHostRoute(addr, bestRoute.getGateway(), iface);
}
}
- return modifyRoute(lp.getInterfaceName(), lp, bestRoute, 0, doAdd, toDefaultTable);
+ return modifyRoute(lp, bestRoute, 0, doAdd, toDefaultTable);
}
- private boolean modifyRoute(String ifaceName, LinkProperties lp, RouteInfo r, int cycleCount,
- boolean doAdd, boolean toDefaultTable) {
+ private boolean modifyRoute(LinkProperties lp, RouteInfo r, int cycleCount, boolean doAdd,
+ boolean toDefaultTable) {
+ String ifaceName = lp.getInterfaceName();
if ((ifaceName == null) || (lp == null) || (r == null)) {
if (DBG) log("modifyRoute got unexpected null: " + ifaceName + ", " + lp + ", " + r);
return false;
@@ -1463,13 +1465,15 @@
if (bestRoute != null) {
if (bestRoute.getGateway().equals(r.getGateway())) {
// if there is no better route, add the implied hostroute for our gateway
- bestRoute = RouteInfo.makeHostRoute(r.getGateway());
+ bestRoute = RouteInfo.makeHostRoute(r.getGateway(), ifaceName);
} else {
// if we will connect to our gateway through another route, add a direct
// route to it's gateway
- bestRoute = RouteInfo.makeHostRoute(r.getGateway(), bestRoute.getGateway());
+ bestRoute = RouteInfo.makeHostRoute(r.getGateway(),
+ bestRoute.getGateway(),
+ ifaceName);
}
- modifyRoute(ifaceName, lp, bestRoute, cycleCount+1, doAdd, toDefaultTable);
+ modifyRoute(lp, bestRoute, cycleCount+1, doAdd, toDefaultTable);
}
}
if (doAdd) {
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index 6ba5cff..01f7544 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/java/com/android/server/InputMethodManagerService.java
@@ -1243,6 +1243,10 @@
unbindCurrentMethodLocked(false, false);
return;
}
+ // Remove commands relating to the previous service. Otherwise WindowManagerService
+ // will reject the command because the token attached to these messages is invalid.
+ mCaller.removeMessages(MSG_SHOW_SOFT_INPUT);
+ mCaller.removeMessages(MSG_HIDE_SOFT_INPUT);
if (DEBUG) Slog.v(TAG, "Initiating attach with token: " + mCurToken);
executeOrSendMessage(mCurMethod, mCaller.obtainMessageOO(
MSG_ATTACH_TOKEN, mCurMethod, mCurToken));
diff --git a/services/java/com/android/server/NotificationManagerService.java b/services/java/com/android/server/NotificationManagerService.java
index 9f2685b..9e036d1 100644
--- a/services/java/com/android/server/NotificationManagerService.java
+++ b/services/java/com/android/server/NotificationManagerService.java
@@ -186,8 +186,14 @@
this.userid = userid;
}
+ boolean userMatches(StatusBarNotification sbn) {
+ if (this.userid == UserHandle.USER_ALL) return true;
+ int nid = sbn.getUserId();
+ return (nid == UserHandle.USER_ALL || nid == this.userid);
+ }
+
public void notifyPostedIfUserMatch(StatusBarNotification sbn) {
- if (this.userid != sbn.getUserId()) return;
+ if (!userMatches(sbn)) return;
try {
listener.onNotificationPosted(sbn);
} catch (RemoteException ex) {
@@ -196,7 +202,7 @@
}
public void notifyRemovedIfUserMatch(StatusBarNotification sbn) {
- if (this.userid != sbn.getUserId()) return;
+ if (!userMatches(sbn)) return;
try {
listener.onNotificationRemoved(sbn);
} catch (RemoteException ex) {
@@ -1249,9 +1255,6 @@
sendAccessibilityEvent(notification, pkg);
}
- // finally, keep some of this information around for later use
- mArchive.record(n);
-
notifyPostedLocked(r);
} else {
Slog.e(TAG, "Ignoring notification with icon==0: " + notification);
@@ -1466,6 +1469,9 @@
if (mLedNotification == r) {
mLedNotification = null;
}
+
+ // Save it for users of getHistoricalNotifications()
+ mArchive.record(r.sbn);
}
/**
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index d8bcf2cd..6f092bf 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -3499,7 +3499,14 @@
} catch (RemoteException e) {
}
if (pkgUid == -1) {
- Slog.w(TAG, "Invalid packageName:" + packageName);
+ Slog.w(TAG, "Invalid packageName: " + packageName);
+ if (observer != null) {
+ try {
+ observer.onRemoveCompleted(packageName, false);
+ } catch (RemoteException e) {
+ Slog.i(TAG, "Observer no longer exists.");
+ }
+ }
return false;
}
if (uid == pkgUid || checkComponentPermission(
diff --git a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
index 4ae013b..f955f4f 100644
--- a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
@@ -62,13 +62,17 @@
private static final String MOBILE_IFACE = "rmnet3";
private static final String WIFI_IFACE = "wlan6";
- private static final RouteInfo MOBILE_ROUTE_V4 = RouteInfo.makeHostRoute(parse("10.0.0.33"));
- private static final RouteInfo MOBILE_ROUTE_V6 = RouteInfo.makeHostRoute(parse("fd00::33"));
+ private static final RouteInfo MOBILE_ROUTE_V4 = RouteInfo.makeHostRoute(parse("10.0.0.33"),
+ MOBILE_IFACE);
+ private static final RouteInfo MOBILE_ROUTE_V6 = RouteInfo.makeHostRoute(parse("fd00::33"),
+ MOBILE_IFACE);
- private static final RouteInfo WIFI_ROUTE_V4 = RouteInfo.makeHostRoute(
- parse("192.168.0.66"), parse("192.168.0.1"));
- private static final RouteInfo WIFI_ROUTE_V6 = RouteInfo.makeHostRoute(
- parse("fd00::66"), parse("fd00::"));
+ private static final RouteInfo WIFI_ROUTE_V4 = RouteInfo.makeHostRoute(parse("192.168.0.66"),
+ parse("192.168.0.1"),
+ WIFI_IFACE);
+ private static final RouteInfo WIFI_ROUTE_V6 = RouteInfo.makeHostRoute(parse("fd00::66"),
+ parse("fd00::"),
+ WIFI_IFACE);
private INetworkManagementService mNetManager;
private INetworkStatsService mStatsService;
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/PathsCacheActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/PathsCacheActivity.java
index 9ab2a86..9f97311 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/PathsCacheActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/PathsCacheActivity.java
@@ -33,6 +33,7 @@
private Path mPath;
private final Random mRandom = new Random();
+ @SuppressWarnings("MismatchedQueryAndUpdateOfCollection")
private final ArrayList<Path> mPathList = new ArrayList<Path>();
@Override
@@ -45,19 +46,32 @@
setContentView(view);
}
- private Path makePath() {
+ private static Path makePath() {
Path path = new Path();
buildPath(path);
return path;
}
- private void buildPath(Path path) {
+ private static void buildPath(Path path) {
path.moveTo(0.0f, 0.0f);
path.cubicTo(0.0f, 0.0f, 100.0f, 150.0f, 100.0f, 200.0f);
path.cubicTo(100.0f, 200.0f, 50.0f, 300.0f, -80.0f, 200.0f);
path.cubicTo(-80.0f, 200.0f, 100.0f, 200.0f, 200.0f, 0.0f);
}
+ private static Path makeLargePath() {
+ Path path = new Path();
+ buildLargePath(path);
+ return path;
+ }
+
+ private static void buildLargePath(Path path) {
+ path.moveTo(0.0f, 0.0f);
+ path.cubicTo(0.0f, 0.0f, 10000.0f, 15000.0f, 10000.0f, 20000.0f);
+ path.cubicTo(10000.0f, 20000.0f, 5000.0f, 30000.0f, -8000.0f, 20000.0f);
+ path.cubicTo(-8000.0f, 20000.0f, 10000.0f, 20000.0f, 20000.0f, 0.0f);
+ }
+
public class PathsView extends View {
private final Paint mMediumPaint;
@@ -97,6 +111,9 @@
int r = mRandom.nextInt(10);
if (r == 5 || r == 3) {
mPathList.add(path);
+ } else if (r == 7) {
+ path = makeLargePath();
+ mPathList.add(path);
}
canvas.save();
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/BWFilter.java b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/BWFilter.java
index 4fd63bf..64be4aa 100644
--- a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/BWFilter.java
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/BWFilter.java
@@ -18,7 +18,6 @@
import java.lang.Math;
-import android.renderscript.Allocation;
public class BWFilter extends TestBase {
private ScriptC_bwfilter mScript;
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java
index d2139ea..8cf46c2 100644
--- a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java
@@ -153,20 +153,23 @@
// more work is ready. Either way, display the result.
@Override
public void handleMessage(Message msg) {
- mTest.updateBitmap(mBitmapOut);
- mDisplayView.invalidate();
-
boolean doTest = false;
synchronized(this) {
+ if (mRS == null) {
+ return;
+ }
+ mTest.updateBitmap(mBitmapOut);
+ mDisplayView.invalidate();
if (mRunCount > 0) {
mRunCount--;
if (mRunCount > 0) {
doTest = true;
}
}
- }
- if (doTest) {
- mTest.runTestSendMessage();
+
+ if (doTest) {
+ mTest.runTestSendMessage();
+ }
}
}
@@ -382,11 +385,7 @@
}
};
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
-
+ void init() {
mBitmapIn = loadBitmap(R.drawable.img1600x1067);
mBitmapIn2 = loadBitmap(R.drawable.img1600x1067b);
mBitmapOut = Bitmap.createBitmap(mBitmapIn.getWidth(), mBitmapIn.getHeight(),
@@ -434,6 +433,50 @@
changeTest(TestName.LEVELS_VEC3_RELAXED);
}
+ void cleanup() {
+ synchronized(this) {
+ RenderScript rs = mRS;
+ mRS = null;
+ while(mDoingBenchmark) {
+ try {
+ Thread.sleep(1, 0);
+ } catch(InterruptedException e) {
+ }
+
+ }
+ rs.destroy();
+ }
+
+ mInPixelsAllocation = null;
+ mInPixelsAllocation2 = null;
+ mOutPixelsAllocation = null;
+ mBitmapIn = null;
+ mBitmapIn2 = null;
+ mBitmapOut = null;
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.main);
+
+ init();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+
+ cleanup();
+ }
+
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+
+ init();
+ }
private Bitmap loadBitmap(int resource) {
final BitmapFactory.Options options = new BitmapFactory.Options();
@@ -476,8 +519,13 @@
changeTest(TestName.LEVELS_VEC3_RELAXED);
}
+
+
// For benchmark test
public float getBenchmark() {
+ if (mRS == null) {
+ return 0;
+ }
mDoingBenchmark = true;
mTest.setupBenchmark();
@@ -504,7 +552,6 @@
mTest.exitBenchmark();
mDoingBenchmark = false;
-
return ft;
}
}
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/blend.rs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/blend.rs
index 87b56f7..9ec1246 100644
--- a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/blend.rs
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/blend.rs
@@ -12,8 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.image)
+#include "ip.rsh"
uchar alpha = 0x0;
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/bwfilter.rs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/bwfilter.rs
index 03e5a79..e706d44 100644
--- a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/bwfilter.rs
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/bwfilter.rs
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.image)
+#include "ip.rsh"
//#pragma rs_fp_relaxed
static float sr = 0.f;
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/colorcube.rs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/colorcube.rs
index fda0d1e..4f1e73e 100644
--- a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/colorcube.rs
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/colorcube.rs
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.image)
+#include "ip.rsh"
#pragma rs_fp_relaxed
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/colormatrix.fs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/colormatrix.fs
index ba8711b..86fb248 100644
--- a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/colormatrix.fs
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/colormatrix.fs
@@ -14,10 +14,7 @@
* limitations under the License.
*/
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.image)
-#pragma rs_fp_relaxed
-
+#include "ip.rsh"
static rs_matrix4x4 Mat;
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/contrast.rs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/contrast.rs
index 5fd7be1..d3743d3 100644
--- a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/contrast.rs
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/contrast.rs
@@ -14,9 +14,7 @@
* limitations under the License.
*/
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.image)
-#pragma rs_fp_full
+#include "ip.rsh"
static float brightM = 0.f;
static float brightC = 0.f;
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/convolve3x3.fs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/convolve3x3.fs
index 772503f..177e86e 100644
--- a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/convolve3x3.fs
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/convolve3x3.fs
@@ -14,9 +14,7 @@
* limitations under the License.
*/
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.image)
-#pragma rs_fp_relaxed
+#include "ip.rsh"
int32_t gWidth;
int32_t gHeight;
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/convolve5x5.fs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/convolve5x5.fs
index a916bfb..922a593 100644
--- a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/convolve5x5.fs
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/convolve5x5.fs
@@ -14,9 +14,7 @@
* limitations under the License.
*/
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.image)
-#pragma rs_fp_relaxed
+#include "ip.rsh"
int32_t gWidth;
int32_t gHeight;
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/copy.fs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/copy.fs
index 5f03483..6595874 100644
--- a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/copy.fs
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/copy.fs
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.image)
+#include "ip.rsh"
uchar4 __attribute__((kernel)) root(uchar4 v_in) {
return v_in;
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/exposure.rs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/exposure.rs
index adfae4a..0f05cb9 100644
--- a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/exposure.rs
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/exposure.rs
@@ -14,9 +14,7 @@
* limitations under the License.
*/
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.image)
-#pragma rs_fp_full
+#include "ip.rsh"
static float bright = 0.f;
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/fisheye_approx_full.rs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/fisheye_approx_full.rs
index 1ea37db..ed69ff4 100644
--- a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/fisheye_approx_full.rs
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/fisheye_approx_full.rs
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.image)
+#include "ip.rsh"
#include "fisheye_approx.rsh"
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/fisheye_approx_relaxed.fs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/fisheye_approx_relaxed.fs
index 3e76368..ed69ff4 100644
--- a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/fisheye_approx_relaxed.fs
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/fisheye_approx_relaxed.fs
@@ -14,9 +14,7 @@
* limitations under the License.
*/
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.image)
-#pragma rs_fp_relaxed
+#include "ip.rsh"
#include "fisheye_approx.rsh"
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/fisheye_full.rs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/fisheye_full.rs
index 20f27e2..f986b5d 100644
--- a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/fisheye_full.rs
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/fisheye_full.rs
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.image)
+#include "ip.rsh"
#include "fisheye.rsh"
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/fisheye_relaxed.fs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/fisheye_relaxed.fs
index dc3ffcb..f986b5d 100644
--- a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/fisheye_relaxed.fs
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/fisheye_relaxed.fs
@@ -14,9 +14,7 @@
* limitations under the License.
*/
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.image)
-#pragma rs_fp_relaxed
+#include "ip.rsh"
#include "fisheye.rsh"
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/grain.fs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/grain.fs
index 4ae095d..2e62cd7 100644
--- a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/grain.fs
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/grain.fs
@@ -14,9 +14,7 @@
* limitations under the License.
*/
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.image)
-#pragma rs_fp_relaxed
+#include "ip.rsh"
uchar __attribute__((kernel)) genRand() {
return (uchar)rsRand(0xff);
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/greyscale.fs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/greyscale.fs
index d419459..4e13072 100644
--- a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/greyscale.fs
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/greyscale.fs
@@ -14,9 +14,7 @@
* limitations under the License.
*/
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.image)
-#pragma rs_fp_relaxed
+#include "ip.rsh"
const static float3 gMonoMult = {0.299f, 0.587f, 0.114f};
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/levels_relaxed.rs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ip.rsh
similarity index 79%
copy from tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/levels_relaxed.rs
copy to tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ip.rsh
index ffdcfe3..01a3346 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/levels_relaxed.rs
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ip.rsh
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 The Android Open Source Project
+ * Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,8 +15,6 @@
*/
#pragma version(1)
-#pragma rs java_package_name(com.android.rs.image2)
-#pragma rs_fp_relaxed
+#pragma rs java_package_name(com.android.rs.image)
-#include "levels.rsh"
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/levels_full.rs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/levels_full.rs
index da6a291..28596ba 100644
--- a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/levels_full.rs
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/levels_full.rs
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.image)
+#include "ip.rsh"
#include "levels.rsh"
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/levels_relaxed.fs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/levels_relaxed.fs
index b115445..28596ba 100644
--- a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/levels_relaxed.fs
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/levels_relaxed.fs
@@ -14,9 +14,7 @@
* limitations under the License.
*/
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.image)
-#pragma rs_fp_relaxed
+#include "ip.rsh"
#include "levels.rsh"
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/mandelbrot.rs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/mandelbrot.rs
index ac2061b..de0bd00 100644
--- a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/mandelbrot.rs
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/mandelbrot.rs
@@ -12,8 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.image)
+#include "ip.rsh"
uint32_t gMaxIteration = 500;
uint32_t gDimX = 1024;
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/shadows.rs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/shadows.rs
index 7ee3405..f6c149d 100644
--- a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/shadows.rs
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/shadows.rs
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.image)
+#include "ip.rsh"
//#pragma rs_fp_relaxed
static double shadowFilterMap[] = {
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/threshold.fs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/threshold.fs
index 86e155a..0b2c2e8 100644
--- a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/threshold.fs
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/threshold.fs
@@ -1,6 +1,20 @@
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.image)
-#pragma rs_fp_relaxed
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ip.rsh"
int height;
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vibrance.rs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vibrance.rs
index fae94a1..ad4de58 100644
--- a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vibrance.rs
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vibrance.rs
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.image)
+#include "ip.rsh"
float vibrance = 0.f;
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vignette_approx_full.rs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vignette_approx_full.rs
index c83c6e1..00cbbc4 100644
--- a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vignette_approx_full.rs
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vignette_approx_full.rs
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.image)
+#include "ip.rsh"
#include "vignette_approx.rsh"
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vignette_approx_relaxed.fs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vignette_approx_relaxed.fs
index 9120612..00cbbc4 100644
--- a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vignette_approx_relaxed.fs
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vignette_approx_relaxed.fs
@@ -14,9 +14,7 @@
* limitations under the License.
*/
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.image)
-#pragma rs_fp_relaxed
+#include "ip.rsh"
#include "vignette_approx.rsh"
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vignette_full.rs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vignette_full.rs
index 64942d9..8202c5c 100644
--- a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vignette_full.rs
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vignette_full.rs
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.image)
+#include "ip.rsh"
#include "vignette.rsh"
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vignette_relaxed.fs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vignette_relaxed.fs
index 8e47ea9..8202c5c 100644
--- a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vignette_relaxed.fs
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/vignette_relaxed.fs
@@ -14,9 +14,7 @@
* limitations under the License.
*/
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.image)
-#pragma rs_fp_relaxed
+#include "ip.rsh"
#include "vignette.rsh"
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/wbalance.rs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/wbalance.rs
index 8c825f2..6650671 100644
--- a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/wbalance.rs
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/wbalance.rs
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.image)
+#include "ip.rsh"
//#pragma rs_fp_relaxed
static int histR[256] = {0}, histG[256] = {0}, histB[256] = {0};
diff --git a/tests/RenderScriptTests/ImageProcessing2/Android.mk b/tests/RenderScriptTests/ImageProcessing2/Android.mk
index dc6c0d8..52966a3 100644
--- a/tests/RenderScriptTests/ImageProcessing2/Android.mk
+++ b/tests/RenderScriptTests/ImageProcessing2/Android.mk
@@ -26,8 +26,8 @@
LOCAL_PACKAGE_NAME := ImageProcessing2
LOCAL_SDK_VERSION := 8
-LOCAL_RENDERSCRIPT_TARGET_API := 17
-LOCAL_RENDERSCRIPT_COMPATIBILITY := 17
+LOCAL_RENDERSCRIPT_TARGET_API := 18
+LOCAL_RENDERSCRIPT_COMPATIBILITY := 18
LOCAL_RENDERSCRIPT_INCLUDES_OVERRIDE := $(TOPDIR)external/clang/lib/Headers \
$(TOPDIR)frameworks/rs/scriptc
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/colormatrix.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/BWFilter.java
similarity index 60%
copy from tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/colormatrix.rs
copy to tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/BWFilter.java
index e93bef3..4b19856 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/colormatrix.rs
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/BWFilter.java
@@ -14,25 +14,21 @@
* limitations under the License.
*/
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.image2)
-#pragma rs_fp_relaxed
+package com.android.rs.image2;
+
+import java.lang.Math;
-static rs_matrix4x4 Mat;
+public class BWFilter extends TestBase {
+ private ScriptC_bwfilter mScript;
-void init() {
- rsMatrixLoadIdentity(&Mat);
+ public void createTest(android.content.res.Resources res) {
+ mScript = new ScriptC_bwfilter(mRS);
+ }
+
+ public void runTest() {
+ mScript.invoke_prepareBwFilter(50, 50, 50);
+ mScript.forEach_bwFilterKernel(mInPixelsAllocation, mOutPixelsAllocation);
+ }
+
}
-
-void setMatrix(rs_matrix4x4 m) {
- Mat = m;
-}
-
-void root(const uchar4 *in, uchar4 *out) {
- float4 f = convert_float4(*in);
- f = rsMatrixMultiply(&Mat, f);
- f = clamp(f, 0.f, 255.f);
- *out = convert_uchar4(f);
-}
-
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Blend.java b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Blend.java
index ac02101..d81ba88 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Blend.java
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Blend.java
@@ -44,8 +44,10 @@
new AdapterView.OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
currentIntrinsic = pos;
- runTest();
- act.updateDisplay();
+ if (mRS != null) {
+ runTest();
+ act.updateDisplay();
+ }
}
public void onNothingSelected(AdapterView parent) {
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Blur25G.java b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Blur25G.java
new file mode 100644
index 0000000..19aa9f7
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Blur25G.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.image2;
+
+import java.lang.Math;
+
+import android.graphics.Bitmap;
+import android.support.v8.renderscript.*;
+import android.util.Log;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+public class Blur25G extends TestBase {
+ private final int MAX_RADIUS = 25;
+ private float mRadius = MAX_RADIUS;
+
+ private ScriptIntrinsicBlur mIntrinsic;
+
+ private ScriptC_greyscale mScript;
+ private Allocation mScratchPixelsAllocation1;
+ private Allocation mScratchPixelsAllocation2;
+
+
+ public Blur25G() {
+ }
+
+ public boolean onBar1Setup(SeekBar b, TextView t) {
+ t.setText("Radius");
+ b.setProgress(100);
+ return true;
+ }
+
+
+ public void onBar1Changed(int progress) {
+ mRadius = ((float)progress) / 100.0f * MAX_RADIUS;
+ if (mRadius <= 0.10f) {
+ mRadius = 0.10f;
+ }
+ mIntrinsic.setRadius(mRadius);
+ }
+
+
+ public void createTest(android.content.res.Resources res) {
+ int width = mInPixelsAllocation.getType().getX();
+ int height = mInPixelsAllocation.getType().getY();
+
+ Type.Builder tb = new Type.Builder(mRS, Element.U8(mRS));
+ tb.setX(width);
+ tb.setY(height);
+ mScratchPixelsAllocation1 = Allocation.createTyped(mRS, tb.create());
+ mScratchPixelsAllocation2 = Allocation.createTyped(mRS, tb.create());
+
+ mScript = new ScriptC_greyscale(mRS);
+ mScript.forEach_toU8(mInPixelsAllocation, mScratchPixelsAllocation1);
+
+ mIntrinsic = ScriptIntrinsicBlur.create(mRS, Element.U8(mRS));
+ mIntrinsic.setRadius(MAX_RADIUS);
+ mIntrinsic.setInput(mScratchPixelsAllocation1);
+ }
+
+ public void runTest() {
+ mIntrinsic.forEach(mScratchPixelsAllocation2);
+ }
+
+ public void setupBenchmark() {
+ mIntrinsic.setRadius(MAX_RADIUS);
+ }
+
+ public void exitBenchmark() {
+ mIntrinsic.setRadius(mRadius);
+ }
+
+ public void updateBitmap(Bitmap b) {
+ mScript.forEach_toU8_4(mScratchPixelsAllocation2, mOutPixelsAllocation);
+ mOutPixelsAllocation.copyTo(b);
+ }
+
+}
+
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/ColorCube.java b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/ColorCube.java
new file mode 100644
index 0000000..e960385
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/ColorCube.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.image2;
+
+import java.lang.Math;
+
+import android.support.v8.renderscript.*;
+import android.util.Log;
+
+public class ColorCube extends TestBase {
+ private Allocation mCube;
+ private ScriptC_colorcube mScript;
+ private ScriptIntrinsic3DLUT mIntrinsic;
+ private boolean mUseIntrinsic;
+
+ public ColorCube(boolean useIntrinsic) {
+ mUseIntrinsic = useIntrinsic;
+ }
+
+ private void initCube() {
+ final int sx = 32;
+ final int sy = 32;
+ final int sz = 16;
+
+ Type.Builder tb = new Type.Builder(mRS, Element.U8_4(mRS));
+ tb.setX(sx);
+ tb.setY(sy);
+ tb.setZ(sz);
+ Type t = tb.create();
+ mCube = Allocation.createTyped(mRS, t);
+
+ int dat[] = new int[sx * sy * sz];
+ for (int z = 0; z < sz; z++) {
+ for (int y = 0; y < sy; y++) {
+ for (int x = 0; x < sx; x++ ) {
+ int v = 0xff000000;
+ v |= (0xff * x / (sx - 1));
+ v |= (0xff * y / (sy - 1)) << 8;
+ v |= (0xff * z / (sz - 1)) << 16;
+ dat[z*sy*sx + y*sx + x] = v;
+ }
+ }
+ }
+
+ mCube.copyFromUnchecked(dat);
+ }
+
+ public void createTest(android.content.res.Resources res) {
+ mScript = new ScriptC_colorcube(mRS, res, R.raw.colorcube);
+ mIntrinsic = ScriptIntrinsic3DLUT.create(mRS, Element.U8_4(mRS));
+
+ initCube();
+ mScript.invoke_setCube(mCube);
+ mIntrinsic.setLUT(mCube);
+ }
+
+ public void runTest() {
+ if (mUseIntrinsic) {
+ mIntrinsic.forEach(mInPixelsAllocation, mOutPixelsAllocation);
+ } else {
+ mScript.forEach_root(mInPixelsAllocation, mOutPixelsAllocation);
+ }
+ }
+
+}
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/colormatrix.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Contrast.java
similarity index 61%
copy from tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/colormatrix.rs
copy to tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Contrast.java
index e93bef3..3ae5d2a 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/colormatrix.rs
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Contrast.java
@@ -14,25 +14,21 @@
* limitations under the License.
*/
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.image2)
-#pragma rs_fp_relaxed
+package com.android.rs.image2;
+
+import java.lang.Math;
-static rs_matrix4x4 Mat;
+public class Contrast extends TestBase {
+ private ScriptC_contrast mScript;
-void init() {
- rsMatrixLoadIdentity(&Mat);
+ public void createTest(android.content.res.Resources res) {
+ mScript = new ScriptC_contrast(mRS);
+ }
+
+ public void runTest() {
+ mScript.invoke_setBright(50.f);
+ mScript.forEach_contrast(mInPixelsAllocation, mOutPixelsAllocation);
+ }
+
}
-
-void setMatrix(rs_matrix4x4 m) {
- Mat = m;
-}
-
-void root(const uchar4 *in, uchar4 *out) {
- float4 f = convert_float4(*in);
- f = rsMatrixMultiply(&Mat, f);
- f = clamp(f, 0.f, 255.f);
- *out = convert_uchar4(f);
-}
-
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Exposure.java b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Exposure.java
new file mode 100644
index 0000000..deb6b46e
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Exposure.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.image2;
+
+import java.lang.Math;
+
+import android.support.v8.renderscript.*;
+
+public class Exposure extends TestBase {
+ private ScriptC_exposure mScript;
+
+ public void createTest(android.content.res.Resources res) {
+ mScript = new ScriptC_exposure(mRS);
+ }
+
+ public void runTest() {
+ mScript.invoke_setBright(50.f);
+ mScript.forEach_exposure(mInPixelsAllocation, mOutPixelsAllocation);
+ }
+
+}
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Greyscale.java b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Greyscale.java
index 2d85ae7..5b16e24 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Greyscale.java
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Greyscale.java
@@ -16,9 +16,6 @@
package com.android.rs.image2;
-import java.lang.Math;
-
-import android.support.v8.renderscript.*;
import android.util.Log;
public class Greyscale extends TestBase {
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/ImageProcessingActivity2.java b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/ImageProcessingActivity2.java
index 19bea43..4b0e2dd 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/ImageProcessingActivity2.java
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/ImageProcessingActivity2.java
@@ -47,12 +47,73 @@
public class ImageProcessingActivity2 extends Activity
implements SeekBar.OnSeekBarChangeListener {
private final String TAG = "Img";
- private final String RESULT_FILE = "image_processing_result.csv";
+ public final String RESULT_FILE = "image_processing_result.csv";
+
+ RenderScript mRS;
+ Allocation mInPixelsAllocation;
+ Allocation mInPixelsAllocation2;
+ Allocation mOutPixelsAllocation;
+
+ /**
+ * Define enum type for test names
+ */
+ public enum TestName {
+ // totally there are 38 test cases
+ LEVELS_VEC3_RELAXED ("Levels Vec3 Relaxed"),
+ LEVELS_VEC4_RELAXED ("Levels Vec4 Relaxed"),
+ LEVELS_VEC3_FULL ("Levels Vec3 Full"),
+ LEVELS_VEC4_FULL ("Levels Vec4 Full"),
+ BLUR_RADIUS_25 ("Blur radius 25"),
+ INTRINSIC_BLUE_RADIUS_25 ("Intrinsic Blur radius 25"),
+ GREYSCALE ("Greyscale"),
+ GRAIN ("Grain"),
+ FISHEYE_FULL ("Fisheye Full"),
+ FISHEYE_RELAXED ("Fisheye Relaxed"),
+ FISHEYE_APPROXIMATE_FULL ("Fisheye Approximate Full"),
+ FISHEYE_APPROXIMATE_RELAXED ("Fisheye Approximate Relaxed"),
+ VIGNETTE_FULL ("Vignette Full"),
+ VIGNETTE_RELAXED ("Vignette Relaxed"),
+ VIGNETTE_APPROXIMATE_FULL ("Vignette Approximate Full"),
+ VIGNETTE_APPROXIMATE_RELAXED ("Vignette Approximate Relaxed"),
+ GROUP_TEST_EMULATED ("Group Test (emulated)"),
+ GROUP_TEST_NATIVE ("Group Test (native)"),
+ CONVOLVE_3X3 ("Convolve 3x3"),
+ INTRINSICS_CONVOLVE_3X3 ("Intrinsics Convolve 3x3"),
+ COLOR_MATRIX ("ColorMatrix"),
+ INTRINSICS_COLOR_MATRIX ("Intrinsics ColorMatrix"),
+ INTRINSICS_COLOR_MATRIX_GREY ("Intrinsics ColorMatrix Grey"),
+ COPY ("Copy"),
+ CROSS_PROCESS_USING_LUT ("CrossProcess (using LUT)"),
+ CONVOLVE_5X5 ("Convolve 5x5"),
+ INTRINSICS_CONVOLVE_5X5 ("Intrinsics Convolve 5x5"),
+ MANDELBROT ("Mandelbrot"),
+ INTRINSICS_BLEND ("Intrinsics Blend"),
+ INTRINSICS_BLUR_25G ("Intrinsics Blur 25 uchar"),
+ VIBRANCE ("Vibrance"),
+ BW_FILTER ("BW Filter"),
+ SHADOWS ("Shadows"),
+ CONTRAST ("Contrast"),
+ EXPOSURE ("Exposure"),
+ WHITE_BALANCE ("White Balance"),
+ COLOR_CUBE ("Color Cube"),
+ COLOR_CUBE_3D_INTRINSIC ("Color Cube (3D LUT intrinsic)");
+
+
+ private final String name;
+
+ private TestName(String s) {
+ name = s;
+ }
+
+ // return quoted string as displayed test name
+ public String toString() {
+ return name;
+ }
+ }
Bitmap mBitmapIn;
Bitmap mBitmapIn2;
Bitmap mBitmapOut;
- String mTestNames[];
private Spinner mSpinner;
private SeekBar mBar1;
@@ -77,6 +138,7 @@
private boolean mDoingBenchmark;
private TestBase mTest;
+ private int mRunCount;
public void updateDisplay() {
mTest.updateBitmap(mBitmapOut);
@@ -135,98 +197,125 @@
}
- void changeTest(int testID) {
+ void changeTest(TestName testName) {
if (mTest != null) {
mTest.destroy();
}
- switch(testID) {
- case 0:
+ switch(testName) {
+ case LEVELS_VEC3_RELAXED:
mTest = new LevelsV4(false, false);
break;
- case 1:
+ case LEVELS_VEC4_RELAXED:
mTest = new LevelsV4(false, true);
break;
- case 2:
+ case LEVELS_VEC3_FULL:
mTest = new LevelsV4(true, false);
break;
- case 3:
+ case LEVELS_VEC4_FULL:
mTest = new LevelsV4(true, true);
break;
- case 4:
+ case BLUR_RADIUS_25:
mTest = new Blur25(false);
break;
- case 5:
+ case INTRINSIC_BLUE_RADIUS_25:
mTest = new Blur25(true);
break;
- case 6:
+ case GREYSCALE:
mTest = new Greyscale();
break;
- case 7:
+ case GRAIN:
mTest = new Grain();
break;
- case 8:
+ case FISHEYE_FULL:
mTest = new Fisheye(false, false);
break;
- case 9:
+ case FISHEYE_RELAXED:
mTest = new Fisheye(false, true);
break;
- case 10:
+ case FISHEYE_APPROXIMATE_FULL:
mTest = new Fisheye(true, false);
break;
- case 11:
+ case FISHEYE_APPROXIMATE_RELAXED:
mTest = new Fisheye(true, true);
break;
- case 12:
+ case VIGNETTE_FULL:
mTest = new Vignette(false, false);
break;
- case 13:
+ case VIGNETTE_RELAXED:
mTest = new Vignette(false, true);
break;
- case 14:
+ case VIGNETTE_APPROXIMATE_FULL:
mTest = new Vignette(true, false);
break;
- case 15:
+ case VIGNETTE_APPROXIMATE_RELAXED:
mTest = new Vignette(true, true);
break;
- case 16:
+ case GROUP_TEST_EMULATED:
mTest = new GroupTest(false);
break;
- case 17:
+ case GROUP_TEST_NATIVE:
mTest = new GroupTest(true);
break;
- case 18:
+ case CONVOLVE_3X3:
mTest = new Convolve3x3(false);
break;
- case 19:
+ case INTRINSICS_CONVOLVE_3X3:
mTest = new Convolve3x3(true);
break;
- case 20:
+ case COLOR_MATRIX:
mTest = new ColorMatrix(false, false);
break;
- case 21:
+ case INTRINSICS_COLOR_MATRIX:
mTest = new ColorMatrix(true, false);
break;
- case 22:
+ case INTRINSICS_COLOR_MATRIX_GREY:
mTest = new ColorMatrix(true, true);
break;
- case 23:
+ case COPY:
mTest = new Copy();
break;
- case 24:
+ case CROSS_PROCESS_USING_LUT:
mTest = new CrossProcess();
break;
- case 25:
+ case CONVOLVE_5X5:
mTest = new Convolve5x5(false);
break;
- case 26:
+ case INTRINSICS_CONVOLVE_5X5:
mTest = new Convolve5x5(true);
break;
- case 27:
+ case MANDELBROT:
mTest = new Mandelbrot();
break;
- case 28:
+ case INTRINSICS_BLEND:
mTest = new Blend();
break;
+ case INTRINSICS_BLUR_25G:
+ mTest = new Blur25G();
+ break;
+ case VIBRANCE:
+ mTest = new Vibrance();
+ break;
+ case BW_FILTER:
+ mTest = new BWFilter();
+ break;
+ case SHADOWS:
+ mTest = new Shadows();
+ break;
+ case CONTRAST:
+ mTest = new Contrast();
+ break;
+ case EXPOSURE:
+ mTest = new Exposure();
+ break;
+ case WHITE_BALANCE:
+ mTest = new WhiteBalance();
+ break;
+ case COLOR_CUBE:
+ mTest = new ColorCube(false);
+ break;
+ case COLOR_CUBE_3D_INTRINSIC:
+ mTest = new ColorCube(true);
+ break;
}
mTest.createBaseTest(this, mBitmapIn, mBitmapIn2, mBitmapOut);
@@ -238,45 +327,14 @@
}
void setupTests() {
- mTestNames = new String[29];
- mTestNames[0] = "Levels Vec3 Relaxed";
- mTestNames[1] = "Levels Vec4 Relaxed";
- mTestNames[2] = "Levels Vec3 Full";
- mTestNames[3] = "Levels Vec4 Full";
- mTestNames[4] = "Blur radius 25";
- mTestNames[5] = "Intrinsic Blur radius 25";
- mTestNames[6] = "Greyscale";
- mTestNames[7] = "Grain";
- mTestNames[8] = "Fisheye Full";
- mTestNames[9] = "Fisheye Relaxed";
- mTestNames[10] = "Fisheye Approximate Full";
- mTestNames[11] = "Fisheye Approximate Relaxed";
- mTestNames[12] = "Vignette Full";
- mTestNames[13] = "Vignette Relaxed";
- mTestNames[14] = "Vignette Approximate Full";
- mTestNames[15] = "Vignette Approximate Relaxed";
- mTestNames[16] = "Group Test (emulated)";
- mTestNames[17] = "Group Test (native)";
- mTestNames[18] = "Convolve 3x3";
- mTestNames[19] = "Intrinsics Convolve 3x3";
- mTestNames[20] = "ColorMatrix";
- mTestNames[21] = "Intrinsics ColorMatrix";
- mTestNames[22] = "Intrinsics ColorMatrix Grey";
- mTestNames[23] = "Copy";
- mTestNames[24] = "CrossProcess (using LUT)";
- mTestNames[25] = "Convolve 5x5";
- mTestNames[26] = "Intrinsics Convolve 5x5";
- mTestNames[27] = "Mandelbrot";
- mTestNames[28] = "Intrinsics Blend";
-
- mTestSpinner.setAdapter(new ArrayAdapter<String>(
- this, R.layout.spinner_layout, mTestNames));
+ mTestSpinner.setAdapter(new ArrayAdapter<TestName>(
+ this, R.layout.spinner_layout, TestName.values()));
}
private AdapterView.OnItemSelectedListener mTestSpinnerListener =
new AdapterView.OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
- changeTest(pos);
+ changeTest(TestName.values()[pos]);
}
public void onNothingSelected(AdapterView parent) {
@@ -291,7 +349,8 @@
mBitmapIn = loadBitmap(R.drawable.img1600x1067);
mBitmapIn2 = loadBitmap(R.drawable.img1600x1067b);
- mBitmapOut = loadBitmap(R.drawable.img1600x1067);
+ mBitmapOut = Bitmap.createBitmap(mBitmapIn.getWidth(), mBitmapIn.getHeight(),
+ mBitmapIn.getConfig());
mSurfaceView = (SurfaceView) findViewById(R.id.surface);
@@ -324,23 +383,22 @@
mBenchmarkResult = (TextView) findViewById(R.id.benchmarkText);
mBenchmarkResult.setText("Result: not run");
+
+ mRS = RenderScript.create(this);
+ mInPixelsAllocation = Allocation.createFromBitmap(mRS, mBitmapIn);
+ mInPixelsAllocation2 = Allocation.createFromBitmap(mRS, mBitmapIn2);
+ mOutPixelsAllocation = Allocation.createFromBitmap(mRS, mBitmapOut);
+
+
setupTests();
- changeTest(0);
+ changeTest(TestName.LEVELS_VEC3_RELAXED);
}
private Bitmap loadBitmap(int resource) {
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
- return copyBitmap(BitmapFactory.decodeResource(getResources(), resource, options));
- }
-
- private static Bitmap copyBitmap(Bitmap source) {
- Bitmap b = Bitmap.createBitmap(source.getWidth(), source.getHeight(), source.getConfig());
- Canvas c = new Canvas(b);
- c.drawBitmap(source, 0, 0, null);
- source.recycle();
- return b;
+ return BitmapFactory.decodeResource(getResources(), resource, options);
}
// button hook
@@ -364,10 +422,10 @@
try {
BufferedWriter rsWriter = new BufferedWriter(new FileWriter(resultFile));
Log.v(TAG, "Saved results in: " + resultFile.getAbsolutePath());
- for (int i = 0; i < mTestNames.length; i++ ) {
- changeTest(i);
+ for (TestName tn: TestName.values()) {
+ changeTest(tn);
float t = getBenchmark();
- String s = new String("" + mTestNames[i] + ", " + t);
+ String s = new String("" + tn.toString() + ", " + t);
rsWriter.write(s + "\n");
Log.v(TAG, "Test " + s + "ms\n");
}
@@ -375,7 +433,7 @@
} catch (IOException e) {
Log.v(TAG, "Unable to write result file " + e.getMessage());
}
- changeTest(0);
+ changeTest(TestName.LEVELS_VEC3_RELAXED);
}
// For benchmark test
@@ -392,7 +450,6 @@
mTest.finish();
} while (t > java.lang.System.currentTimeMillis());
-
//Log.v(TAG, "Benchmarking");
int ct = 0;
t = java.lang.System.currentTimeMillis();
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Mandelbrot.java b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Mandelbrot.java
index 556d797..1780587 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Mandelbrot.java
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Mandelbrot.java
@@ -18,7 +18,6 @@
import java.lang.Math;
-import android.support.v8.renderscript.*;
import android.util.Log;
import android.widget.SeekBar;
import android.widget.TextView;
diff --git a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/greyscale.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Shadows.java
similarity index 61%
copy from tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/greyscale.rs
copy to tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Shadows.java
index b3a7ef0..353c56d 100644
--- a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/greyscale.rs
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Shadows.java
@@ -14,17 +14,19 @@
* limitations under the License.
*/
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.imagejb)
-#pragma rs_fp_relaxed
+package com.android.rs.image2;
-const static float3 gMonoMult = {0.299f, 0.587f, 0.114f};
-void root(const uchar4 *v_in, uchar4 *out) {
- float4 f4 = rsUnpackColor8888(*v_in);
+public class Shadows extends TestBase {
+ private ScriptC_shadows mScript;
- float3 mono = dot(f4.rgb, gMonoMult);
- *out = rsPackColorTo8888(mono);
+ public void createTest(android.content.res.Resources res) {
+ mScript = new ScriptC_shadows(mRS);
+ }
+
+ public void runTest() {
+ mScript.invoke_prepareShadows(50.f);
+ mScript.forEach_shadowsKernel(mInPixelsAllocation, mOutPixelsAllocation);
+ }
+
}
-
-
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/TestBase.java b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/TestBase.java
index dbbc594..eeabc73 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/TestBase.java
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/TestBase.java
@@ -90,18 +90,17 @@
public final void createBaseTest(ImageProcessingActivity2 ipact, Bitmap b, Bitmap b2, Bitmap outb) {
act = ipact;
- mRS = RenderScript.create(act);
+ mRS = ipact.mRS;
- mInPixelsAllocation = Allocation.createFromBitmap(mRS, b);
- mInPixelsAllocation2 = Allocation.createFromBitmap(mRS, b2);
- mOutPixelsAllocation = Allocation.createFromBitmap(mRS, outb);
+ mInPixelsAllocation = ipact.mInPixelsAllocation;
+ mInPixelsAllocation2 = ipact.mInPixelsAllocation2;
+ mOutPixelsAllocation = ipact.mOutPixelsAllocation;
createTest(act.getResources());
}
// Must override
public void createTest(android.content.res.Resources res) {
- android.util.Log.e("img", "implement createTest");
}
// Must override
@@ -113,7 +112,6 @@
}
public void destroy() {
- mRS.destroy();
}
public void updateBitmap(Bitmap b) {
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Vibrance.java b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Vibrance.java
new file mode 100644
index 0000000..37c0aa7
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Vibrance.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.image2;
+
+public class Vibrance extends TestBase {
+ private ScriptC_vibrance mScript;
+
+ public void createTest(android.content.res.Resources res) {
+ mScript = new ScriptC_vibrance(mRS);
+ }
+
+ public void runTest() {
+ mScript.set_vibrance(50.f);
+ mScript.invoke_prepareVibrance();
+ mScript.forEach_vibranceKernel(mInPixelsAllocation, mOutPixelsAllocation);
+ }
+
+}
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Vignette.java b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Vignette.java
index 8618d5a..9f6d34d 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Vignette.java
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Vignette.java
@@ -16,7 +16,6 @@
package com.android.rs.image2;
-import android.support.v8.renderscript.*;
import android.widget.SeekBar;
import android.widget.TextView;
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/WhiteBalance.java b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/WhiteBalance.java
new file mode 100644
index 0000000..658e3b1
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/WhiteBalance.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.image2;
+
+import java.lang.Math;
+
+import android.support.v8.renderscript.*;
+
+public class WhiteBalance extends TestBase {
+ private ScriptC_wbalance mScript;
+
+ public void createTest(android.content.res.Resources res) {
+ mScript = new ScriptC_wbalance(mRS);
+ }
+
+ public void runTest() {
+ mScript.set_histogramSource(mInPixelsAllocation);
+ mScript.set_histogramWidth(mInPixelsAllocation.getType().getX());
+ mScript.set_histogramHeight(mInPixelsAllocation.getType().getY());
+ mScript.invoke_prepareWhiteBalance();
+ mScript.forEach_whiteBalanceKernel(mInPixelsAllocation, mOutPixelsAllocation);
+ }
+
+}
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/blend.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/blend.rs
index 4d90725..9ec1246 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/blend.rs
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/blend.rs
@@ -12,8 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.image2)
+#include "ip.rsh"
uchar alpha = 0x0;
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/bwfilter.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/bwfilter.rs
new file mode 100644
index 0000000..e706d44
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/bwfilter.rs
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ip.rsh"
+//#pragma rs_fp_relaxed
+
+static float sr = 0.f;
+static float sg = 0.f;
+static float sb = 0.f;
+
+void prepareBwFilter(uint32_t rw, uint32_t gw, uint32_t bw) {
+
+ sr = rw;
+ sg = gw;
+ sb = bw;
+
+ float imageMin = min(sg,sb);
+ imageMin = fmin(sr,imageMin);
+ float imageMax = max(sg,sb);
+ imageMax = fmax(sr,imageMax);
+ float avg = (imageMin + imageMax)/2;
+ sb /= avg;
+ sg /= avg;
+ sr /= avg;
+
+}
+
+void bwFilterKernel(const uchar4 *in, uchar4 *out) {
+ float r = in->r * sr;
+ float g = in->g * sg;
+ float b = in->b * sb;
+ float localMin, localMax, avg;
+ localMin = fmin(g,b);
+ localMin = fmin(r,localMin);
+ localMax = fmax(g,b);
+ localMax = fmax(r,localMax);
+ avg = (localMin+localMax) * 0.5f;
+ out->r = out->g = out->b = rsClamp(avg, 0, 255);
+}
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/colorcube.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/colorcube.rs
new file mode 100644
index 0000000..4f1e73e
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/colorcube.rs
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ip.rsh"
+#pragma rs_fp_relaxed
+
+
+static rs_allocation gCube;
+static int4 gDims;
+static int4 gCoordMul;
+
+
+void setCube(rs_allocation c) {
+ gCube = c;
+ gDims.x = rsAllocationGetDimX(gCube);
+ gDims.y = rsAllocationGetDimY(gCube);
+ gDims.z = rsAllocationGetDimZ(gCube);
+ gDims.w = 0;
+
+ float4 m = (float4)(1.f / 255.f) * convert_float4(gDims - 1);
+ gCoordMul = convert_int4(m * (float4)0x10000);
+
+ rsDebug("dims", gDims);
+ rsDebug("gCoordMul", gCoordMul);
+}
+
+void root(const uchar4 *in, uchar4 *out, uint32_t x, uint32_t y) {
+ //rsDebug("root", in);
+
+ int4 baseCoord = convert_int4(*in) * gCoordMul;
+ int4 coord1 = baseCoord >> (int4)16;
+ int4 coord2 = min(coord1 + 1, gDims - 1);
+
+ int4 weight2 = baseCoord & 0xffff;
+ int4 weight1 = (int4)0x10000 - weight2;
+
+ uint4 v000 = convert_uint4(rsGetElementAt_uchar4(gCube, coord1.x, coord1.y, coord1.z));
+ uint4 v100 = convert_uint4(rsGetElementAt_uchar4(gCube, coord2.x, coord1.y, coord1.z));
+ uint4 v010 = convert_uint4(rsGetElementAt_uchar4(gCube, coord1.x, coord2.y, coord1.z));
+ uint4 v110 = convert_uint4(rsGetElementAt_uchar4(gCube, coord2.x, coord2.y, coord1.z));
+ uint4 v001 = convert_uint4(rsGetElementAt_uchar4(gCube, coord1.x, coord1.y, coord2.z));
+ uint4 v101 = convert_uint4(rsGetElementAt_uchar4(gCube, coord2.x, coord1.y, coord2.z));
+ uint4 v011 = convert_uint4(rsGetElementAt_uchar4(gCube, coord1.x, coord2.y, coord2.z));
+ uint4 v111 = convert_uint4(rsGetElementAt_uchar4(gCube, coord2.x, coord2.y, coord2.z));
+
+ uint4 yz00 = ((v000 * weight1.x) + (v100 * weight2.x)) >> (int4)8;
+ uint4 yz10 = ((v010 * weight1.x) + (v110 * weight2.x)) >> (int4)8;
+ uint4 yz01 = ((v001 * weight1.x) + (v101 * weight2.x)) >> (int4)8;
+ uint4 yz11 = ((v011 * weight1.x) + (v111 * weight2.x)) >> (int4)8;
+
+ uint4 z0 = ((yz00 * weight1.y) + (yz10 * weight2.y)) >> (int4)16;
+ uint4 z1 = ((yz01 * weight1.y) + (yz11 * weight2.y)) >> (int4)16;
+
+ uint4 v = ((z0 * weight1.z) + (z1 * weight2.z)) >> (int4)16;
+ uint4 v2 = (v + 0x7f) >> (int4)8;
+
+ *out = convert_uchar4(v2);
+ out->a = 0xff;
+
+ #if 0
+ if (in->r != out->r) {
+ rsDebug("dr", in->r - out->r);
+ //rsDebug("in", convert_int4(*in));
+ //rsDebug("coord1", coord1);
+ //rsDebug("coord2", coord2);
+ //rsDebug("weight1", weight1);
+ //rsDebug("weight2", weight2);
+ //rsDebug("yz00", yz00);
+ //rsDebug("z0", z0);
+ //rsDebug("v", v);
+ //rsDebug("v2", v2);
+ //rsDebug("out", convert_int4(*out));
+ }
+ #endif
+}
+
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/colormatrix.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/colormatrix.fs
similarity index 79%
rename from tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/colormatrix.rs
rename to tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/colormatrix.fs
index e93bef3..86fb248 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/colormatrix.rs
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/colormatrix.fs
@@ -14,10 +14,7 @@
* limitations under the License.
*/
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.image2)
-#pragma rs_fp_relaxed
-
+#include "ip.rsh"
static rs_matrix4x4 Mat;
@@ -29,10 +26,10 @@
Mat = m;
}
-void root(const uchar4 *in, uchar4 *out) {
- float4 f = convert_float4(*in);
+uchar4 __attribute__((kernel)) root(uchar4 in) {
+ float4 f = convert_float4(in);
f = rsMatrixMultiply(&Mat, f);
f = clamp(f, 0.f, 255.f);
- *out = convert_uchar4(f);
+ return convert_uchar4(f);
}
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/contrast.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/contrast.rs
new file mode 100644
index 0000000..d3743d3
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/contrast.rs
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ip.rsh"
+
+static float brightM = 0.f;
+static float brightC = 0.f;
+
+void setBright(float v) {
+ brightM = pow(2.f, v / 100.f);
+ brightC = 127.f - brightM * 127.f;
+}
+
+void contrast(const uchar4 *in, uchar4 *out)
+{
+#if 0
+ out->r = rsClamp((int)(brightM * in->r + brightC), 0, 255);
+ out->g = rsClamp((int)(brightM * in->g + brightC), 0, 255);
+ out->b = rsClamp((int)(brightM * in->b + brightC), 0, 255);
+#else
+ float3 v = convert_float3(in->rgb) * brightM + brightC;
+ out->rgb = convert_uchar3(clamp(v, 0.f, 255.f));
+#endif
+}
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/convolve5x5.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/convolve5x5.fs
similarity index 93%
rename from tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/convolve5x5.rs
rename to tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/convolve5x5.fs
index b1ad241..922a593 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/convolve5x5.rs
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/convolve5x5.fs
@@ -14,9 +14,7 @@
* limitations under the License.
*/
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.image2)
-#pragma rs_fp_relaxed
+#include "ip.rsh"
int32_t gWidth;
int32_t gHeight;
@@ -24,7 +22,7 @@
float gCoeffs[25];
-void root(uchar4 *out, uint32_t x, uint32_t y) {
+uchar4 __attribute__((kernel)) root(uint32_t x, uint32_t y) {
uint32_t x0 = max((int32_t)x-2, 0);
uint32_t x1 = max((int32_t)x-1, 0);
uint32_t x2 = x;
@@ -68,8 +66,7 @@
+ convert_float4(rsGetElementAt_uchar4(gIn, x4, y4)) * gCoeffs[24];
p0 = clamp(p0 + p1 + p2 + p3 + p4, 0.f, 255.f);
- p0.a = 255.f;
- *out = convert_uchar4(p0);
+ return convert_uchar4(p0);
}
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/levels_relaxed.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/copy.fs
similarity index 84%
copy from tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/levels_relaxed.rs
copy to tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/copy.fs
index ffdcfe3..6595874 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/levels_relaxed.rs
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/copy.fs
@@ -14,9 +14,10 @@
* limitations under the License.
*/
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.image2)
-#pragma rs_fp_relaxed
+#include "ip.rsh"
-#include "levels.rsh"
+uchar4 __attribute__((kernel)) root(uchar4 v_in) {
+ return v_in;
+}
+
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/copy.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/copy.rs
deleted file mode 100644
index 31e4241..0000000
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/copy.rs
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.image2)
-
-void root(const uchar4 *v_in, uchar4 *v_out) {
- *v_out = *v_in;
-}
-
-
diff --git a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/greyscale.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/exposure.rs
similarity index 66%
rename from tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/greyscale.rs
rename to tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/exposure.rs
index b3a7ef0..0f05cb9 100644
--- a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/greyscale.rs
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/exposure.rs
@@ -14,17 +14,18 @@
* limitations under the License.
*/
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.imagejb)
-#pragma rs_fp_relaxed
+#include "ip.rsh"
-const static float3 gMonoMult = {0.299f, 0.587f, 0.114f};
+static float bright = 0.f;
-void root(const uchar4 *v_in, uchar4 *out) {
- float4 f4 = rsUnpackColor8888(*v_in);
-
- float3 mono = dot(f4.rgb, gMonoMult);
- *out = rsPackColorTo8888(mono);
+void setBright(float v) {
+ bright = 255.f / (255.f - v);
}
+void exposure(const uchar4 *in, uchar4 *out)
+{
+ out->r = rsClamp((int)(bright * in->r), 0, 255);
+ out->g = rsClamp((int)(bright * in->g), 0, 255);
+ out->b = rsClamp((int)(bright * in->b), 0, 255);
+}
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye.rsh b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye.rsh
index 3809912..2eacb7d 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye.rsh
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye.rsh
@@ -26,7 +26,7 @@
neg_center = -center;
inv_dimensions.x = 1.f / (float)dim_x;
inv_dimensions.y = 1.f / (float)dim_y;
- alpha = k * 2.0 + 0.75;
+ alpha = k * 2.0f + 0.75f;
axis_scale = (float2)1.f;
if (dim_x > dim_y)
@@ -34,15 +34,15 @@
else
axis_scale.x = (float)dim_x / (float)dim_y;
- const float bound2 = 0.25 * (axis_scale.x*axis_scale.x + axis_scale.y*axis_scale.y);
+ const float bound2 = 0.25f * (axis_scale.x*axis_scale.x + axis_scale.y*axis_scale.y);
const float bound = sqrt(bound2);
- const float radius = 1.15 * bound;
+ const float radius = 1.15f * bound;
radius2 = radius*radius;
const float max_radian = M_PI_2 - atan(alpha / bound * sqrt(radius2 - bound2));
factor = bound / max_radian;
}
-void root(uchar4 *out, uint32_t x, uint32_t y) {
+uchar4 __attribute__((kernel)) root(uint32_t x, uint32_t y) {
// Convert x and y to floating point coordinates with center as origin
const float2 inCoord = {(float)x, (float)y};
const float2 coord = mad(inCoord, inv_dimensions, neg_center);
@@ -53,6 +53,6 @@
const float scalar = radian * factor * inv_dist;
const float2 new_coord = mad(coord, scalar, center);
const float4 fout = rsSample(in_alloc, sampler, new_coord);
- *out = rsPackColorTo8888(fout);
+ return rsPackColorTo8888(fout);
}
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_approx.rsh b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_approx.rsh
index 08b4126..fcf0a3d 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_approx.rsh
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_approx.rsh
@@ -26,7 +26,7 @@
neg_center = -center;
inv_dimensions.x = 1.f / (float)dim_x;
inv_dimensions.y = 1.f / (float)dim_y;
- alpha = k * 2.0 + 0.75;
+ alpha = k * 2.0f + 0.75f;
axis_scale = (float2)1.f;
if (dim_x > dim_y)
@@ -34,15 +34,15 @@
else
axis_scale.x = (float)dim_x / (float)dim_y;
- const float bound2 = 0.25 * (axis_scale.x*axis_scale.x + axis_scale.y*axis_scale.y);
+ const float bound2 = 0.25f * (axis_scale.x*axis_scale.x + axis_scale.y*axis_scale.y);
const float bound = sqrt(bound2);
- const float radius = 1.15 * bound;
+ const float radius = 1.15f * bound;
radius2 = radius*radius;
const float max_radian = M_PI_2 - atan(alpha / bound * sqrt(radius2 - bound2));
factor = bound / max_radian;
}
-void root(uchar4 *out, uint32_t x, uint32_t y) {
+uchar4 __attribute__((kernel)) root(uint32_t x, uint32_t y) {
// Convert x and y to floating point coordinates with center as origin
const float2 inCoord = {(float)x, (float)y};
const float2 coord = mad(inCoord, inv_dimensions, neg_center);
@@ -53,6 +53,6 @@
const float scalar = radian * factor * inv_dist;
const float2 new_coord = mad(coord, scalar, center);
const float4 fout = rsSample(in_alloc, sampler, new_coord);
- *out = rsPackColorTo8888(fout);
+ return rsPackColorTo8888(fout);
}
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_approx_full.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_approx_full.rs
index cce42f9..ed69ff4 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_approx_full.rs
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_approx_full.rs
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.image2)
+#include "ip.rsh"
#include "fisheye_approx.rsh"
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_approx_relaxed.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_approx_relaxed.fs
similarity index 87%
rename from tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_approx_relaxed.rs
rename to tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_approx_relaxed.fs
index 64d27ed..ed69ff4 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_approx_relaxed.rs
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_approx_relaxed.fs
@@ -14,9 +14,7 @@
* limitations under the License.
*/
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.image2)
-#pragma rs_fp_relaxed
+#include "ip.rsh"
#include "fisheye_approx.rsh"
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_full.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_full.rs
index e42df13..f986b5d 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_full.rs
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_full.rs
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.image2)
+#include "ip.rsh"
#include "fisheye.rsh"
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_relaxed.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_relaxed.fs
similarity index 87%
rename from tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_relaxed.rs
rename to tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_relaxed.fs
index 990310b..f986b5d 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_relaxed.rs
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_relaxed.fs
@@ -14,9 +14,7 @@
* limitations under the License.
*/
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.image2)
-#pragma rs_fp_relaxed
+#include "ip.rsh"
#include "fisheye.rsh"
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/grain.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/grain.fs
similarity index 87%
rename from tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/grain.rs
rename to tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/grain.fs
index 44320a5..2e62cd7 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/grain.rs
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/grain.fs
@@ -14,12 +14,10 @@
* limitations under the License.
*/
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.image2)
-#pragma rs_fp_relaxed
+#include "ip.rsh"
-void genRand(uchar *out) {
- *out = (uchar)rsRand(0xff);
+uchar __attribute__((kernel)) genRand() {
+ return (uchar)rsRand(0xff);
}
/*
@@ -42,7 +40,7 @@
int32_t gHMask;
rs_allocation gBlendSource;
-void blend9(uchar *out, uint32_t x, uint32_t y) {
+uchar __attribute__((kernel)) blend9(uint32_t x, uint32_t y) {
uint32_t x1 = (x-1) & gWMask;
uint32_t x2 = (x+1) & gWMask;
uint32_t y1 = (y-1) & gHMask;
@@ -70,14 +68,14 @@
p20 += p02;
p20 = min(p20 >> 10, (uint)255);
- *out = (uchar)p20;
+ return (uchar)p20;
}
float gNoiseStrength;
rs_allocation gNoise;
-void root(const uchar4 *in, uchar4 *out, uint32_t x, uint32_t y) {
- float4 ip = convert_float4(*in);
+uchar4 __attribute__((kernel)) root(uchar4 in, uint32_t x, uint32_t y) {
+ float4 ip = convert_float4(in);
float pnoise = (float) rsGetElementAt_uchar(gNoise, x & gWMask, y & gHMask);
float energy_level = ip.r + ip.g + ip.b;
@@ -89,5 +87,5 @@
uchar4 p = convert_uchar4(ip);
p.a = 0xff;
- *out = p;
+ return p;
}
diff --git a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/greyscale.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/greyscale.fs
similarity index 66%
copy from tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/greyscale.rs
copy to tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/greyscale.fs
index b3a7ef0..4e13072 100644
--- a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/greyscale.rs
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/greyscale.fs
@@ -14,17 +14,23 @@
* limitations under the License.
*/
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.imagejb)
-#pragma rs_fp_relaxed
+#include "ip.rsh"
const static float3 gMonoMult = {0.299f, 0.587f, 0.114f};
-void root(const uchar4 *v_in, uchar4 *out) {
- float4 f4 = rsUnpackColor8888(*v_in);
+uchar4 __attribute__((kernel)) root(uchar4 v_in) {
+ float4 f4 = rsUnpackColor8888(v_in);
float3 mono = dot(f4.rgb, gMonoMult);
- *out = rsPackColorTo8888(mono);
+ return rsPackColorTo8888(mono);
}
+uchar __attribute__((kernel)) toU8(uchar4 v_in) {
+ float4 f4 = convert_float4(v_in);
+ return (uchar)dot(f4.rgb, gMonoMult);
+}
+
+uchar4 __attribute__((kernel)) toU8_4(uchar v_in) {
+ return (uchar4)v_in;
+}
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/greyscale.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/greyscale.rs
deleted file mode 100644
index b5abf3f0..0000000
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/greyscale.rs
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.image2)
-#pragma rs_fp_relaxed
-
-const static float3 gMonoMult = {0.299f, 0.587f, 0.114f};
-
-void root(const uchar4 *v_in, uchar4 *v_out) {
- float4 f4 = rsUnpackColor8888(*v_in);
-
- float3 mono = dot(f4.rgb, gMonoMult);
- *v_out = rsPackColorTo8888(mono);
-}
-
-
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/levels_relaxed.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/ip.rsh
similarity index 86%
copy from tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/levels_relaxed.rs
copy to tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/ip.rsh
index ffdcfe3..34e213c 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/levels_relaxed.rs
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/ip.rsh
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 The Android Open Source Project
+ * Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,7 +16,5 @@
#pragma version(1)
#pragma rs java_package_name(com.android.rs.image2)
-#pragma rs_fp_relaxed
-#include "levels.rsh"
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/ip2_convolve3x3.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/ip2_convolve3x3.rs
index 13f9032..177e86e 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/ip2_convolve3x3.rs
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/ip2_convolve3x3.rs
@@ -14,9 +14,7 @@
* limitations under the License.
*/
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.image2)
-#pragma rs_fp_relaxed
+#include "ip.rsh"
int32_t gWidth;
int32_t gHeight;
@@ -24,21 +22,21 @@
float gCoeffs[9];
-void root(uchar4 *out, uint32_t x, uint32_t y) {
+uchar4 __attribute__((kernel)) root(uint32_t x, uint32_t y) {
uint32_t x1 = min((int32_t)x+1, gWidth-1);
uint32_t x2 = max((int32_t)x-1, 0);
uint32_t y1 = min((int32_t)y+1, gHeight-1);
uint32_t y2 = max((int32_t)y-1, 0);
- float4 p00 = convert_float4(((uchar4 *)rsGetElementAt(gIn, x1, y1))[0]);
- float4 p01 = convert_float4(((uchar4 *)rsGetElementAt(gIn, x, y1))[0]);
- float4 p02 = convert_float4(((uchar4 *)rsGetElementAt(gIn, x2, y1))[0]);
- float4 p10 = convert_float4(((uchar4 *)rsGetElementAt(gIn, x1, y))[0]);
- float4 p11 = convert_float4(((uchar4 *)rsGetElementAt(gIn, x, y))[0]);
- float4 p12 = convert_float4(((uchar4 *)rsGetElementAt(gIn, x2, y))[0]);
- float4 p20 = convert_float4(((uchar4 *)rsGetElementAt(gIn, x1, y2))[0]);
- float4 p21 = convert_float4(((uchar4 *)rsGetElementAt(gIn, x, y2))[0]);
- float4 p22 = convert_float4(((uchar4 *)rsGetElementAt(gIn, x2, y2))[0]);
+ float4 p00 = convert_float4(rsGetElementAt_uchar4(gIn, x1, y1));
+ float4 p01 = convert_float4(rsGetElementAt_uchar4(gIn, x, y1));
+ float4 p02 = convert_float4(rsGetElementAt_uchar4(gIn, x2, y1));
+ float4 p10 = convert_float4(rsGetElementAt_uchar4(gIn, x1, y));
+ float4 p11 = convert_float4(rsGetElementAt_uchar4(gIn, x, y));
+ float4 p12 = convert_float4(rsGetElementAt_uchar4(gIn, x2, y));
+ float4 p20 = convert_float4(rsGetElementAt_uchar4(gIn, x1, y2));
+ float4 p21 = convert_float4(rsGetElementAt_uchar4(gIn, x, y2));
+ float4 p22 = convert_float4(rsGetElementAt_uchar4(gIn, x2, y2));
p00 *= gCoeffs[0];
p01 *= gCoeffs[1];
p02 *= gCoeffs[2];
@@ -61,7 +59,7 @@
p20 += p02;
p20 = clamp(p20, 0.f, 255.f);
- *out = convert_uchar4(p20);
+ return convert_uchar4(p20);
}
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/levels.rsh b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/levels.rsh
index 7c5d930..e289906 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/levels.rsh
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/levels.rsh
@@ -21,24 +21,26 @@
float overInWMinInB;
rs_matrix3x3 colorMat;
-void root(const uchar4 *in, uchar4 *out, uint32_t x, uint32_t y) {
- float3 pixel = convert_float4(in[0]).rgb;
+uchar4 __attribute__((kernel)) root(uchar4 in, uint32_t x, uint32_t y) {
+ uchar4 out;
+ float3 pixel = convert_float4(in).rgb;
pixel = rsMatrixMultiply(&colorMat, pixel);
pixel = clamp(pixel, 0.f, 255.f);
pixel = (pixel - inBlack) * overInWMinInB;
pixel = pixel * outWMinOutB + outBlack;
pixel = clamp(pixel, 0.f, 255.f);
- out->xyz = convert_uchar3(pixel);
- out->w = 0xff;
+ out.xyz = convert_uchar3(pixel);
+ out.w = 0xff;
+ return out;
}
-void root4(const uchar4 *in, uchar4 *out, uint32_t x, uint32_t y) {
- float4 pixel = convert_float4(in[0]);
+uchar4 __attribute__((kernel)) root4(uchar4 in, uint32_t x, uint32_t y) {
+ float4 pixel = convert_float4(in);
pixel.rgb = rsMatrixMultiply(&colorMat, pixel.rgb);
pixel = clamp(pixel, 0.f, 255.f);
pixel = (pixel - inBlack) * overInWMinInB;
pixel = pixel * outWMinOutB + outBlack;
pixel = clamp(pixel, 0.f, 255.f);
- out->xyzw = convert_uchar4(pixel);
+ return convert_uchar4(pixel);
}
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/levels_full.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/levels_full.rs
index a4aa388..28596ba 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/levels_full.rs
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/levels_full.rs
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.image2)
+#include "ip.rsh"
#include "levels.rsh"
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/levels_relaxed.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/levels_relaxed.fs
similarity index 87%
rename from tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/levels_relaxed.rs
rename to tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/levels_relaxed.fs
index ffdcfe3..28596ba 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/levels_relaxed.rs
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/levels_relaxed.fs
@@ -14,9 +14,7 @@
* limitations under the License.
*/
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.image2)
-#pragma rs_fp_relaxed
+#include "ip.rsh"
#include "levels.rsh"
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/mandelbrot.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/mandelbrot.rs
index 5b3912d..de0bd00 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/mandelbrot.rs
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/mandelbrot.rs
@@ -12,8 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.image2)
+#include "ip.rsh"
uint32_t gMaxIteration = 500;
uint32_t gDimX = 1024;
@@ -23,7 +22,7 @@
float lowerBoundY = -2.f;
float scaleFactor = 4.f;
-void root(uchar4 *v_out, uint32_t x, uint32_t y) {
+uchar4 __attribute__((kernel)) root(uint32_t x, uint32_t y) {
float2 p;
p.x = lowerBoundX + ((float)x / gDimX) * scaleFactor;
p.y = lowerBoundY + ((float)y / gDimY) * scaleFactor;
@@ -41,16 +40,16 @@
if(iter >= gMaxIteration) {
// write a non-transparent black pixel
- *v_out = (uchar4){0, 0, 0, 0xff};
+ return (uchar4){0, 0, 0, 0xff};
} else {
float mi3 = gMaxIteration / 3.f;
if (iter <= (gMaxIteration / 3))
- *v_out = (uchar4){0xff * (iter / mi3), 0, 0, 0xff};
+ return (uchar4){0xff * (iter / mi3), 0, 0, 0xff};
else if (iter <= (((gMaxIteration / 3) * 2)))
- *v_out = (uchar4){0xff - (0xff * ((iter - mi3) / mi3)),
- (0xff * ((iter - mi3) / mi3)), 0, 0xff};
+ return (uchar4){0xff - (0xff * ((iter - mi3) / mi3)),
+ (0xff * ((iter - mi3) / mi3)), 0, 0xff};
else
- *v_out = (uchar4){0, 0xff - (0xff * ((iter - (mi3 * 2)) / mi3)),
- (0xff * ((iter - (mi3 * 2)) / mi3)), 0xff};
+ return (uchar4){0, 0xff - (0xff * ((iter - (mi3 * 2)) / mi3)),
+ (0xff * ((iter - (mi3 * 2)) / mi3)), 0xff};
}
}
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/shadows.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/shadows.rs
new file mode 100644
index 0000000..f6c149d
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/shadows.rs
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ip.rsh"
+//#pragma rs_fp_relaxed
+
+static double shadowFilterMap[] = {
+ -0.00591, 0.0001,
+ 1.16488, 0.01668,
+ -0.18027, -0.06791,
+ -0.12625, 0.09001,
+ 0.15065, -0.03897
+};
+
+static double poly[] = {
+ 0., 0.,
+ 0., 0.,
+ 0.
+};
+
+static const int ABITS = 4;
+static const int HSCALE = 256;
+static const int k1=255 << ABITS;
+static const int k2=HSCALE << ABITS;
+
+static double fastevalPoly(double *poly,int n, double x){
+
+ double f =x;
+ double sum = poly[0]+poly[1]*f;
+ int i;
+ for (i = 2; i < n; i++) {
+ f*=x;
+ sum += poly[i]*f;
+ }
+ return sum;
+}
+
+static ushort3 rgb2hsv( uchar4 rgb)
+{
+ int iMin,iMax,chroma;
+
+ int ri = rgb.r;
+ int gi = rgb.g;
+ int bi = rgb.b;
+ short rv,rs,rh;
+
+ if (ri > gi) {
+ iMax = max (ri, bi);
+ iMin = min (gi, bi);
+ } else {
+ iMax = max (gi, bi);
+ iMin = min (ri, bi);
+ }
+
+ chroma = iMax - iMin;
+ // set value
+ rv = (short)( iMax << ABITS);
+
+ // set saturation
+ if (rv == 0)
+ rs = 0;
+ else
+ rs = (short)((k1*chroma)/iMax);
+
+ // set hue
+ if (rs == 0)
+ rh = 0;
+ else {
+ if ( ri == iMax ) {
+ rh = (short)( (k2*(6*chroma+gi - bi))/(6*chroma));
+ if (rh >= k2) rh -= k2;
+ } else if (gi == iMax)
+ rh = (short)( (k2*(2*chroma+bi - ri ))/(6*chroma));
+ else // (bi == iMax )
+ rh = (short)( (k2*(4*chroma+ri - gi ))/(6*chroma));
+ }
+
+ ushort3 out;
+ out.x = rv;
+ out.y = rs;
+ out.z = rh;
+ return out;
+}
+
+static uchar4 hsv2rgb(ushort3 hsv)
+{
+ int ABITS = 4;
+ int HSCALE = 256;
+ int m;
+ int H,X,ih,is,iv;
+ int k1=255<<ABITS;
+ int k2=HSCALE<<ABITS;
+ int k3=1<<(ABITS-1);
+ int rr=0;
+ int rg=0;
+ int rb=0;
+ short cv = hsv.x;
+ short cs = hsv.y;
+ short ch = hsv.z;
+
+ // set chroma and min component value m
+ //chroma = ( cv * cs )/k1;
+ //m = cv - chroma;
+ m = ((int)cv*(k1 - (int)cs ))/k1;
+
+ // chroma == 0 <-> cs == 0 --> m=cv
+ if (cs == 0) {
+ rb = ( rg = ( rr =( cv >> ABITS) ));
+ } else {
+ ih=(int)ch;
+ is=(int)cs;
+ iv=(int)cv;
+
+ H = (6*ih)/k2;
+ X = ((iv*is)/k2)*(k2- abs(6*ih- 2*(H>>1)*k2 - k2)) ;
+
+ // removing additional bits --> unit8
+ X=( (X+iv*(k1 - is ))/k1 + k3 ) >> ABITS;
+ m=m >> ABITS;
+
+ // ( chroma + m ) --> cv ;
+ cv=(short) (cv >> ABITS);
+ switch (H) {
+ case 0:
+ rr = cv;
+ rg = X;
+ rb = m;
+ break;
+ case 1:
+ rr = X;
+ rg = cv;
+ rb = m;
+ break;
+ case 2:
+ rr = m;
+ rg = cv;
+ rb = X;
+ break;
+ case 3:
+ rr = m;
+ rg = X;
+ rb = cv;
+ break;
+ case 4:
+ rr = X;
+ rg = m;
+ rb = cv;
+ break;
+ case 5:
+ rr = cv;
+ rg = m ;
+ rb = X;
+ break;
+ }
+ }
+
+ uchar4 rgb;
+
+ rgb.r = rr;
+ rgb.g = rg;
+ rgb.b = rb;
+
+ return rgb;
+}
+
+void prepareShadows(float scale) {
+ double s = (scale>=0)?scale:scale/5;
+ for (int i = 0; i < 5; i++) {
+ poly[i] = fastevalPoly(shadowFilterMap+i*2,2 , s);
+ }
+}
+
+void shadowsKernel(const uchar4 *in, uchar4 *out) {
+ ushort3 hsv = rgb2hsv(*in);
+ double v = (fastevalPoly(poly,5,hsv.x/4080.)*4080);
+ if (v>4080) v = 4080;
+ hsv.x = (unsigned short) ((v>0)?v:0);
+ *out = hsv2rgb(hsv);
+}
diff --git a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/threshold.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/threshold.fs
similarity index 67%
rename from tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/threshold.rs
rename to tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/threshold.fs
index d18117a..0b2c2e8 100644
--- a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/threshold.rs
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/threshold.fs
@@ -1,6 +1,20 @@
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.imagejb)
-#pragma rs_fp_relaxed
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ip.rsh"
int height;
@@ -56,51 +70,49 @@
}
}
-void copyIn(const uchar4 *in, float4 *out) {
- *out = convert_float4(*in);
+float4 __attribute__((kernel)) copyIn(uchar4 in) {
+ return convert_float4(in);
}
-static inline float4 GetElementAt_float4(rs_allocation a, uint32_t x, uint32_t y) {
- return ((float4 *)rsGetElementAt(a, x, y))[0];
-}
-
-void vert(uchar4 *out, uint32_t x, uint32_t y) {
+uchar4 __attribute__((kernel)) vert(uint32_t x, uint32_t y) {
float3 blurredPixel = 0;
int gi = 0;
+ uchar4 out;
if ((y > radius) && (y < (height - radius))) {
for (int r = -radius; r <= radius; r ++) {
- float4 i = GetElementAt_float4(ScratchPixel2, x, y + r);
+ float4 i = rsGetElementAt_float4(ScratchPixel2, x, y + r);
blurredPixel += i.xyz * gaussian[gi++];
}
} else {
for (int r = -radius; r <= radius; r ++) {
int validH = rsClamp((int)y + r, (int)0, (int)(height - 1));
- float4 i = GetElementAt_float4(ScratchPixel2, x, validH);
+ float4 i = rsGetElementAt_float4(ScratchPixel2, x, validH);
blurredPixel += i.xyz * gaussian[gi++];
}
}
- out->xyz = convert_uchar3(clamp(blurredPixel, 0.f, 255.f));
- out->w = 0xff;
+ out.xyz = convert_uchar3(clamp(blurredPixel, 0.f, 255.f));
+ out.w = 0xff;
+ return out;
}
-void horz(float4 *out, uint32_t x, uint32_t y) {
+float4 __attribute__((kernel)) horz(uint32_t x, uint32_t y) {
float4 blurredPixel = 0;
int gi = 0;
if ((x > radius) && (x < (width - radius))) {
for (int r = -radius; r <= radius; r ++) {
- float4 i = GetElementAt_float4(ScratchPixel1, x + r, y);
+ float4 i = rsGetElementAt_float4(ScratchPixel1, x + r, y);
blurredPixel += i * gaussian[gi++];
}
} else {
for (int r = -radius; r <= radius; r ++) {
// Stepping left and right away from the pixel
int validX = rsClamp((int)x + r, (int)0, (int)(width - 1));
- float4 i = GetElementAt_float4(ScratchPixel1, validX, y);
+ float4 i = rsGetElementAt_float4(ScratchPixel1, validX, y);
blurredPixel += i * gaussian[gi++];
}
}
- *out = blurredPixel;
+ return blurredPixel;
}
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/threshold.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/threshold.rs
deleted file mode 100644
index 9ef4898..0000000
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/threshold.rs
+++ /dev/null
@@ -1,106 +0,0 @@
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.image2)
-#pragma rs_fp_relaxed
-
-
-int height;
-int width;
-static int radius;
-
-rs_allocation InPixel;
-rs_allocation ScratchPixel1;
-rs_allocation ScratchPixel2;
-
-const int MAX_RADIUS = 25;
-
-// Store our coefficients here
-static float gaussian[MAX_RADIUS * 2 + 1];
-
-void setRadius(int rad) {
- radius = rad;
- // Compute gaussian weights for the blur
- // e is the euler's number
- float e = 2.718281828459045f;
- float pi = 3.1415926535897932f;
- // g(x) = ( 1 / sqrt( 2 * pi ) * sigma) * e ^ ( -x^2 / 2 * sigma^2 )
- // x is of the form [-radius .. 0 .. radius]
- // and sigma varies with radius.
- // Based on some experimental radius values and sigma's
- // we approximately fit sigma = f(radius) as
- // sigma = radius * 0.4 + 0.6
- // The larger the radius gets, the more our gaussian blur
- // will resemble a box blur since with large sigma
- // the gaussian curve begins to lose its shape
- float sigma = 0.4f * (float)radius + 0.6f;
-
- // Now compute the coefficints
- // We will store some redundant values to save some math during
- // the blur calculations
- // precompute some values
- float coeff1 = 1.0f / (sqrt( 2.0f * pi ) * sigma);
- float coeff2 = - 1.0f / (2.0f * sigma * sigma);
-
- float normalizeFactor = 0.0f;
- float floatR = 0.0f;
- for (int r = -radius; r <= radius; r ++) {
- floatR = (float)r;
- gaussian[r + radius] = coeff1 * pow(e, floatR * floatR * coeff2);
- normalizeFactor += gaussian[r + radius];
- }
-
- //Now we need to normalize the weights because all our coefficients need to add up to one
- normalizeFactor = 1.0f / normalizeFactor;
- for (int r = -radius; r <= radius; r ++) {
- floatR = (float)r;
- gaussian[r + radius] *= normalizeFactor;
- }
-}
-
-void copyIn(const uchar4 *in, float4 *out) {
- *out = convert_float4(*in);
-}
-
-void vert(uchar4 *out, uint32_t x, uint32_t y) {
- float3 blurredPixel = 0;
- const float *gPtr = gaussian;
- if ((y > radius) && (y < (height - radius))) {
- for (int r = -radius; r <= radius; r ++) {
- const float4 *i = (const float4 *)rsGetElementAt(ScratchPixel2, x, y + r);
- blurredPixel += i->xyz * gPtr[0];
- gPtr++;
- }
- } else {
- for (int r = -radius; r <= radius; r ++) {
- int validH = rsClamp((int)y + r, (int)0, (int)(height - 1));
- const float4 *i = (const float4 *)rsGetElementAt(ScratchPixel2, x, validH);
- blurredPixel += i->xyz * gPtr[0];
- gPtr++;
- }
- }
-
- out->xyz = convert_uchar3(clamp(blurredPixel, 0.f, 255.f));
- out->w = 0xff;
-}
-
-void horz(float4 *out, uint32_t x, uint32_t y) {
- float3 blurredPixel = 0;
- const float *gPtr = gaussian;
- if ((x > radius) && (x < (width - radius))) {
- for (int r = -radius; r <= radius; r ++) {
- const float4 *i = (const float4 *)rsGetElementAt(ScratchPixel1, x + r, y);
- blurredPixel += i->xyz * gPtr[0];
- gPtr++;
- }
- } else {
- for (int r = -radius; r <= radius; r ++) {
- // Stepping left and right away from the pixel
- int validX = rsClamp((int)x + r, (int)0, (int)(width - 1));
- const float4 *i = (const float4 *)rsGetElementAt(ScratchPixel1, validX, y);
- blurredPixel += i->xyz * gPtr[0];
- gPtr++;
- }
- }
-
- out->xyz = blurredPixel;
-}
-
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vibrance.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vibrance.rs
new file mode 100644
index 0000000..ad4de58
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vibrance.rs
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ip.rsh"
+
+float vibrance = 0.f;
+
+static const float Rf = 0.2999f;
+static const float Gf = 0.587f;
+static const float Bf = 0.114f;
+
+static float S = 0.f;
+static float MS = 0.f;
+static float Rt = 0.f;
+static float Gt = 0.f;
+static float Bt = 0.f;
+static float Vib = 0.f;
+
+void vibranceKernel(const uchar4 *in, uchar4 *out) {
+
+ float R, G, B;
+
+ int r = in->r;
+ int g = in->g;
+ int b = in->b;
+ float red = (r-max(g, b))/256.f;
+ float sx = (float)(Vib/(1+native_exp(-red*3)));
+ S = sx+1;
+ MS = 1.0f - S;
+ Rt = Rf * MS;
+ Gt = Gf * MS;
+ Bt = Bf * MS;
+ int t = (r + g) / 2;
+ R = r;
+ G = g;
+ B = b;
+
+ float Rc = R * (Rt + S) + G * Gt + B * Bt;
+ float Gc = R * Rt + G * (Gt + S) + B * Bt;
+ float Bc = R * Rt + G * Gt + B * (Bt + S);
+
+ out->r = rsClamp(Rc, 0, 255);
+ out->g = rsClamp(Gc, 0, 255);
+ out->b = rsClamp(Bc, 0, 255);
+
+}
+
+void prepareVibrance() {
+
+ Vib = vibrance/100.f;
+ S = Vib + 1;
+ MS = 1.0f - S;
+ Rt = Rf * MS;
+ Gt = Gf * MS;
+ Bt = Bf * MS;
+
+}
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette.rsh b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette.rsh
index a1e4ae5..04ca1f1 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette.rsh
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette.rsh
@@ -31,29 +31,29 @@
else
axis_scale.x = (float)dim_x / (float)dim_y;
- const float max_dist = 0.5 * length(axis_scale);
+ const float max_dist = 0.5f * length(axis_scale);
sloped_inv_max_dist = desired_slope * 1.f/max_dist;
// Range needs to be between 1.3 to 0.6. When scale is zero then range is
// 1.3 which means no vignette at all because the luminousity difference is
// less than 1/256. Expect input scale to be between 0.0 and 1.0.
- const float neg_range = 0.7*sqrt(desired_scale) - 1.3;
+ const float neg_range = 0.7f*sqrt(desired_scale) - 1.3f;
sloped_neg_range = exp(neg_range * desired_slope);
shade = desired_shade;
opp_shade = 1.f - desired_shade;
}
-void root(const uchar4 *in, uchar4 *out, uint32_t x, uint32_t y) {
+uchar4 __attribute__((kernel)) root(uchar4 in, uint32_t x, uint32_t y) {
// Convert x and y to floating point coordinates with center as origin
- const float4 fin = convert_float4(*in);
+ const float4 fin = convert_float4(in);
const float2 inCoord = {(float)x, (float)y};
const float2 coord = mad(inCoord, inv_dimensions, neg_center);
const float sloped_dist_ratio = length(axis_scale * coord) * sloped_inv_max_dist;
- const float lumen = opp_shade + shade / ( 1.0 + sloped_neg_range * exp(sloped_dist_ratio) );
+ const float lumen = opp_shade + shade / ( 1.0f + sloped_neg_range * exp(sloped_dist_ratio) );
float4 fout;
fout.rgb = fin.rgb * lumen;
fout.w = fin.w;
- *out = convert_uchar4(fout);
+ return convert_uchar4(fout);
}
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette_approx.rsh b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette_approx.rsh
index 7f7bdcf..5668621 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette_approx.rsh
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette_approx.rsh
@@ -31,30 +31,29 @@
else
axis_scale.x = (float)dim_x / (float)dim_y;
- const float max_dist = 0.5 * length(axis_scale);
+ const float max_dist = 0.5f * length(axis_scale);
sloped_inv_max_dist = desired_slope * 1.f/max_dist;
// Range needs to be between 1.3 to 0.6. When scale is zero then range is
// 1.3 which means no vignette at all because the luminousity difference is
// less than 1/256. Expect input scale to be between 0.0 and 1.0.
- const float neg_range = 0.7*sqrt(desired_scale) - 1.3;
+ const float neg_range = 0.7f*sqrt(desired_scale) - 1.3f;
sloped_neg_range = exp(neg_range * desired_slope);
shade = desired_shade;
opp_shade = 1.f - desired_shade;
}
-void root(const uchar4 *in, uchar4 *out, uint32_t x, uint32_t y) {
+uchar4 __attribute__((kernel)) root(uchar4 in, uint32_t x, uint32_t y) {
// Convert x and y to floating point coordinates with center as origin
- const float4 fin = convert_float4(*in);
+ const float4 fin = convert_float4(in);
const float2 inCoord = {(float)x, (float)y};
const float2 coord = mad(inCoord, inv_dimensions, neg_center);
const float sloped_dist_ratio = fast_length(axis_scale * coord) * sloped_inv_max_dist;
- // TODO: add half_exp once implemented
- const float lumen = opp_shade + shade * half_recip(1.f + sloped_neg_range * exp(sloped_dist_ratio));
+ const float lumen = opp_shade + shade * half_recip(1.f + sloped_neg_range * native_exp(sloped_dist_ratio));
float4 fout;
fout.rgb = fin.rgb * lumen;
fout.w = fin.w;
- *out = convert_uchar4(fout);
+ return convert_uchar4(fout);
}
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette_approx_full.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette_approx_full.rs
index 3612509..00cbbc4 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette_approx_full.rs
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette_approx_full.rs
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.image2)
+#include "ip.rsh"
#include "vignette_approx.rsh"
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette_approx_relaxed.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette_approx_relaxed.fs
similarity index 87%
rename from tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette_approx_relaxed.rs
rename to tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette_approx_relaxed.fs
index b714e9b..00cbbc4 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette_approx_relaxed.rs
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette_approx_relaxed.fs
@@ -14,9 +14,7 @@
* limitations under the License.
*/
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.image2)
-#pragma rs_fp_relaxed
+#include "ip.rsh"
#include "vignette_approx.rsh"
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette_full.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette_full.rs
index 5fc2dda..8202c5c 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette_full.rs
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette_full.rs
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.image2)
+#include "ip.rsh"
#include "vignette.rsh"
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette_relaxed.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette_relaxed.fs
similarity index 87%
rename from tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette_relaxed.rs
rename to tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette_relaxed.fs
index 430b685..8202c5c 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette_relaxed.rs
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette_relaxed.fs
@@ -14,9 +14,7 @@
* limitations under the License.
*/
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.image2)
-#pragma rs_fp_relaxed
+#include "ip.rsh"
#include "vignette.rsh"
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/wbalance.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/wbalance.rs
new file mode 100644
index 0000000..6650671
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/wbalance.rs
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ip.rsh"
+//#pragma rs_fp_relaxed
+
+static int histR[256] = {0}, histG[256] = {0}, histB[256] = {0};
+
+rs_allocation histogramSource;
+uint32_t histogramHeight;
+uint32_t histogramWidth;
+
+static float scaleR;
+static float scaleG;
+static float scaleB;
+
+static uchar4 estimateWhite() {
+
+ for (int i = 0; i < 256; i++) {
+ histR[i] = 0; histG[i] = 0; histB[i] = 0;
+ }
+
+ for (uint32_t i = 0; i < histogramHeight; i++) {
+ for (uint32_t j = 0; j < histogramWidth; j++) {
+ uchar4 in = rsGetElementAt_uchar4(histogramSource, j, i);
+ histR[in.r]++;
+ histG[in.g]++;
+ histB[in.b]++;
+ }
+ }
+
+ int min_r = -1, min_g = -1, min_b = -1;
+ int max_r = 0, max_g = 0, max_b = 0;
+ int sum_r = 0, sum_g = 0, sum_b = 0;
+
+ for (int i = 1; i < 255; i++) {
+ int r = histR[i];
+ int g = histG[i];
+ int b = histB[i];
+ sum_r += r;
+ sum_g += g;
+ sum_b += b;
+
+ if (r>0){
+ if (min_r < 0) min_r = i;
+ max_r = i;
+ }
+ if (g>0){
+ if (min_g < 0) min_g = i;
+ max_g = i;
+ }
+ if (b>0){
+ if (min_b < 0) min_b = i;
+ max_b = i;
+ }
+ }
+
+ int sum15r = 0, sum15g = 0, sum15b = 0;
+ int count15r = 0, count15g = 0, count15b = 0;
+ int tmp_r = 0, tmp_g = 0, tmp_b = 0;
+
+ for (int i = 254; i >0; i--) {
+ int r = histR[i];
+ int g = histG[i];
+ int b = histB[i];
+ tmp_r += r;
+ tmp_g += g;
+ tmp_b += b;
+
+ if ((tmp_r > sum_r/20) && (tmp_r < sum_r/5)) {
+ sum15r += r*i;
+ count15r += r;
+ }
+ if ((tmp_g > sum_g/20) && (tmp_g < sum_g/5)) {
+ sum15g += g*i;
+ count15g += g;
+ }
+ if ((tmp_b > sum_b/20) && (tmp_b < sum_b/5)) {
+ sum15b += b*i;
+ count15b += b;
+ }
+
+ }
+
+ uchar4 out;
+
+ if ((count15r>0) && (count15g>0) && (count15b>0) ){
+ out.r = sum15r/count15r;
+ out.g = sum15g/count15g;
+ out.b = sum15b/count15b;
+ }else {
+ out.r = out.g = out.b = 255;
+ }
+
+ return out;
+
+}
+
+void prepareWhiteBalance() {
+ uchar4 estimation = estimateWhite();
+ int minimum = min(estimation.r, min(estimation.g, estimation.b));
+ int maximum = max(estimation.r, max(estimation.g, estimation.b));
+ float avg = (minimum + maximum) / 2.f;
+
+ scaleR = avg/estimation.r;
+ scaleG = avg/estimation.g;
+ scaleB = avg/estimation.b;
+
+}
+
+static unsigned char contrastClamp(int c)
+{
+ int N = 255;
+ c &= ~(c >> 31);
+ c -= N;
+ c &= (c >> 31);
+ c += N;
+ return (unsigned char) c;
+}
+
+void whiteBalanceKernel(const uchar4 *in, uchar4 *out) {
+ float Rc = in->r*scaleR;
+ float Gc = in->g*scaleG;
+ float Bc = in->b*scaleB;
+
+ out->r = contrastClamp(Rc);
+ out->g = contrastClamp(Gc);
+ out->b = contrastClamp(Bc);
+}
diff --git a/tests/RenderScriptTests/ImageProcessing_jb/Android.mk b/tests/RenderScriptTests/ImageProcessing_jb/Android.mk
index 6cdd1c0..20d6be7 100644
--- a/tests/RenderScriptTests/ImageProcessing_jb/Android.mk
+++ b/tests/RenderScriptTests/ImageProcessing_jb/Android.mk
@@ -24,6 +24,6 @@
#LOCAL_STATIC_JAVA_LIBRARIES := android.renderscript
LOCAL_PACKAGE_NAME := ImageProcessingJB
-LOCAL_SDK_VERSION := 16
+LOCAL_SDK_VERSION := 17
include $(BUILD_PACKAGE)
diff --git a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/BWFilter.java b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/BWFilter.java
new file mode 100644
index 0000000..4870ac4
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/BWFilter.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.imagejb;
+
+import java.lang.Math;
+
+
+public class BWFilter extends TestBase {
+ private ScriptC_bwfilter mScript;
+
+ public void createTest(android.content.res.Resources res) {
+ mScript = new ScriptC_bwfilter(mRS);
+ }
+
+ public void runTest() {
+ mScript.invoke_prepareBwFilter(50, 50, 50);
+ mScript.forEach_bwFilterKernel(mInPixelsAllocation, mOutPixelsAllocation);
+ }
+
+}
diff --git a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/Blend.java b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/Blend.java
new file mode 100644
index 0000000..302dc31
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/Blend.java
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.imagejb;
+
+import java.lang.Math;
+import java.lang.Short;
+
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.Matrix4f;
+import android.renderscript.RenderScript;
+import android.renderscript.Script;
+import android.renderscript.ScriptC;
+import android.renderscript.ScriptGroup;
+import android.renderscript.ScriptIntrinsicBlend;
+import android.renderscript.Type;
+import android.util.Log;
+import android.widget.SeekBar;
+import android.widget.TextView;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.view.View;
+import android.widget.Spinner;
+
+public class Blend extends TestBase {
+ private ScriptIntrinsicBlend mBlend;
+ private ScriptC_blend mBlendHelper;
+ private short image1Alpha = 128;
+ private short image2Alpha = 128;
+
+ String mIntrinsicNames[];
+
+ private Allocation image1;
+ private Allocation image2;
+ private int currentIntrinsic = 0;
+
+ private AdapterView.OnItemSelectedListener mIntrinsicSpinnerListener =
+ new AdapterView.OnItemSelectedListener() {
+ public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
+ currentIntrinsic = pos;
+ if (mRS != null) {
+ runTest();
+ act.updateDisplay();
+ }
+ }
+
+ public void onNothingSelected(AdapterView parent) {
+
+ }
+ };
+
+ public void createTest(android.content.res.Resources res) {
+ mBlend = ScriptIntrinsicBlend.create(mRS, Element.U8_4(mRS));
+ mBlendHelper = new ScriptC_blend(mRS);
+ mBlendHelper.set_alpha((short)128);
+
+ image1 = Allocation.createTyped(mRS, mInPixelsAllocation.getType());
+ image2 = Allocation.createTyped(mRS, mInPixelsAllocation2.getType());
+
+ mIntrinsicNames = new String[14];
+ mIntrinsicNames[0] = "Source";
+ mIntrinsicNames[1] = "Destination";
+ mIntrinsicNames[2] = "Source Over";
+ mIntrinsicNames[3] = "Destination Over";
+ mIntrinsicNames[4] = "Source In";
+ mIntrinsicNames[5] = "Destination In";
+ mIntrinsicNames[6] = "Source Out";
+ mIntrinsicNames[7] = "Destination Out";
+ mIntrinsicNames[8] = "Source Atop";
+ mIntrinsicNames[9] = "Destination Atop";
+ mIntrinsicNames[10] = "XOR";
+ mIntrinsicNames[11] = "Add";
+ mIntrinsicNames[12] = "Subtract";
+ mIntrinsicNames[13] = "Multiply";
+ }
+
+ public boolean onSpinner1Setup(Spinner s) {
+ s.setAdapter(new ArrayAdapter<String>(
+ act, R.layout.spinner_layout, mIntrinsicNames));
+ s.setOnItemSelectedListener(mIntrinsicSpinnerListener);
+ return true;
+ }
+
+ public boolean onBar1Setup(SeekBar b, TextView t) {
+ t.setText("Image 1 Alpha");
+ b.setMax(255);
+ b.setProgress(image1Alpha);
+ return true;
+ }
+
+ public void onBar1Changed(int progress) {
+ image1Alpha = (short)progress;
+ }
+
+ public boolean onBar2Setup(SeekBar b, TextView t) {
+ t.setText("Image 2 Alpha");
+ b.setMax(255);
+ b.setProgress(image2Alpha);
+ return true;
+ }
+
+ public void onBar2Changed(int progress) {
+ image2Alpha = (short)progress;
+ }
+
+ public void runTest() {
+ image1.copy2DRangeFrom(0, 0, mInPixelsAllocation.getType().getX(), mInPixelsAllocation.getType().getY(), mInPixelsAllocation, 0, 0);
+ image2.copy2DRangeFrom(0, 0, mInPixelsAllocation2.getType().getX(), mInPixelsAllocation2.getType().getY(), mInPixelsAllocation2, 0, 0);
+
+ mBlendHelper.set_alpha(image1Alpha);
+ mBlendHelper.forEach_setImageAlpha(image1);
+
+ mBlendHelper.set_alpha(image2Alpha);
+ mBlendHelper.forEach_setImageAlpha(image2);
+
+ switch (currentIntrinsic) {
+ case 0:
+ mBlend.forEachSrc(image1, image2);
+ break;
+ case 1:
+ mBlend.forEachDst(image1, image2);
+ break;
+ case 2:
+ mBlend.forEachSrcOver(image1, image2);
+ break;
+ case 3:
+ mBlend.forEachDstOver(image1, image2);
+ break;
+ case 4:
+ mBlend.forEachSrcIn(image1, image2);
+ break;
+ case 5:
+ mBlend.forEachDstIn(image1, image2);
+ break;
+ case 6:
+ mBlend.forEachSrcOut(image1, image2);
+ break;
+ case 7:
+ mBlend.forEachDstOut(image1, image2);
+ break;
+ case 8:
+ mBlend.forEachSrcAtop(image1, image2);
+ break;
+ case 9:
+ mBlend.forEachDstAtop(image1, image2);
+ break;
+ case 10:
+ mBlend.forEachXor(image1, image2);
+ break;
+ case 11:
+ mBlend.forEachAdd(image1, image2);
+ break;
+ case 12:
+ mBlend.forEachSubtract(image1, image2);
+ break;
+ case 13:
+ mBlend.forEachMultiply(image1, image2);
+ break;
+ }
+
+ mOutPixelsAllocation.copy2DRangeFrom(0, 0, image2.getType().getX(), image2.getType().getY(), image2, 0, 0);
+ }
+
+}
diff --git a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/Blur25.java b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/Blur25.java
index d7e918b..90acd00 100644
--- a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/Blur25.java
+++ b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/Blur25.java
@@ -21,12 +21,16 @@
import android.renderscript.Allocation;
import android.renderscript.Element;
import android.renderscript.RenderScript;
+import android.renderscript.ScriptIntrinsicBlur;
import android.renderscript.Type;
import android.util.Log;
import android.widget.SeekBar;
import android.widget.TextView;
public class Blur25 extends TestBase {
+ private boolean mUseIntrinsic = false;
+ private ScriptIntrinsicBlur mIntrinsic;
+
private int MAX_RADIUS = 25;
private ScriptC_threshold mScript;
private float mRadius = MAX_RADIUS;
@@ -35,7 +39,8 @@
private Allocation mScratchPixelsAllocation2;
- public Blur25() {
+ public Blur25(boolean useIntrinsic) {
+ mUseIntrinsic = useIntrinsic;
}
public boolean onBar1Setup(SeekBar b, TextView t) {
@@ -50,7 +55,11 @@
if (mRadius <= 0.10f) {
mRadius = 0.10f;
}
- mScript.invoke_setRadius((int)mRadius);
+ if (mUseIntrinsic) {
+ mIntrinsic.setRadius(mRadius);
+ } else {
+ mScript.invoke_setRadius((int)mRadius);
+ }
}
@@ -58,33 +67,52 @@
int width = mInPixelsAllocation.getType().getX();
int height = mInPixelsAllocation.getType().getY();
- Type.Builder tb = new Type.Builder(mRS, Element.F32_4(mRS));
- tb.setX(width);
- tb.setY(height);
- mScratchPixelsAllocation1 = Allocation.createTyped(mRS, tb.create());
- mScratchPixelsAllocation2 = Allocation.createTyped(mRS, tb.create());
+ if (mUseIntrinsic) {
+ mIntrinsic = ScriptIntrinsicBlur.create(mRS, Element.U8_4(mRS));
+ mIntrinsic.setRadius(MAX_RADIUS);
+ mIntrinsic.setInput(mInPixelsAllocation);
+ } else {
- mScript = new ScriptC_threshold(mRS, res, R.raw.threshold);
- mScript.set_width(width);
- mScript.set_height(height);
- mScript.invoke_setRadius(MAX_RADIUS);
+ Type.Builder tb = new Type.Builder(mRS, Element.F32_4(mRS));
+ tb.setX(width);
+ tb.setY(height);
+ mScratchPixelsAllocation1 = Allocation.createTyped(mRS, tb.create());
+ mScratchPixelsAllocation2 = Allocation.createTyped(mRS, tb.create());
- mScript.set_InPixel(mInPixelsAllocation);
- mScript.set_ScratchPixel1(mScratchPixelsAllocation1);
- mScript.set_ScratchPixel2(mScratchPixelsAllocation2);
+ mScript = new ScriptC_threshold(mRS, res, R.raw.threshold);
+ mScript.set_width(width);
+ mScript.set_height(height);
+ mScript.invoke_setRadius(MAX_RADIUS);
+
+ mScript.set_InPixel(mInPixelsAllocation);
+ mScript.set_ScratchPixel1(mScratchPixelsAllocation1);
+ mScript.set_ScratchPixel2(mScratchPixelsAllocation2);
+ }
}
public void runTest() {
- mScript.forEach_copyIn(mInPixelsAllocation, mScratchPixelsAllocation1);
- mScript.forEach_horz(mScratchPixelsAllocation2);
- mScript.forEach_vert(mOutPixelsAllocation);
+ if (mUseIntrinsic) {
+ mIntrinsic.forEach(mOutPixelsAllocation);
+ } else {
+ mScript.forEach_copyIn(mInPixelsAllocation, mScratchPixelsAllocation1);
+ mScript.forEach_horz(mScratchPixelsAllocation2);
+ mScript.forEach_vert(mOutPixelsAllocation);
+ }
}
public void setupBenchmark() {
- mScript.invoke_setRadius(MAX_RADIUS);
+ if (mUseIntrinsic) {
+ mIntrinsic.setRadius(MAX_RADIUS);
+ } else {
+ mScript.invoke_setRadius(MAX_RADIUS);
+ }
}
public void exitBenchmark() {
- mScript.invoke_setRadius((int)mRadius);
+ if (mUseIntrinsic) {
+ mIntrinsic.setRadius(mRadius);
+ } else {
+ mScript.invoke_setRadius((int)mRadius);
+ }
}
}
diff --git a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/ColorMatrix.java b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/ColorMatrix.java
index 62ca694..5053d4d 100644
--- a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/ColorMatrix.java
+++ b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/ColorMatrix.java
@@ -24,14 +24,19 @@
import android.renderscript.RenderScript;
import android.renderscript.Script;
import android.renderscript.ScriptC;
+import android.renderscript.ScriptGroup;
+import android.renderscript.ScriptIntrinsicColorMatrix;
import android.renderscript.Type;
import android.util.Log;
public class ColorMatrix extends TestBase {
private ScriptC_colormatrix mScript;
+ private ScriptIntrinsicColorMatrix mIntrinsic;
+ private boolean mUseIntrinsic;
private boolean mUseGrey;
- public ColorMatrix(boolean useGrey) {
+ public ColorMatrix(boolean useIntrinsic, boolean useGrey) {
+ mUseIntrinsic = useIntrinsic;
mUseGrey = useGrey;
}
@@ -41,12 +46,25 @@
m.set(1, 1, 0.9f);
m.set(1, 2, 0.2f);
- mScript = new ScriptC_colormatrix(mRS, res, R.raw.colormatrix);
- mScript.invoke_setMatrix(m);
+ if (mUseIntrinsic) {
+ mIntrinsic = ScriptIntrinsicColorMatrix.create(mRS, Element.U8_4(mRS));
+ if (mUseGrey) {
+ mIntrinsic.setGreyscale();
+ } else {
+ mIntrinsic.setColorMatrix(m);
+ }
+ } else {
+ mScript = new ScriptC_colormatrix(mRS, res, R.raw.colormatrix);
+ mScript.invoke_setMatrix(m);
+ }
}
public void runTest() {
- mScript.forEach_root(mInPixelsAllocation, mOutPixelsAllocation);
+ if (mUseIntrinsic) {
+ mIntrinsic.forEach(mInPixelsAllocation, mOutPixelsAllocation);
+ } else {
+ mScript.forEach_root(mInPixelsAllocation, mOutPixelsAllocation);
+ }
}
}
diff --git a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/Contrast.java b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/Contrast.java
new file mode 100644
index 0000000..20b28ff
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/Contrast.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.imagejb;
+
+import java.lang.Math;
+
+import android.renderscript.Allocation;
+
+public class Contrast extends TestBase {
+ private ScriptC_contrast mScript;
+
+ public void createTest(android.content.res.Resources res) {
+ mScript = new ScriptC_contrast(mRS);
+ }
+
+ public void runTest() {
+ mScript.invoke_setBright(50.f);
+ mScript.forEach_contrast(mInPixelsAllocation, mOutPixelsAllocation);
+ }
+
+}
diff --git a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/Convolve3x3.java b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/Convolve3x3.java
index 6673032..d7acf4a 100644
--- a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/Convolve3x3.java
+++ b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/Convolve3x3.java
@@ -24,16 +24,21 @@
import android.renderscript.RenderScript;
import android.renderscript.Script;
import android.renderscript.ScriptC;
+import android.renderscript.ScriptGroup;
+import android.renderscript.ScriptIntrinsicConvolve3x3;
import android.renderscript.Type;
import android.util.Log;
public class Convolve3x3 extends TestBase {
private ScriptC_convolve3x3 mScript;
+ private ScriptIntrinsicConvolve3x3 mIntrinsic;
private int mWidth;
private int mHeight;
+ private boolean mUseIntrinsic;
- public Convolve3x3() {
+ public Convolve3x3(boolean useIntrinsic) {
+ mUseIntrinsic = useIntrinsic;
}
public void createTest(android.content.res.Resources res) {
@@ -45,11 +50,17 @@
f[3] = -1.f; f[4] = 5.f; f[5] = -1.f;
f[6] = 0.f; f[7] = -1.f; f[8] = 0.f;
- mScript = new ScriptC_convolve3x3(mRS, res, R.raw.convolve3x3);
- mScript.set_gCoeffs(f);
- mScript.set_gIn(mInPixelsAllocation);
- mScript.set_gWidth(mWidth);
- mScript.set_gHeight(mHeight);
+ if (mUseIntrinsic) {
+ mIntrinsic = ScriptIntrinsicConvolve3x3.create(mRS, Element.U8_4(mRS));
+ mIntrinsic.setCoefficients(f);
+ mIntrinsic.setInput(mInPixelsAllocation);
+ } else {
+ mScript = new ScriptC_convolve3x3(mRS, res, R.raw.convolve3x3);
+ mScript.set_gCoeffs(f);
+ mScript.set_gIn(mInPixelsAllocation);
+ mScript.set_gWidth(mWidth);
+ mScript.set_gHeight(mHeight);
+ }
}
public void runTest() {
diff --git a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/Convolve5x5.java b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/Convolve5x5.java
index 895d459..d1dbb1f 100644
--- a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/Convolve5x5.java
+++ b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/Convolve5x5.java
@@ -24,16 +24,21 @@
import android.renderscript.RenderScript;
import android.renderscript.Script;
import android.renderscript.ScriptC;
+import android.renderscript.ScriptGroup;
+import android.renderscript.ScriptIntrinsicConvolve5x5;
import android.renderscript.Type;
import android.util.Log;
public class Convolve5x5 extends TestBase {
private ScriptC_convolve5x5 mScript;
+ private ScriptIntrinsicConvolve5x5 mIntrinsic;
private int mWidth;
private int mHeight;
+ private boolean mUseIntrinsic;
- public Convolve5x5() {
+ public Convolve5x5(boolean useIntrinsic) {
+ mUseIntrinsic = useIntrinsic;
}
public void createTest(android.content.res.Resources res) {
@@ -59,15 +64,25 @@
f[15]= -3.f; f[16]= 0.f; f[17]= 6.f; f[18]= 0.f; f[19]= -3.f;
f[20]= -1.f; f[21]= -3.f; f[22]= -4.f; f[23]= -3.f; f[24]= -1.f;
- mScript = new ScriptC_convolve5x5(mRS, res, R.raw.convolve5x5);
- mScript.set_gCoeffs(f);
- mScript.set_gIn(mInPixelsAllocation);
- mScript.set_gWidth(mWidth);
- mScript.set_gHeight(mHeight);
+ if (mUseIntrinsic) {
+ mIntrinsic = ScriptIntrinsicConvolve5x5.create(mRS, Element.U8_4(mRS));
+ mIntrinsic.setCoefficients(f);
+ mIntrinsic.setInput(mInPixelsAllocation);
+ } else {
+ mScript = new ScriptC_convolve5x5(mRS, res, R.raw.convolve5x5);
+ mScript.set_gCoeffs(f);
+ mScript.set_gIn(mInPixelsAllocation);
+ mScript.set_gWidth(mWidth);
+ mScript.set_gHeight(mHeight);
+ }
}
public void runTest() {
- mScript.forEach_root(mOutPixelsAllocation);
+ if (mUseIntrinsic) {
+ mIntrinsic.forEach(mOutPixelsAllocation);
+ } else {
+ mScript.forEach_root(mOutPixelsAllocation);
+ }
}
}
diff --git a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/CrossProcess.java b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/CrossProcess.java
new file mode 100644
index 0000000..75ee39b
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/CrossProcess.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.imagejb;
+
+import java.lang.Math;
+
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.RenderScript;
+import android.renderscript.ScriptIntrinsicLUT;
+import android.util.Log;
+
+public class CrossProcess extends TestBase {
+ private ScriptIntrinsicLUT mIntrinsic;
+
+ public void createTest(android.content.res.Resources res) {
+ mIntrinsic = ScriptIntrinsicLUT.create(mRS, Element.U8_4(mRS));
+ for (int ct=0; ct < 256; ct++) {
+ float f = ((float)ct) / 255.f;
+
+ float r = f;
+ if (r < 0.5f) {
+ r = 4.0f * r * r * r;
+ } else {
+ r = 1.0f - r;
+ r = 1.0f - (4.0f * r * r * r);
+ }
+ mIntrinsic.setRed(ct, (int)(r * 255.f + 0.5f));
+
+ float g = f;
+ if (g < 0.5f) {
+ g = 2.0f * g * g;
+ } else {
+ g = 1.0f - g;
+ g = 1.0f - (2.0f * g * g);
+ }
+ mIntrinsic.setGreen(ct, (int)(g * 255.f + 0.5f));
+
+ float b = f * 0.5f + 0.25f;
+ mIntrinsic.setBlue(ct, (int)(b * 255.f + 0.5f));
+ }
+
+ }
+
+ public void runTest() {
+ mIntrinsic.forEach(mInPixelsAllocation, mOutPixelsAllocation);
+ }
+
+}
diff --git a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/Exposure.java b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/Exposure.java
new file mode 100644
index 0000000..ddde96f
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/Exposure.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.imagejb;
+
+import java.lang.Math;
+
+import android.renderscript.Allocation;
+
+public class Exposure extends TestBase {
+ private ScriptC_exposure mScript;
+
+ public void createTest(android.content.res.Resources res) {
+ mScript = new ScriptC_exposure(mRS);
+ }
+
+ public void runTest() {
+ mScript.invoke_setBright(50.f);
+ mScript.forEach_exposure(mInPixelsAllocation, mOutPixelsAllocation);
+ }
+
+}
diff --git a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/Fisheye.java b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/Fisheye.java
new file mode 100644
index 0000000..114839c
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/Fisheye.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.imagejb;
+
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.Sampler;
+import android.renderscript.Type;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+public class Fisheye extends TestBase {
+ private ScriptC_fisheye_full mScript_full = null;
+ private ScriptC_fisheye_relaxed mScript_relaxed = null;
+ private ScriptC_fisheye_approx_full mScript_approx_full = null;
+ private ScriptC_fisheye_approx_relaxed mScript_approx_relaxed = null;
+ private final boolean approx;
+ private final boolean relaxed;
+ private float center_x = 0.5f;
+ private float center_y = 0.5f;
+ private float scale = 0.5f;
+
+ public Fisheye(boolean approx, boolean relaxed) {
+ this.approx = approx;
+ this.relaxed = relaxed;
+ }
+
+ public boolean onBar1Setup(SeekBar b, TextView t) {
+ t.setText("Scale");
+ b.setMax(100);
+ b.setProgress(25);
+ return true;
+ }
+ public boolean onBar2Setup(SeekBar b, TextView t) {
+ t.setText("Shift center X");
+ b.setMax(100);
+ b.setProgress(50);
+ return true;
+ }
+ public boolean onBar3Setup(SeekBar b, TextView t) {
+ t.setText("Shift center Y");
+ b.setMax(100);
+ b.setProgress(50);
+ return true;
+ }
+
+ public void onBar1Changed(int progress) {
+ scale = progress / 50.0f;
+ do_init();
+ }
+ public void onBar2Changed(int progress) {
+ center_x = progress / 100.0f;
+ do_init();
+ }
+ public void onBar3Changed(int progress) {
+ center_y = progress / 100.0f;
+ do_init();
+ }
+
+ private void do_init() {
+ if (approx) {
+ if (relaxed)
+ mScript_approx_relaxed.invoke_init_filter(
+ mInPixelsAllocation.getType().getX(),
+ mInPixelsAllocation.getType().getY(), center_x,
+ center_y, scale);
+ else
+ mScript_approx_full.invoke_init_filter(
+ mInPixelsAllocation.getType().getX(),
+ mInPixelsAllocation.getType().getY(), center_x,
+ center_y, scale);
+ } else if (relaxed)
+ mScript_relaxed.invoke_init_filter(
+ mInPixelsAllocation.getType().getX(),
+ mInPixelsAllocation.getType().getY(), center_x, center_y,
+ scale);
+ else
+ mScript_full.invoke_init_filter(
+ mInPixelsAllocation.getType().getX(),
+ mInPixelsAllocation.getType().getY(), center_x, center_y,
+ scale);
+ }
+
+ public void createTest(android.content.res.Resources res) {
+ if (approx) {
+ if (relaxed) {
+ mScript_approx_relaxed = new ScriptC_fisheye_approx_relaxed(mRS,
+ res, R.raw.fisheye_approx_relaxed);
+ mScript_approx_relaxed.set_in_alloc(mInPixelsAllocation);
+ mScript_approx_relaxed.set_sampler(Sampler.CLAMP_LINEAR(mRS));
+ } else {
+ mScript_approx_full = new ScriptC_fisheye_approx_full(mRS, res,
+ R.raw.fisheye_approx_full);
+ mScript_approx_full.set_in_alloc(mInPixelsAllocation);
+ mScript_approx_full.set_sampler(Sampler.CLAMP_LINEAR(mRS));
+ }
+ } else if (relaxed) {
+ mScript_relaxed = new ScriptC_fisheye_relaxed(mRS, res,
+ R.raw.fisheye_relaxed);
+ mScript_relaxed.set_in_alloc(mInPixelsAllocation);
+ mScript_relaxed.set_sampler(Sampler.CLAMP_LINEAR(mRS));
+ } else {
+ mScript_full = new ScriptC_fisheye_full(mRS, res,
+ R.raw.fisheye_full);
+ mScript_full.set_in_alloc(mInPixelsAllocation);
+ mScript_full.set_sampler(Sampler.CLAMP_LINEAR(mRS));
+ }
+ do_init();
+ }
+
+ public void runTest() {
+ if (approx) {
+ if (relaxed)
+ mScript_approx_relaxed.forEach_root(mOutPixelsAllocation);
+ else
+ mScript_approx_full.forEach_root(mOutPixelsAllocation);
+ } else if (relaxed)
+ mScript_relaxed.forEach_root(mOutPixelsAllocation);
+ else
+ mScript_full.forEach_root(mOutPixelsAllocation);
+ }
+
+}
+
diff --git a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/GroupTest.java b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/GroupTest.java
new file mode 100644
index 0000000..3e5175a
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/GroupTest.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.imagejb;
+
+import java.lang.Math;
+
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.RenderScript;
+import android.renderscript.ScriptIntrinsicConvolve3x3;
+import android.renderscript.ScriptIntrinsicColorMatrix;
+import android.renderscript.Type;
+import android.renderscript.Matrix4f;
+import android.renderscript.ScriptGroup;
+import android.util.Log;
+
+public class GroupTest extends TestBase {
+ private ScriptIntrinsicConvolve3x3 mConvolve;
+ private ScriptIntrinsicColorMatrix mMatrix;
+
+ private Allocation mScratchPixelsAllocation1;
+ private ScriptGroup mGroup;
+
+ private int mWidth;
+ private int mHeight;
+ private boolean mUseNative;
+
+
+ public GroupTest(boolean useNative) {
+ mUseNative = useNative;
+ }
+
+ public void createTest(android.content.res.Resources res) {
+ mWidth = mInPixelsAllocation.getType().getX();
+ mHeight = mInPixelsAllocation.getType().getY();
+
+ mConvolve = ScriptIntrinsicConvolve3x3.create(mRS, Element.U8_4(mRS));
+ mMatrix = ScriptIntrinsicColorMatrix.create(mRS, Element.U8_4(mRS));
+
+ float f[] = new float[9];
+ f[0] = 0.f; f[1] = -1.f; f[2] = 0.f;
+ f[3] = -1.f; f[4] = 5.f; f[5] = -1.f;
+ f[6] = 0.f; f[7] = -1.f; f[8] = 0.f;
+ mConvolve.setCoefficients(f);
+
+ Matrix4f m = new Matrix4f();
+ m.set(1, 0, 0.2f);
+ m.set(1, 1, 0.9f);
+ m.set(1, 2, 0.2f);
+ mMatrix.setColorMatrix(m);
+
+ Type.Builder tb = new Type.Builder(mRS, Element.U8_4(mRS));
+ tb.setX(mWidth);
+ tb.setY(mHeight);
+ Type connect = tb.create();
+
+ if (mUseNative) {
+ ScriptGroup.Builder b = new ScriptGroup.Builder(mRS);
+ b.addKernel(mConvolve.getKernelID());
+ b.addKernel(mMatrix.getKernelID());
+ b.addConnection(connect, mConvolve.getKernelID(), mMatrix.getKernelID());
+ mGroup = b.create();
+ } else {
+ mScratchPixelsAllocation1 = Allocation.createTyped(mRS, connect);
+ }
+ }
+
+ public void runTest() {
+ mConvolve.setInput(mInPixelsAllocation);
+ if (mUseNative) {
+ mGroup.setOutput(mMatrix.getKernelID(), mOutPixelsAllocation);
+ mGroup.execute();
+ } else {
+ mConvolve.forEach(mScratchPixelsAllocation1);
+ mMatrix.forEach(mScratchPixelsAllocation1, mOutPixelsAllocation);
+ }
+ }
+
+}
diff --git a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/ImageProcessingActivityJB.java b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/ImageProcessingActivityJB.java
index b3b06d4..93937ef 100644
--- a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/ImageProcessingActivityJB.java
+++ b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/ImageProcessingActivityJB.java
@@ -23,14 +23,7 @@
import android.graphics.BitmapFactory;
import android.graphics.Bitmap;
import android.graphics.Canvas;
-import android.renderscript.ScriptC;
-import android.renderscript.RenderScript;
-import android.renderscript.Type;
-import android.renderscript.Allocation;
-import android.renderscript.Element;
-import android.renderscript.Script;
import android.view.SurfaceView;
-import android.view.SurfaceHolder;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
@@ -39,13 +32,14 @@
import android.widget.TextView;
import android.view.View;
import android.util.Log;
-import java.lang.Math;
+import android.renderscript.ScriptC;
+import android.renderscript.RenderScript;
+import android.renderscript.Type;
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.Script;
import android.os.Environment;
-import android.app.Instrumentation;
-import android.content.Context;
-import android.content.Intent;
-import android.net.Uri;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
@@ -54,12 +48,70 @@
public class ImageProcessingActivityJB extends Activity
implements SeekBar.OnSeekBarChangeListener {
private final String TAG = "Img";
- private final String RESULT_FILE = "image_processing_result.csv";
+ public final String RESULT_FILE = "image_processing_result.csv";
+
+ RenderScript mRS;
+ Allocation mInPixelsAllocation;
+ Allocation mInPixelsAllocation2;
+ Allocation mOutPixelsAllocation;
+
+ /**
+ * Define enum type for test names
+ */
+ public enum TestName {
+ // totally there are 38 test cases
+ LEVELS_VEC3_RELAXED ("Levels Vec3 Relaxed"),
+ LEVELS_VEC4_RELAXED ("Levels Vec4 Relaxed"),
+ LEVELS_VEC3_FULL ("Levels Vec3 Full"),
+ LEVELS_VEC4_FULL ("Levels Vec4 Full"),
+ BLUR_RADIUS_25 ("Blur radius 25"),
+ INTRINSIC_BLUE_RADIUS_25 ("Intrinsic Blur radius 25"),
+ GREYSCALE ("Greyscale"),
+ GRAIN ("Grain"),
+ FISHEYE_FULL ("Fisheye Full"),
+ FISHEYE_RELAXED ("Fisheye Relaxed"),
+ FISHEYE_APPROXIMATE_FULL ("Fisheye Approximate Full"),
+ FISHEYE_APPROXIMATE_RELAXED ("Fisheye Approximate Relaxed"),
+ VIGNETTE_FULL ("Vignette Full"),
+ VIGNETTE_RELAXED ("Vignette Relaxed"),
+ VIGNETTE_APPROXIMATE_FULL ("Vignette Approximate Full"),
+ VIGNETTE_APPROXIMATE_RELAXED ("Vignette Approximate Relaxed"),
+ GROUP_TEST_EMULATED ("Group Test (emulated)"),
+ GROUP_TEST_NATIVE ("Group Test (native)"),
+ CONVOLVE_3X3 ("Convolve 3x3"),
+ INTRINSICS_CONVOLVE_3X3 ("Intrinsics Convolve 3x3"),
+ COLOR_MATRIX ("ColorMatrix"),
+ INTRINSICS_COLOR_MATRIX ("Intrinsics ColorMatrix"),
+ INTRINSICS_COLOR_MATRIX_GREY ("Intrinsics ColorMatrix Grey"),
+ COPY ("Copy"),
+ CROSS_PROCESS_USING_LUT ("CrossProcess (using LUT)"),
+ CONVOLVE_5X5 ("Convolve 5x5"),
+ INTRINSICS_CONVOLVE_5X5 ("Intrinsics Convolve 5x5"),
+ MANDELBROT ("Mandelbrot"),
+ INTRINSICS_BLEND ("Intrinsics Blend"),
+ VIBRANCE ("Vibrance"),
+ BW_FILTER ("BW Filter"),
+ SHADOWS ("Shadows"),
+ CONTRAST ("Contrast"),
+ EXPOSURE ("Exposure"),
+ WHITE_BALANCE ("White Balance");
+
+
+ private final String name;
+
+ private TestName(String s) {
+ name = s;
+ }
+
+ // return quoted string as displayed test name
+ public String toString() {
+ return name;
+ }
+ }
Bitmap mBitmapIn;
Bitmap mBitmapIn2;
Bitmap mBitmapOut;
- String mTestNames[];
private Spinner mSpinner;
private SeekBar mBar1;
@@ -91,12 +143,15 @@
}
private Handler mHandler = new Handler() {
+ // Allow the filter to complete without blocking the UI
+ // thread. When the message arrives that the op is complete
+ // we will either mark completion or start a new filter if
+ // more work is ready. Either way, display the result.
@Override
public void handleMessage(Message msg) {
mTest.updateBitmap(mBitmapOut);
mDisplayView.invalidate();
- android.util.Log.v("Img", "mRunCount hdl " + mRunCount);
boolean doTest = false;
synchronized(this) {
if (mRunCount > 0) {
@@ -175,56 +230,119 @@
}
- void changeTest(int testID) {
+ void changeTest(TestName testName) {
if (mTest != null) {
mTest.destroy();
}
- switch(testID) {
- case 0:
+ switch(testName) {
+ case LEVELS_VEC3_RELAXED:
mTest = new LevelsV4(false, false);
break;
- case 1:
+ case LEVELS_VEC4_RELAXED:
mTest = new LevelsV4(false, true);
break;
- case 2:
+ case LEVELS_VEC3_FULL:
mTest = new LevelsV4(true, false);
break;
- case 3:
+ case LEVELS_VEC4_FULL:
mTest = new LevelsV4(true, true);
break;
- case 4:
- mTest = new Blur25();
+ case BLUR_RADIUS_25:
+ mTest = new Blur25(false);
break;
- case 5:
+ case INTRINSIC_BLUE_RADIUS_25:
+ mTest = new Blur25(true);
+ break;
+ case GREYSCALE:
mTest = new Greyscale();
break;
- case 6:
+ case GRAIN:
mTest = new Grain();
break;
- case 7:
- mTest = new Vignette(false);
+ case FISHEYE_FULL:
+ mTest = new Fisheye(false, false);
break;
- case 8:
- mTest = new Vignette(true);
+ case FISHEYE_RELAXED:
+ mTest = new Fisheye(false, true);
break;
- case 9:
- mTest = new Convolve3x3();
+ case FISHEYE_APPROXIMATE_FULL:
+ mTest = new Fisheye(true, false);
break;
- case 10:
- mTest = new ColorMatrix(false);
+ case FISHEYE_APPROXIMATE_RELAXED:
+ mTest = new Fisheye(true, true);
break;
- case 11:
+ case VIGNETTE_FULL:
+ mTest = new Vignette(false, false);
+ break;
+ case VIGNETTE_RELAXED:
+ mTest = new Vignette(false, true);
+ break;
+ case VIGNETTE_APPROXIMATE_FULL:
+ mTest = new Vignette(true, false);
+ break;
+ case VIGNETTE_APPROXIMATE_RELAXED:
+ mTest = new Vignette(true, true);
+ break;
+ case GROUP_TEST_EMULATED:
+ mTest = new GroupTest(false);
+ break;
+ case GROUP_TEST_NATIVE:
+ mTest = new GroupTest(true);
+ break;
+ case CONVOLVE_3X3:
+ mTest = new Convolve3x3(false);
+ break;
+ case INTRINSICS_CONVOLVE_3X3:
+ mTest = new Convolve3x3(true);
+ break;
+ case COLOR_MATRIX:
+ mTest = new ColorMatrix(false, false);
+ break;
+ case INTRINSICS_COLOR_MATRIX:
+ mTest = new ColorMatrix(true, false);
+ break;
+ case INTRINSICS_COLOR_MATRIX_GREY:
+ mTest = new ColorMatrix(true, true);
+ break;
+ case COPY:
mTest = new Copy();
break;
- case 12:
- mTest = new Convolve5x5();
+ case CROSS_PROCESS_USING_LUT:
+ mTest = new CrossProcess();
break;
- case 13:
+ case CONVOLVE_5X5:
+ mTest = new Convolve5x5(false);
+ break;
+ case INTRINSICS_CONVOLVE_5X5:
+ mTest = new Convolve5x5(true);
+ break;
+ case MANDELBROT:
mTest = new Mandelbrot();
break;
+ case INTRINSICS_BLEND:
+ mTest = new Blend();
+ break;
+ case VIBRANCE:
+ mTest = new Vibrance();
+ break;
+ case BW_FILTER:
+ mTest = new BWFilter();
+ break;
+ case SHADOWS:
+ mTest = new Shadows();
+ break;
+ case CONTRAST:
+ mTest = new Contrast();
+ break;
+ case EXPOSURE:
+ mTest = new Exposure();
+ break;
+ case WHITE_BALANCE:
+ mTest = new WhiteBalance();
+ break;
}
- mTest.createBaseTest(this, mBitmapIn, mBitmapIn2);
+ mTest.createBaseTest(this, mBitmapIn, mBitmapIn2, mBitmapOut);
setupBars();
mTest.runTest();
@@ -233,30 +351,14 @@
}
void setupTests() {
- mTestNames = new String[14];
- mTestNames[0] = "Levels Vec3 Relaxed";
- mTestNames[1] = "Levels Vec4 Relaxed";
- mTestNames[2] = "Levels Vec3 Full";
- mTestNames[3] = "Levels Vec4 Full";
- mTestNames[4] = "Blur radius 25";
- mTestNames[5] = "Greyscale";
- mTestNames[6] = "Grain";
- mTestNames[7] = "Vignette Full";
- mTestNames[8] = "Vignette Relaxed";
- mTestNames[9] = "Convolve 3x3";
- mTestNames[10] = "ColorMatrix";
- mTestNames[11] = "Copy";
- mTestNames[12] = "Convolve 5x5";
- mTestNames[13] = "Mandelbrot";
-
- mTestSpinner.setAdapter(new ArrayAdapter<String>(
- this, R.layout.spinner_layout, mTestNames));
+ mTestSpinner.setAdapter(new ArrayAdapter<TestName>(
+ this, R.layout.spinner_layout, TestName.values()));
}
private AdapterView.OnItemSelectedListener mTestSpinnerListener =
new AdapterView.OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
- changeTest(pos);
+ changeTest(TestName.values()[pos]);
}
public void onNothingSelected(AdapterView parent) {
@@ -305,8 +407,15 @@
mBenchmarkResult = (TextView) findViewById(R.id.benchmarkText);
mBenchmarkResult.setText("Result: not run");
+
+ mRS = RenderScript.create(this);
+ mInPixelsAllocation = Allocation.createFromBitmap(mRS, mBitmapIn);
+ mInPixelsAllocation2 = Allocation.createFromBitmap(mRS, mBitmapIn2);
+ mOutPixelsAllocation = Allocation.createFromBitmap(mRS, mBitmapOut);
+
+
setupTests();
- changeTest(0);
+ changeTest(TestName.LEVELS_VEC3_RELAXED);
}
@@ -337,10 +446,10 @@
try {
BufferedWriter rsWriter = new BufferedWriter(new FileWriter(resultFile));
Log.v(TAG, "Saved results in: " + resultFile.getAbsolutePath());
- for (int i = 0; i < mTestNames.length; i++ ) {
- changeTest(i);
+ for (TestName tn: TestName.values()) {
+ changeTest(tn);
float t = getBenchmark();
- String s = new String("" + mTestNames[i] + ", " + t);
+ String s = new String("" + tn.toString() + ", " + t);
rsWriter.write(s + "\n");
Log.v(TAG, "Test " + s + "ms\n");
}
@@ -348,7 +457,7 @@
} catch (IOException e) {
Log.v(TAG, "Unable to write result file " + e.getMessage());
}
- changeTest(0);
+ changeTest(TestName.LEVELS_VEC3_RELAXED);
}
// For benchmark test
@@ -365,7 +474,6 @@
mTest.finish();
} while (t > java.lang.System.currentTimeMillis());
-
//Log.v(TAG, "Benchmarking");
int ct = 0;
t = java.lang.System.currentTimeMillis();
diff --git a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/Shadows.java b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/Shadows.java
new file mode 100644
index 0000000..d246d59
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/Shadows.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.imagejb;
+
+import java.lang.Math;
+
+import android.renderscript.Allocation;
+
+public class Shadows extends TestBase {
+ private ScriptC_shadows mScript;
+
+ public void createTest(android.content.res.Resources res) {
+ mScript = new ScriptC_shadows(mRS);
+ }
+
+ public void runTest() {
+ mScript.invoke_prepareShadows(50.f);
+ mScript.forEach_shadowsKernel(mInPixelsAllocation, mOutPixelsAllocation);
+ }
+
+}
diff --git a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/TestBase.java b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/TestBase.java
index ed22578..9ae366a 100644
--- a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/TestBase.java
+++ b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/TestBase.java
@@ -106,26 +106,20 @@
return false;
}
- public final void createBaseTest(ImageProcessingActivityJB ipact, Bitmap b, Bitmap b2) {
+ public final void createBaseTest(ImageProcessingActivityJB ipact, Bitmap b, Bitmap b2, Bitmap outb) {
act = ipact;
- mRS = RenderScript.create(act);
+ mRS = ipact.mRS;
mRS.setMessageHandler(new MessageProcessor(act));
- mMessageScript = new ScriptC_msg(mRS);
- mInPixelsAllocation = Allocation.createFromBitmap(mRS, b,
- Allocation.MipmapControl.MIPMAP_NONE,
- Allocation.USAGE_SCRIPT);
- mInPixelsAllocation2 = Allocation.createFromBitmap(mRS, b2,
- Allocation.MipmapControl.MIPMAP_NONE,
- Allocation.USAGE_SCRIPT);
- mOutPixelsAllocation = Allocation.createFromBitmap(mRS, b,
- Allocation.MipmapControl.MIPMAP_NONE,
- Allocation.USAGE_SCRIPT);
+
+ mInPixelsAllocation = ipact.mInPixelsAllocation;
+ mInPixelsAllocation2 = ipact.mInPixelsAllocation2;
+ mOutPixelsAllocation = ipact.mOutPixelsAllocation;
+
createTest(act.getResources());
}
// Must override
public void createTest(android.content.res.Resources res) {
- android.util.Log.e("img", "implement createTest");
}
// Must override
@@ -133,7 +127,6 @@
}
final public void runTestSendMessage() {
- android.util.Log.v("Img", "run");
runTest();
mMessageScript.invoke_sendMsg();
}
@@ -143,8 +136,7 @@
}
public void destroy() {
- mRS.destroy();
- mRS = null;
+ mRS.setMessageHandler(null);
}
public void updateBitmap(Bitmap b) {
diff --git a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/Vibrance.java b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/Vibrance.java
new file mode 100644
index 0000000..09822a9
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/Vibrance.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.imagejb;
+
+import java.lang.Math;
+
+import android.renderscript.Allocation;
+
+public class Vibrance extends TestBase {
+ private ScriptC_vibrance mScript;
+
+ public void createTest(android.content.res.Resources res) {
+ mScript = new ScriptC_vibrance(mRS);
+ }
+
+ public void runTest() {
+ mScript.set_vibrance(50.f);
+ mScript.invoke_prepareVibrance();
+ mScript.forEach_vibranceKernel(mInPixelsAllocation, mOutPixelsAllocation);
+ }
+
+}
diff --git a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/Vignette.java b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/Vignette.java
index 487cd63..9451757 100644
--- a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/Vignette.java
+++ b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/Vignette.java
@@ -26,6 +26,9 @@
public class Vignette extends TestBase {
private ScriptC_vignette_full mScript_full = null;
private ScriptC_vignette_relaxed mScript_relaxed = null;
+ private ScriptC_vignette_approx_full mScript_approx_full = null;
+ private ScriptC_vignette_approx_relaxed mScript_approx_relaxed = null;
+ private final boolean approx;
private final boolean relaxed;
private float center_x = 0.5f;
private float center_y = 0.5f;
@@ -33,7 +36,8 @@
private float shade = 0.5f;
private float slope = 20.0f;
- public Vignette(boolean relaxed) {
+ public Vignette(boolean approx, boolean relaxed) {
+ this.approx = approx;
this.relaxed = relaxed;
}
@@ -90,7 +94,18 @@
}
private void do_init() {
- if (relaxed)
+ if (approx) {
+ if (relaxed)
+ mScript_approx_relaxed.invoke_init_vignette(
+ mInPixelsAllocation.getType().getX(),
+ mInPixelsAllocation.getType().getY(), center_x,
+ center_y, scale, shade, slope);
+ else
+ mScript_approx_full.invoke_init_vignette(
+ mInPixelsAllocation.getType().getX(),
+ mInPixelsAllocation.getType().getY(), center_x,
+ center_y, scale, shade, slope);
+ } else if (relaxed)
mScript_relaxed.invoke_init_vignette(
mInPixelsAllocation.getType().getX(),
mInPixelsAllocation.getType().getY(), center_x, center_y,
@@ -103,7 +118,14 @@
}
public void createTest(android.content.res.Resources res) {
- if (relaxed)
+ if (approx) {
+ if (relaxed)
+ mScript_approx_relaxed = new ScriptC_vignette_approx_relaxed(
+ mRS, res, R.raw.vignette_approx_relaxed);
+ else
+ mScript_approx_full = new ScriptC_vignette_approx_full(
+ mRS, res, R.raw.vignette_approx_full);
+ } else if (relaxed)
mScript_relaxed = new ScriptC_vignette_relaxed(mRS, res,
R.raw.vignette_relaxed);
else
@@ -113,7 +135,14 @@
}
public void runTest() {
- if (relaxed)
+ if (approx) {
+ if (relaxed)
+ mScript_approx_relaxed.forEach_root(mInPixelsAllocation,
+ mOutPixelsAllocation);
+ else
+ mScript_approx_full.forEach_root(mInPixelsAllocation,
+ mOutPixelsAllocation);
+ } else if (relaxed)
mScript_relaxed.forEach_root(mInPixelsAllocation,
mOutPixelsAllocation);
else
diff --git a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/WhiteBalance.java b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/WhiteBalance.java
new file mode 100644
index 0000000..f15aaf5b
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/WhiteBalance.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.imagejb;
+
+import java.lang.Math;
+
+import android.renderscript.Allocation;
+
+public class WhiteBalance extends TestBase {
+ private ScriptC_wbalance mScript;
+
+ public void createTest(android.content.res.Resources res) {
+ mScript = new ScriptC_wbalance(mRS);
+ }
+
+ public void runTest() {
+ mScript.set_histogramSource(mInPixelsAllocation);
+ mScript.set_histogramWidth(mInPixelsAllocation.getType().getX());
+ mScript.set_histogramHeight(mInPixelsAllocation.getType().getY());
+ mScript.invoke_prepareWhiteBalance();
+ mScript.forEach_whiteBalanceKernel(mInPixelsAllocation, mOutPixelsAllocation);
+ }
+
+}
diff --git a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/blend.rs b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/blend.rs
new file mode 100644
index 0000000..9ec1246
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/blend.rs
@@ -0,0 +1,23 @@
+// Copyright (C) 2011 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "ip.rsh"
+
+uchar alpha = 0x0;
+
+void setImageAlpha(uchar4 *v_out, uint32_t x, uint32_t y) {
+ v_out->rgba = convert_uchar4((convert_uint4(v_out->rgba) * alpha) >> (uint4)8);
+ v_out->a = alpha;
+}
+
diff --git a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/bwfilter.rs b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/bwfilter.rs
new file mode 100644
index 0000000..e706d44
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/bwfilter.rs
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ip.rsh"
+//#pragma rs_fp_relaxed
+
+static float sr = 0.f;
+static float sg = 0.f;
+static float sb = 0.f;
+
+void prepareBwFilter(uint32_t rw, uint32_t gw, uint32_t bw) {
+
+ sr = rw;
+ sg = gw;
+ sb = bw;
+
+ float imageMin = min(sg,sb);
+ imageMin = fmin(sr,imageMin);
+ float imageMax = max(sg,sb);
+ imageMax = fmax(sr,imageMax);
+ float avg = (imageMin + imageMax)/2;
+ sb /= avg;
+ sg /= avg;
+ sr /= avg;
+
+}
+
+void bwFilterKernel(const uchar4 *in, uchar4 *out) {
+ float r = in->r * sr;
+ float g = in->g * sg;
+ float b = in->b * sb;
+ float localMin, localMax, avg;
+ localMin = fmin(g,b);
+ localMin = fmin(r,localMin);
+ localMax = fmax(g,b);
+ localMax = fmax(r,localMax);
+ avg = (localMin+localMax) * 0.5f;
+ out->r = out->g = out->b = rsClamp(avg, 0, 255);
+}
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/colormatrix.rs b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/colormatrix.fs
similarity index 79%
copy from tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/colormatrix.rs
copy to tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/colormatrix.fs
index e93bef3..86fb248 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/colormatrix.rs
+++ b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/colormatrix.fs
@@ -14,10 +14,7 @@
* limitations under the License.
*/
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.image2)
-#pragma rs_fp_relaxed
-
+#include "ip.rsh"
static rs_matrix4x4 Mat;
@@ -29,10 +26,10 @@
Mat = m;
}
-void root(const uchar4 *in, uchar4 *out) {
- float4 f = convert_float4(*in);
+uchar4 __attribute__((kernel)) root(uchar4 in) {
+ float4 f = convert_float4(in);
f = rsMatrixMultiply(&Mat, f);
f = clamp(f, 0.f, 255.f);
- *out = convert_uchar4(f);
+ return convert_uchar4(f);
}
diff --git a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/colormatrix.rs b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/colormatrix.rs
deleted file mode 100644
index 772cb83..0000000
--- a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/colormatrix.rs
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.imagejb)
-#pragma rs_fp_relaxed
-
-
-static rs_matrix4x4 Mat;
-
-void init() {
- rsMatrixLoadIdentity(&Mat);
-}
-
-void setMatrix(rs_matrix4x4 m) {
- Mat = m;
-}
-
-void root(const uchar4 *in, uchar4 *out) {
- float4 f = convert_float4(*in);
- f = rsMatrixMultiply(&Mat, f);
- f = clamp(f, 0.f, 255.f);
- *out = convert_uchar4(f);
-}
-
diff --git a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/contrast.rs b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/contrast.rs
new file mode 100644
index 0000000..d3743d3
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/contrast.rs
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ip.rsh"
+
+static float brightM = 0.f;
+static float brightC = 0.f;
+
+void setBright(float v) {
+ brightM = pow(2.f, v / 100.f);
+ brightC = 127.f - brightM * 127.f;
+}
+
+void contrast(const uchar4 *in, uchar4 *out)
+{
+#if 0
+ out->r = rsClamp((int)(brightM * in->r + brightC), 0, 255);
+ out->g = rsClamp((int)(brightM * in->g + brightC), 0, 255);
+ out->b = rsClamp((int)(brightM * in->b + brightC), 0, 255);
+#else
+ float3 v = convert_float3(in->rgb) * brightM + brightC;
+ out->rgb = convert_uchar3(clamp(v, 0.f, 255.f));
+#endif
+}
diff --git a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/convolve3x3.fs b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/convolve3x3.fs
new file mode 100644
index 0000000..177e86e
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/convolve3x3.fs
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ip.rsh"
+
+int32_t gWidth;
+int32_t gHeight;
+rs_allocation gIn;
+
+float gCoeffs[9];
+
+uchar4 __attribute__((kernel)) root(uint32_t x, uint32_t y) {
+ uint32_t x1 = min((int32_t)x+1, gWidth-1);
+ uint32_t x2 = max((int32_t)x-1, 0);
+ uint32_t y1 = min((int32_t)y+1, gHeight-1);
+ uint32_t y2 = max((int32_t)y-1, 0);
+
+ float4 p00 = convert_float4(rsGetElementAt_uchar4(gIn, x1, y1));
+ float4 p01 = convert_float4(rsGetElementAt_uchar4(gIn, x, y1));
+ float4 p02 = convert_float4(rsGetElementAt_uchar4(gIn, x2, y1));
+ float4 p10 = convert_float4(rsGetElementAt_uchar4(gIn, x1, y));
+ float4 p11 = convert_float4(rsGetElementAt_uchar4(gIn, x, y));
+ float4 p12 = convert_float4(rsGetElementAt_uchar4(gIn, x2, y));
+ float4 p20 = convert_float4(rsGetElementAt_uchar4(gIn, x1, y2));
+ float4 p21 = convert_float4(rsGetElementAt_uchar4(gIn, x, y2));
+ float4 p22 = convert_float4(rsGetElementAt_uchar4(gIn, x2, y2));
+ p00 *= gCoeffs[0];
+ p01 *= gCoeffs[1];
+ p02 *= gCoeffs[2];
+ p10 *= gCoeffs[3];
+ p11 *= gCoeffs[4];
+ p12 *= gCoeffs[5];
+ p20 *= gCoeffs[6];
+ p21 *= gCoeffs[7];
+ p22 *= gCoeffs[8];
+
+ p00 += p01;
+ p02 += p10;
+ p11 += p12;
+ p20 += p21;
+
+ p22 += p00;
+ p02 += p11;
+
+ p20 += p22;
+ p20 += p02;
+
+ p20 = clamp(p20, 0.f, 255.f);
+ return convert_uchar4(p20);
+}
+
+
diff --git a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/convolve3x3.rs b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/convolve3x3.rs
deleted file mode 100644
index f12f6ce..0000000
--- a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/convolve3x3.rs
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.imagejb)
-#pragma rs_fp_relaxed
-
-int32_t gWidth;
-int32_t gHeight;
-rs_allocation gIn;
-
-float gCoeffs[9];
-
-static inline uchar4 GetElementAt_uchar4(rs_allocation a, uint32_t x, uint32_t y) {
- return ((uchar4 *)rsGetElementAt(a, x, y))[0];
-}
-
-void root(uchar4 *out, uint32_t x, uint32_t y) {
- uint32_t x1 = min((int32_t)x+1, gWidth-1);
- uint32_t x2 = max((int32_t)x-1, 0);
- uint32_t y1 = min((int32_t)y+1, gHeight-1);
- uint32_t y2 = max((int32_t)y-1, 0);
-
- float4 p00 = convert_float4(GetElementAt_uchar4(gIn, x1, y1));
- float4 p01 = convert_float4(GetElementAt_uchar4(gIn, x, y1));
- float4 p02 = convert_float4(GetElementAt_uchar4(gIn, x2, y1));
- float4 p10 = convert_float4(GetElementAt_uchar4(gIn, x1, y));
- float4 p11 = convert_float4(GetElementAt_uchar4(gIn, x, y));
- float4 p12 = convert_float4(GetElementAt_uchar4(gIn, x2, y));
- float4 p20 = convert_float4(GetElementAt_uchar4(gIn, x1, y2));
- float4 p21 = convert_float4(GetElementAt_uchar4(gIn, x, y2));
- float4 p22 = convert_float4(GetElementAt_uchar4(gIn, x2, y2));
- p00 *= gCoeffs[0];
- p01 *= gCoeffs[1];
- p02 *= gCoeffs[2];
- p10 *= gCoeffs[3];
- p11 *= gCoeffs[4];
- p12 *= gCoeffs[5];
- p20 *= gCoeffs[6];
- p21 *= gCoeffs[7];
- p22 *= gCoeffs[8];
-
- p00 += p01;
- p02 += p10;
- p11 += p12;
- p20 += p21;
-
- p22 += p00;
- p02 += p11;
-
- p20 += p22;
- p20 += p02;
-
- p20 = clamp(p20, 0.f, 255.f);
- *out = convert_uchar4(p20);
-}
-
-
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/convolve5x5.rs b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/convolve5x5.fs
similarity index 93%
copy from tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/convolve5x5.rs
copy to tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/convolve5x5.fs
index b1ad241..922a593 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/convolve5x5.rs
+++ b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/convolve5x5.fs
@@ -14,9 +14,7 @@
* limitations under the License.
*/
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.image2)
-#pragma rs_fp_relaxed
+#include "ip.rsh"
int32_t gWidth;
int32_t gHeight;
@@ -24,7 +22,7 @@
float gCoeffs[25];
-void root(uchar4 *out, uint32_t x, uint32_t y) {
+uchar4 __attribute__((kernel)) root(uint32_t x, uint32_t y) {
uint32_t x0 = max((int32_t)x-2, 0);
uint32_t x1 = max((int32_t)x-1, 0);
uint32_t x2 = x;
@@ -68,8 +66,7 @@
+ convert_float4(rsGetElementAt_uchar4(gIn, x4, y4)) * gCoeffs[24];
p0 = clamp(p0 + p1 + p2 + p3 + p4, 0.f, 255.f);
- p0.a = 255.f;
- *out = convert_uchar4(p0);
+ return convert_uchar4(p0);
}
diff --git a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/convolve5x5.rs b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/convolve5x5.rs
deleted file mode 100644
index 6e23d79..0000000
--- a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/convolve5x5.rs
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.imagejb)
-#pragma rs_fp_relaxed
-
-int32_t gWidth;
-int32_t gHeight;
-rs_allocation gIn;
-
-float gCoeffs[25];
-
-static inline uchar4 GetElementAt_uchar4(rs_allocation a, uint32_t x, uint32_t y) {
- return ((uchar4 *)rsGetElementAt(a, x, y))[0];
-}
-
-void root(uchar4 *out, uint32_t x, uint32_t y) {
- uint32_t x0 = max((int32_t)x-2, 0);
- uint32_t x1 = max((int32_t)x-1, 0);
- uint32_t x2 = x;
- uint32_t x3 = min((int32_t)x+1, gWidth-1);
- uint32_t x4 = min((int32_t)x+2, gWidth-1);
-
- uint32_t y0 = max((int32_t)y-2, 0);
- uint32_t y1 = max((int32_t)y-1, 0);
- uint32_t y2 = y;
- uint32_t y3 = min((int32_t)y+1, gHeight-1);
- uint32_t y4 = min((int32_t)y+2, gHeight-1);
-
- float4 p0 = convert_float4(GetElementAt_uchar4(gIn, x0, y0)) * gCoeffs[0]
- + convert_float4(GetElementAt_uchar4(gIn, x1, y0)) * gCoeffs[1]
- + convert_float4(GetElementAt_uchar4(gIn, x2, y0)) * gCoeffs[2]
- + convert_float4(GetElementAt_uchar4(gIn, x3, y0)) * gCoeffs[3]
- + convert_float4(GetElementAt_uchar4(gIn, x4, y0)) * gCoeffs[4];
-
- float4 p1 = convert_float4(GetElementAt_uchar4(gIn, x0, y1)) * gCoeffs[5]
- + convert_float4(GetElementAt_uchar4(gIn, x1, y1)) * gCoeffs[6]
- + convert_float4(GetElementAt_uchar4(gIn, x2, y1)) * gCoeffs[7]
- + convert_float4(GetElementAt_uchar4(gIn, x3, y1)) * gCoeffs[8]
- + convert_float4(GetElementAt_uchar4(gIn, x4, y1)) * gCoeffs[9];
-
- float4 p2 = convert_float4(GetElementAt_uchar4(gIn, x0, y2)) * gCoeffs[10]
- + convert_float4(GetElementAt_uchar4(gIn, x1, y2)) * gCoeffs[11]
- + convert_float4(GetElementAt_uchar4(gIn, x2, y2)) * gCoeffs[12]
- + convert_float4(GetElementAt_uchar4(gIn, x3, y2)) * gCoeffs[13]
- + convert_float4(GetElementAt_uchar4(gIn, x4, y2)) * gCoeffs[14];
-
- float4 p3 = convert_float4(GetElementAt_uchar4(gIn, x0, y3)) * gCoeffs[15]
- + convert_float4(GetElementAt_uchar4(gIn, x1, y3)) * gCoeffs[16]
- + convert_float4(GetElementAt_uchar4(gIn, x2, y3)) * gCoeffs[17]
- + convert_float4(GetElementAt_uchar4(gIn, x3, y3)) * gCoeffs[18]
- + convert_float4(GetElementAt_uchar4(gIn, x4, y3)) * gCoeffs[19];
-
- float4 p4 = convert_float4(GetElementAt_uchar4(gIn, x0, y4)) * gCoeffs[20]
- + convert_float4(GetElementAt_uchar4(gIn, x1, y4)) * gCoeffs[21]
- + convert_float4(GetElementAt_uchar4(gIn, x2, y4)) * gCoeffs[22]
- + convert_float4(GetElementAt_uchar4(gIn, x3, y4)) * gCoeffs[23]
- + convert_float4(GetElementAt_uchar4(gIn, x4, y4)) * gCoeffs[24];
-
- p0 = clamp(p0 + p1 + p2 + p3 + p4, 0.f, 255.f);
- *out = convert_uchar4(p0);
-}
-
-
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/levels_relaxed.rs b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/copy.fs
similarity index 83%
copy from tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/levels_relaxed.rs
copy to tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/copy.fs
index ffdcfe3..6595874 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/levels_relaxed.rs
+++ b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/copy.fs
@@ -14,9 +14,10 @@
* limitations under the License.
*/
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.image2)
-#pragma rs_fp_relaxed
+#include "ip.rsh"
-#include "levels.rsh"
+uchar4 __attribute__((kernel)) root(uchar4 v_in) {
+ return v_in;
+}
+
diff --git a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/copy.rs b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/copy.rs
deleted file mode 100644
index 17f7cff..0000000
--- a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/copy.rs
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.imagejb)
-
-void root(const uchar4 *in, uchar4 *out) {
- *out = *in;
-}
-
-
diff --git a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/greyscale.rs b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/exposure.rs
similarity index 66%
copy from tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/greyscale.rs
copy to tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/exposure.rs
index b3a7ef0..0f05cb9 100644
--- a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/greyscale.rs
+++ b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/exposure.rs
@@ -14,17 +14,18 @@
* limitations under the License.
*/
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.imagejb)
-#pragma rs_fp_relaxed
+#include "ip.rsh"
-const static float3 gMonoMult = {0.299f, 0.587f, 0.114f};
+static float bright = 0.f;
-void root(const uchar4 *v_in, uchar4 *out) {
- float4 f4 = rsUnpackColor8888(*v_in);
-
- float3 mono = dot(f4.rgb, gMonoMult);
- *out = rsPackColorTo8888(mono);
+void setBright(float v) {
+ bright = 255.f / (255.f - v);
}
+void exposure(const uchar4 *in, uchar4 *out)
+{
+ out->r = rsClamp((int)(bright * in->r), 0, 255);
+ out->g = rsClamp((int)(bright * in->g), 0, 255);
+ out->b = rsClamp((int)(bright * in->b), 0, 255);
+}
diff --git a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/fisheye.rsh b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/fisheye.rsh
new file mode 100644
index 0000000..2eacb7d
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/fisheye.rsh
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+rs_allocation in_alloc;
+rs_sampler sampler;
+
+static float2 center, neg_center, inv_dimensions, axis_scale;
+static float alpha, radius2, factor;
+
+void init_filter(uint32_t dim_x, uint32_t dim_y, float center_x, float center_y, float k) {
+ center.x = center_x;
+ center.y = center_y;
+ neg_center = -center;
+ inv_dimensions.x = 1.f / (float)dim_x;
+ inv_dimensions.y = 1.f / (float)dim_y;
+ alpha = k * 2.0f + 0.75f;
+
+ axis_scale = (float2)1.f;
+ if (dim_x > dim_y)
+ axis_scale.y = (float)dim_y / (float)dim_x;
+ else
+ axis_scale.x = (float)dim_x / (float)dim_y;
+
+ const float bound2 = 0.25f * (axis_scale.x*axis_scale.x + axis_scale.y*axis_scale.y);
+ const float bound = sqrt(bound2);
+ const float radius = 1.15f * bound;
+ radius2 = radius*radius;
+ const float max_radian = M_PI_2 - atan(alpha / bound * sqrt(radius2 - bound2));
+ factor = bound / max_radian;
+}
+
+uchar4 __attribute__((kernel)) root(uint32_t x, uint32_t y) {
+ // Convert x and y to floating point coordinates with center as origin
+ const float2 inCoord = {(float)x, (float)y};
+ const float2 coord = mad(inCoord, inv_dimensions, neg_center);
+ const float2 scaledCoord = axis_scale * coord;
+ const float dist2 = scaledCoord.x*scaledCoord.x + scaledCoord.y*scaledCoord.y;
+ const float inv_dist = rsqrt(dist2);
+ const float radian = M_PI_2 - atan((alpha * sqrt(radius2 - dist2)) * inv_dist);
+ const float scalar = radian * factor * inv_dist;
+ const float2 new_coord = mad(coord, scalar, center);
+ const float4 fout = rsSample(in_alloc, sampler, new_coord);
+ return rsPackColorTo8888(fout);
+}
+
diff --git a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/fisheye_approx.rsh b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/fisheye_approx.rsh
new file mode 100644
index 0000000..fcf0a3d
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/fisheye_approx.rsh
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+rs_allocation in_alloc;
+rs_sampler sampler;
+
+static float2 center, neg_center, inv_dimensions, axis_scale;
+static float alpha, radius2, factor;
+
+void init_filter(uint32_t dim_x, uint32_t dim_y, float center_x, float center_y, float k) {
+ center.x = center_x;
+ center.y = center_y;
+ neg_center = -center;
+ inv_dimensions.x = 1.f / (float)dim_x;
+ inv_dimensions.y = 1.f / (float)dim_y;
+ alpha = k * 2.0f + 0.75f;
+
+ axis_scale = (float2)1.f;
+ if (dim_x > dim_y)
+ axis_scale.y = (float)dim_y / (float)dim_x;
+ else
+ axis_scale.x = (float)dim_x / (float)dim_y;
+
+ const float bound2 = 0.25f * (axis_scale.x*axis_scale.x + axis_scale.y*axis_scale.y);
+ const float bound = sqrt(bound2);
+ const float radius = 1.15f * bound;
+ radius2 = radius*radius;
+ const float max_radian = M_PI_2 - atan(alpha / bound * sqrt(radius2 - bound2));
+ factor = bound / max_radian;
+}
+
+uchar4 __attribute__((kernel)) root(uint32_t x, uint32_t y) {
+ // Convert x and y to floating point coordinates with center as origin
+ const float2 inCoord = {(float)x, (float)y};
+ const float2 coord = mad(inCoord, inv_dimensions, neg_center);
+ const float2 scaledCoord = axis_scale * coord;
+ const float dist2 = scaledCoord.x*scaledCoord.x + scaledCoord.y*scaledCoord.y;
+ const float inv_dist = half_rsqrt(dist2);
+ const float radian = M_PI_2 - atan((alpha * half_sqrt(radius2 - dist2)) * inv_dist);
+ const float scalar = radian * factor * inv_dist;
+ const float2 new_coord = mad(coord, scalar, center);
+ const float4 fout = rsSample(in_alloc, sampler, new_coord);
+ return rsPackColorTo8888(fout);
+}
+
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_approx_relaxed.rs b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/fisheye_approx_full.rs
similarity index 86%
copy from tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_approx_relaxed.rs
copy to tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/fisheye_approx_full.rs
index 64d27ed..ed69ff4 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_approx_relaxed.rs
+++ b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/fisheye_approx_full.rs
@@ -14,9 +14,7 @@
* limitations under the License.
*/
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.image2)
-#pragma rs_fp_relaxed
+#include "ip.rsh"
#include "fisheye_approx.rsh"
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_approx_relaxed.rs b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/fisheye_approx_relaxed.fs
similarity index 86%
copy from tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_approx_relaxed.rs
copy to tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/fisheye_approx_relaxed.fs
index 64d27ed..ed69ff4 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_approx_relaxed.rs
+++ b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/fisheye_approx_relaxed.fs
@@ -14,9 +14,7 @@
* limitations under the License.
*/
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.image2)
-#pragma rs_fp_relaxed
+#include "ip.rsh"
#include "fisheye_approx.rsh"
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_relaxed.rs b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/fisheye_full.rs
similarity index 86%
copy from tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_relaxed.rs
copy to tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/fisheye_full.rs
index 990310b..f986b5d 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_relaxed.rs
+++ b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/fisheye_full.rs
@@ -14,9 +14,7 @@
* limitations under the License.
*/
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.image2)
-#pragma rs_fp_relaxed
+#include "ip.rsh"
#include "fisheye.rsh"
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_relaxed.rs b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/fisheye_relaxed.fs
similarity index 86%
copy from tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_relaxed.rs
copy to tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/fisheye_relaxed.fs
index 990310b..f986b5d 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_relaxed.rs
+++ b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/fisheye_relaxed.fs
@@ -14,9 +14,7 @@
* limitations under the License.
*/
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.image2)
-#pragma rs_fp_relaxed
+#include "ip.rsh"
#include "fisheye.rsh"
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/grain.rs b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/grain.fs
similarity index 87%
copy from tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/grain.rs
copy to tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/grain.fs
index 44320a5..2e62cd7 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/grain.rs
+++ b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/grain.fs
@@ -14,12 +14,10 @@
* limitations under the License.
*/
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.image2)
-#pragma rs_fp_relaxed
+#include "ip.rsh"
-void genRand(uchar *out) {
- *out = (uchar)rsRand(0xff);
+uchar __attribute__((kernel)) genRand() {
+ return (uchar)rsRand(0xff);
}
/*
@@ -42,7 +40,7 @@
int32_t gHMask;
rs_allocation gBlendSource;
-void blend9(uchar *out, uint32_t x, uint32_t y) {
+uchar __attribute__((kernel)) blend9(uint32_t x, uint32_t y) {
uint32_t x1 = (x-1) & gWMask;
uint32_t x2 = (x+1) & gWMask;
uint32_t y1 = (y-1) & gHMask;
@@ -70,14 +68,14 @@
p20 += p02;
p20 = min(p20 >> 10, (uint)255);
- *out = (uchar)p20;
+ return (uchar)p20;
}
float gNoiseStrength;
rs_allocation gNoise;
-void root(const uchar4 *in, uchar4 *out, uint32_t x, uint32_t y) {
- float4 ip = convert_float4(*in);
+uchar4 __attribute__((kernel)) root(uchar4 in, uint32_t x, uint32_t y) {
+ float4 ip = convert_float4(in);
float pnoise = (float) rsGetElementAt_uchar(gNoise, x & gWMask, y & gHMask);
float energy_level = ip.r + ip.g + ip.b;
@@ -89,5 +87,5 @@
uchar4 p = convert_uchar4(ip);
p.a = 0xff;
- *out = p;
+ return p;
}
diff --git a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/grain.rs b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/grain.rs
deleted file mode 100644
index 885ef49..0000000
--- a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/grain.rs
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.imagejb)
-#pragma rs_fp_relaxed
-
-void genRand(uchar *out) {
- *out = (uchar)rsRand(0xff);
-}
-
-static inline uchar GetElementAt_uchar(rs_allocation a, uint32_t x, uint32_t y) {
- return ((uchar *)rsGetElementAt(a, x, y))[0];
-}
-
-static inline float4 GetElementAt_float4(rs_allocation a, uint32_t x, uint32_t y) {
- return ((float4 *)rsGetElementAt(a, x, y))[0];
-}
-
-/*
- * Convolution matrix of distance 2 with fixed point of 'kShiftBits' bits
- * shifted. Thus the sum of this matrix should be 'kShiftValue'. Entries of
- * small values are not calculated to gain efficiency.
- * The order ot pixels represented in this matrix is:
- * 1 2 3
- * 4 0 5
- * 6 7 8
- * and the matrix should be: {230, 56, 114, 56, 114, 114, 56, 114, 56}.
- * However, since most of the valus are identical, we only use the first three
- * entries and the entries corresponding to the pixels is:
- * 1 2 1
- * 2 0 2
- * 1 2 1
- */
-
-int32_t gWMask;
-int32_t gHMask;
-
-rs_allocation gBlendSource;
-void blend9(uchar *out, uint32_t x, uint32_t y) {
- uint32_t x1 = (x-1) & gWMask;
- uint32_t x2 = (x+1) & gWMask;
- uint32_t y1 = (y-1) & gHMask;
- uint32_t y2 = (y+1) & gHMask;
-
- uint p00 = 56 * GetElementAt_uchar(gBlendSource, x1, y1);
- uint p01 = 114 * GetElementAt_uchar(gBlendSource, x, y1);
- uint p02 = 56 * GetElementAt_uchar(gBlendSource, x2, y1);
- uint p10 = 114 * GetElementAt_uchar(gBlendSource, x1, y);
- uint p11 = 230 * GetElementAt_uchar(gBlendSource, x, y);
- uint p12 = 114 * GetElementAt_uchar(gBlendSource, x2, y);
- uint p20 = 56 * GetElementAt_uchar(gBlendSource, x1, y2);
- uint p21 = 114 * GetElementAt_uchar(gBlendSource, x, y2);
- uint p22 = 56 * GetElementAt_uchar(gBlendSource, x2, y2);
-
- p00 += p01;
- p02 += p10;
- p11 += p12;
- p20 += p21;
-
- p22 += p00;
- p02 += p11;
-
- p20 += p22;
- p20 += p02;
-
- p20 = min(p20 >> 10, (uint)255);
- *out = (uchar)p20;
-}
-
-float gNoiseStrength;
-
-rs_allocation gNoise;
-void root(const uchar4 *in, uchar4 *out, uint32_t x, uint32_t y) {
- float4 ip = convert_float4(*in);
- float pnoise = (float) GetElementAt_uchar(gNoise, x & gWMask, y & gHMask);
-
- float energy_level = ip.r + ip.g + ip.b;
- float energy_mask = (28.f - sqrt(energy_level)) * 0.03571f;
- pnoise = (pnoise - 128.f) * energy_mask;
-
- ip += pnoise * gNoiseStrength;
- ip = clamp(ip, 0.f, 255.f);
-
- uchar4 p = convert_uchar4(ip);
- p.a = 0xff;
- *out = p;
-}
diff --git a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/greyscale.rs b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/greyscale.fs
similarity index 66%
copy from tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/greyscale.rs
copy to tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/greyscale.fs
index b3a7ef0..4e13072 100644
--- a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/greyscale.rs
+++ b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/greyscale.fs
@@ -14,17 +14,23 @@
* limitations under the License.
*/
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.imagejb)
-#pragma rs_fp_relaxed
+#include "ip.rsh"
const static float3 gMonoMult = {0.299f, 0.587f, 0.114f};
-void root(const uchar4 *v_in, uchar4 *out) {
- float4 f4 = rsUnpackColor8888(*v_in);
+uchar4 __attribute__((kernel)) root(uchar4 v_in) {
+ float4 f4 = rsUnpackColor8888(v_in);
float3 mono = dot(f4.rgb, gMonoMult);
- *out = rsPackColorTo8888(mono);
+ return rsPackColorTo8888(mono);
}
+uchar __attribute__((kernel)) toU8(uchar4 v_in) {
+ float4 f4 = convert_float4(v_in);
+ return (uchar)dot(f4.rgb, gMonoMult);
+}
+
+uchar4 __attribute__((kernel)) toU8_4(uchar v_in) {
+ return (uchar4)v_in;
+}
diff --git a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/levels_relaxed.rs b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/ip.rsh
similarity index 86%
rename from tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/levels_relaxed.rs
rename to tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/ip.rsh
index b2564ef..8124211 100644
--- a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/levels_relaxed.rs
+++ b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/ip.rsh
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 The Android Open Source Project
+ * Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,7 +16,5 @@
#pragma version(1)
#pragma rs java_package_name(com.android.rs.imagejb)
-#pragma rs_fp_relaxed
-#include "levels.rsh"
diff --git a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/levels.rsh b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/levels.rsh
index a3a2775..e289906 100644
--- a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/levels.rsh
+++ b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/levels.rsh
@@ -21,24 +21,26 @@
float overInWMinInB;
rs_matrix3x3 colorMat;
-void root(const uchar4 *in, uchar4 *out, uint32_t x, uint32_t y) {
- float3 pixel = convert_float4(*in).rgb;
+uchar4 __attribute__((kernel)) root(uchar4 in, uint32_t x, uint32_t y) {
+ uchar4 out;
+ float3 pixel = convert_float4(in).rgb;
pixel = rsMatrixMultiply(&colorMat, pixel);
pixel = clamp(pixel, 0.f, 255.f);
pixel = (pixel - inBlack) * overInWMinInB;
pixel = pixel * outWMinOutB + outBlack;
pixel = clamp(pixel, 0.f, 255.f);
- out->xyz = convert_uchar3(pixel);
- out->w = 0xff;
+ out.xyz = convert_uchar3(pixel);
+ out.w = 0xff;
+ return out;
}
-void root4(const uchar4 *in, uchar4 *out, uint32_t x, uint32_t y) {
- float4 pixel = convert_float4(*in);
+uchar4 __attribute__((kernel)) root4(uchar4 in, uint32_t x, uint32_t y) {
+ float4 pixel = convert_float4(in);
pixel.rgb = rsMatrixMultiply(&colorMat, pixel.rgb);
pixel = clamp(pixel, 0.f, 255.f);
pixel = (pixel - inBlack) * overInWMinInB;
pixel = pixel * outWMinOutB + outBlack;
pixel = clamp(pixel, 0.f, 255.f);
- *out = convert_uchar4(pixel);
+ return convert_uchar4(pixel);
}
diff --git a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/levels_full.rs b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/levels_full.rs
index dead169..28596ba 100644
--- a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/levels_full.rs
+++ b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/levels_full.rs
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.imagejb)
+#include "ip.rsh"
#include "levels.rsh"
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/levels_relaxed.rs b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/levels_relaxed.fs
similarity index 86%
copy from tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/levels_relaxed.rs
copy to tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/levels_relaxed.fs
index ffdcfe3..28596ba 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/levels_relaxed.rs
+++ b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/levels_relaxed.fs
@@ -14,9 +14,7 @@
* limitations under the License.
*/
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.image2)
-#pragma rs_fp_relaxed
+#include "ip.rsh"
#include "levels.rsh"
diff --git a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/mandelbrot.rs b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/mandelbrot.rs
index 7cd8488..de0bd00 100644
--- a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/mandelbrot.rs
+++ b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/mandelbrot.rs
@@ -12,8 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.imagejb)
+#include "ip.rsh"
uint32_t gMaxIteration = 500;
uint32_t gDimX = 1024;
@@ -23,7 +22,7 @@
float lowerBoundY = -2.f;
float scaleFactor = 4.f;
-void root(uchar4 *out, uint32_t x, uint32_t y) {
+uchar4 __attribute__((kernel)) root(uint32_t x, uint32_t y) {
float2 p;
p.x = lowerBoundX + ((float)x / gDimX) * scaleFactor;
p.y = lowerBoundY + ((float)y / gDimY) * scaleFactor;
@@ -41,16 +40,16 @@
if(iter >= gMaxIteration) {
// write a non-transparent black pixel
- *out = (uchar4){0, 0, 0, 0xff};
+ return (uchar4){0, 0, 0, 0xff};
} else {
float mi3 = gMaxIteration / 3.f;
if (iter <= (gMaxIteration / 3))
- *out = (uchar4){0xff * (iter / mi3), 0, 0, 0xff};
+ return (uchar4){0xff * (iter / mi3), 0, 0, 0xff};
else if (iter <= (((gMaxIteration / 3) * 2)))
- *out = (uchar4){0xff - (0xff * ((iter - mi3) / mi3)),
+ return (uchar4){0xff - (0xff * ((iter - mi3) / mi3)),
(0xff * ((iter - mi3) / mi3)), 0, 0xff};
else
- *out = (uchar4){0, 0xff - (0xff * ((iter - (mi3 * 2)) / mi3)),
+ return (uchar4){0, 0xff - (0xff * ((iter - (mi3 * 2)) / mi3)),
(0xff * ((iter - (mi3 * 2)) / mi3)), 0xff};
}
}
diff --git a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/shadows.rs b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/shadows.rs
new file mode 100644
index 0000000..f6c149d
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/shadows.rs
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ip.rsh"
+//#pragma rs_fp_relaxed
+
+static double shadowFilterMap[] = {
+ -0.00591, 0.0001,
+ 1.16488, 0.01668,
+ -0.18027, -0.06791,
+ -0.12625, 0.09001,
+ 0.15065, -0.03897
+};
+
+static double poly[] = {
+ 0., 0.,
+ 0., 0.,
+ 0.
+};
+
+static const int ABITS = 4;
+static const int HSCALE = 256;
+static const int k1=255 << ABITS;
+static const int k2=HSCALE << ABITS;
+
+static double fastevalPoly(double *poly,int n, double x){
+
+ double f =x;
+ double sum = poly[0]+poly[1]*f;
+ int i;
+ for (i = 2; i < n; i++) {
+ f*=x;
+ sum += poly[i]*f;
+ }
+ return sum;
+}
+
+static ushort3 rgb2hsv( uchar4 rgb)
+{
+ int iMin,iMax,chroma;
+
+ int ri = rgb.r;
+ int gi = rgb.g;
+ int bi = rgb.b;
+ short rv,rs,rh;
+
+ if (ri > gi) {
+ iMax = max (ri, bi);
+ iMin = min (gi, bi);
+ } else {
+ iMax = max (gi, bi);
+ iMin = min (ri, bi);
+ }
+
+ chroma = iMax - iMin;
+ // set value
+ rv = (short)( iMax << ABITS);
+
+ // set saturation
+ if (rv == 0)
+ rs = 0;
+ else
+ rs = (short)((k1*chroma)/iMax);
+
+ // set hue
+ if (rs == 0)
+ rh = 0;
+ else {
+ if ( ri == iMax ) {
+ rh = (short)( (k2*(6*chroma+gi - bi))/(6*chroma));
+ if (rh >= k2) rh -= k2;
+ } else if (gi == iMax)
+ rh = (short)( (k2*(2*chroma+bi - ri ))/(6*chroma));
+ else // (bi == iMax )
+ rh = (short)( (k2*(4*chroma+ri - gi ))/(6*chroma));
+ }
+
+ ushort3 out;
+ out.x = rv;
+ out.y = rs;
+ out.z = rh;
+ return out;
+}
+
+static uchar4 hsv2rgb(ushort3 hsv)
+{
+ int ABITS = 4;
+ int HSCALE = 256;
+ int m;
+ int H,X,ih,is,iv;
+ int k1=255<<ABITS;
+ int k2=HSCALE<<ABITS;
+ int k3=1<<(ABITS-1);
+ int rr=0;
+ int rg=0;
+ int rb=0;
+ short cv = hsv.x;
+ short cs = hsv.y;
+ short ch = hsv.z;
+
+ // set chroma and min component value m
+ //chroma = ( cv * cs )/k1;
+ //m = cv - chroma;
+ m = ((int)cv*(k1 - (int)cs ))/k1;
+
+ // chroma == 0 <-> cs == 0 --> m=cv
+ if (cs == 0) {
+ rb = ( rg = ( rr =( cv >> ABITS) ));
+ } else {
+ ih=(int)ch;
+ is=(int)cs;
+ iv=(int)cv;
+
+ H = (6*ih)/k2;
+ X = ((iv*is)/k2)*(k2- abs(6*ih- 2*(H>>1)*k2 - k2)) ;
+
+ // removing additional bits --> unit8
+ X=( (X+iv*(k1 - is ))/k1 + k3 ) >> ABITS;
+ m=m >> ABITS;
+
+ // ( chroma + m ) --> cv ;
+ cv=(short) (cv >> ABITS);
+ switch (H) {
+ case 0:
+ rr = cv;
+ rg = X;
+ rb = m;
+ break;
+ case 1:
+ rr = X;
+ rg = cv;
+ rb = m;
+ break;
+ case 2:
+ rr = m;
+ rg = cv;
+ rb = X;
+ break;
+ case 3:
+ rr = m;
+ rg = X;
+ rb = cv;
+ break;
+ case 4:
+ rr = X;
+ rg = m;
+ rb = cv;
+ break;
+ case 5:
+ rr = cv;
+ rg = m ;
+ rb = X;
+ break;
+ }
+ }
+
+ uchar4 rgb;
+
+ rgb.r = rr;
+ rgb.g = rg;
+ rgb.b = rb;
+
+ return rgb;
+}
+
+void prepareShadows(float scale) {
+ double s = (scale>=0)?scale:scale/5;
+ for (int i = 0; i < 5; i++) {
+ poly[i] = fastevalPoly(shadowFilterMap+i*2,2 , s);
+ }
+}
+
+void shadowsKernel(const uchar4 *in, uchar4 *out) {
+ ushort3 hsv = rgb2hsv(*in);
+ double v = (fastevalPoly(poly,5,hsv.x/4080.)*4080);
+ if (v>4080) v = 4080;
+ hsv.x = (unsigned short) ((v>0)?v:0);
+ *out = hsv2rgb(hsv);
+}
diff --git a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/threshold.rs b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/threshold.fs
similarity index 67%
copy from tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/threshold.rs
copy to tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/threshold.fs
index d18117a..0b2c2e8 100644
--- a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/threshold.rs
+++ b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/threshold.fs
@@ -1,6 +1,20 @@
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.imagejb)
-#pragma rs_fp_relaxed
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ip.rsh"
int height;
@@ -56,51 +70,49 @@
}
}
-void copyIn(const uchar4 *in, float4 *out) {
- *out = convert_float4(*in);
+float4 __attribute__((kernel)) copyIn(uchar4 in) {
+ return convert_float4(in);
}
-static inline float4 GetElementAt_float4(rs_allocation a, uint32_t x, uint32_t y) {
- return ((float4 *)rsGetElementAt(a, x, y))[0];
-}
-
-void vert(uchar4 *out, uint32_t x, uint32_t y) {
+uchar4 __attribute__((kernel)) vert(uint32_t x, uint32_t y) {
float3 blurredPixel = 0;
int gi = 0;
+ uchar4 out;
if ((y > radius) && (y < (height - radius))) {
for (int r = -radius; r <= radius; r ++) {
- float4 i = GetElementAt_float4(ScratchPixel2, x, y + r);
+ float4 i = rsGetElementAt_float4(ScratchPixel2, x, y + r);
blurredPixel += i.xyz * gaussian[gi++];
}
} else {
for (int r = -radius; r <= radius; r ++) {
int validH = rsClamp((int)y + r, (int)0, (int)(height - 1));
- float4 i = GetElementAt_float4(ScratchPixel2, x, validH);
+ float4 i = rsGetElementAt_float4(ScratchPixel2, x, validH);
blurredPixel += i.xyz * gaussian[gi++];
}
}
- out->xyz = convert_uchar3(clamp(blurredPixel, 0.f, 255.f));
- out->w = 0xff;
+ out.xyz = convert_uchar3(clamp(blurredPixel, 0.f, 255.f));
+ out.w = 0xff;
+ return out;
}
-void horz(float4 *out, uint32_t x, uint32_t y) {
+float4 __attribute__((kernel)) horz(uint32_t x, uint32_t y) {
float4 blurredPixel = 0;
int gi = 0;
if ((x > radius) && (x < (width - radius))) {
for (int r = -radius; r <= radius; r ++) {
- float4 i = GetElementAt_float4(ScratchPixel1, x + r, y);
+ float4 i = rsGetElementAt_float4(ScratchPixel1, x + r, y);
blurredPixel += i * gaussian[gi++];
}
} else {
for (int r = -radius; r <= radius; r ++) {
// Stepping left and right away from the pixel
int validX = rsClamp((int)x + r, (int)0, (int)(width - 1));
- float4 i = GetElementAt_float4(ScratchPixel1, validX, y);
+ float4 i = rsGetElementAt_float4(ScratchPixel1, validX, y);
blurredPixel += i * gaussian[gi++];
}
}
- *out = blurredPixel;
+ return blurredPixel;
}
diff --git a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/vibrance.rs b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/vibrance.rs
new file mode 100644
index 0000000..8db113c
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/vibrance.rs
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ip.rsh"
+
+float vibrance = 0.f;
+
+static const float Rf = 0.2999f;
+static const float Gf = 0.587f;
+static const float Bf = 0.114f;
+
+static float S = 0.f;
+static float MS = 0.f;
+static float Rt = 0.f;
+static float Gt = 0.f;
+static float Bt = 0.f;
+static float Vib = 0.f;
+
+void vibranceKernel(const uchar4 *in, uchar4 *out) {
+
+ float R, G, B;
+
+ int r = in->r;
+ int g = in->g;
+ int b = in->b;
+ float red = (r-max(g, b))/256.f;
+ float sx = (float)(Vib/(1+exp(-red*3)));
+ S = sx+1;
+ MS = 1.0f - S;
+ Rt = Rf * MS;
+ Gt = Gf * MS;
+ Bt = Bf * MS;
+ int t = (r + g) / 2;
+ R = r;
+ G = g;
+ B = b;
+
+ float Rc = R * (Rt + S) + G * Gt + B * Bt;
+ float Gc = R * Rt + G * (Gt + S) + B * Bt;
+ float Bc = R * Rt + G * Gt + B * (Bt + S);
+
+ out->r = rsClamp(Rc, 0, 255);
+ out->g = rsClamp(Gc, 0, 255);
+ out->b = rsClamp(Bc, 0, 255);
+
+}
+
+void prepareVibrance() {
+
+ Vib = vibrance/100.f;
+ S = Vib + 1;
+ MS = 1.0f - S;
+ Rt = Rf * MS;
+ Gt = Gf * MS;
+ Bt = Bf * MS;
+
+}
diff --git a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/vignette.rsh b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/vignette.rsh
index 3fef0c3..04ca1f1 100644
--- a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/vignette.rsh
+++ b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/vignette.rsh
@@ -44,9 +44,9 @@
opp_shade = 1.f - desired_shade;
}
-void root(const uchar4 *in, uchar4 *out, uint32_t x, uint32_t y) {
+uchar4 __attribute__((kernel)) root(uchar4 in, uint32_t x, uint32_t y) {
// Convert x and y to floating point coordinates with center as origin
- const float4 fin = convert_float4(*in);
+ const float4 fin = convert_float4(in);
const float2 inCoord = {(float)x, (float)y};
const float2 coord = mad(inCoord, inv_dimensions, neg_center);
const float sloped_dist_ratio = length(axis_scale * coord) * sloped_inv_max_dist;
@@ -54,6 +54,6 @@
float4 fout;
fout.rgb = fin.rgb * lumen;
fout.w = fin.w;
- *out = convert_uchar4(fout);
+ return convert_uchar4(fout);
}
diff --git a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/vignette_approx.rsh b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/vignette_approx.rsh
new file mode 100644
index 0000000..0eacdc8
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/vignette_approx.rsh
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+static float2 neg_center, axis_scale, inv_dimensions;
+static float sloped_neg_range, sloped_inv_max_dist, shade, opp_shade;
+
+void init_vignette(uint32_t dim_x, uint32_t dim_y, float center_x, float center_y,
+ float desired_scale, float desired_shade, float desired_slope) {
+
+ neg_center.x = -center_x;
+ neg_center.y = -center_y;
+ inv_dimensions.x = 1.f / (float)dim_x;
+ inv_dimensions.y = 1.f / (float)dim_y;
+
+ axis_scale = (float2)1.f;
+ if (dim_x > dim_y)
+ axis_scale.y = (float)dim_y / (float)dim_x;
+ else
+ axis_scale.x = (float)dim_x / (float)dim_y;
+
+ const float max_dist = 0.5f * length(axis_scale);
+ sloped_inv_max_dist = desired_slope * 1.f/max_dist;
+
+ // Range needs to be between 1.3 to 0.6. When scale is zero then range is
+ // 1.3 which means no vignette at all because the luminousity difference is
+ // less than 1/256. Expect input scale to be between 0.0 and 1.0.
+ const float neg_range = 0.7f*sqrt(desired_scale) - 1.3f;
+ sloped_neg_range = exp(neg_range * desired_slope);
+
+ shade = desired_shade;
+ opp_shade = 1.f - desired_shade;
+}
+
+uchar4 __attribute__((kernel)) root(uchar4 in, uint32_t x, uint32_t y) {
+ // Convert x and y to floating point coordinates with center as origin
+ const float4 fin = convert_float4(in);
+ const float2 inCoord = {(float)x, (float)y};
+ const float2 coord = mad(inCoord, inv_dimensions, neg_center);
+ const float sloped_dist_ratio = fast_length(axis_scale * coord) * sloped_inv_max_dist;
+ const float lumen = opp_shade + shade * half_recip(1.f + sloped_neg_range * exp(sloped_dist_ratio));
+ float4 fout;
+ fout.rgb = fin.rgb * lumen;
+ fout.w = fin.w;
+ return convert_uchar4(fout);
+}
+
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette_approx_relaxed.rs b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/vignette_approx_full.rs
similarity index 86%
copy from tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette_approx_relaxed.rs
copy to tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/vignette_approx_full.rs
index b714e9b..00cbbc4 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette_approx_relaxed.rs
+++ b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/vignette_approx_full.rs
@@ -14,9 +14,7 @@
* limitations under the License.
*/
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.image2)
-#pragma rs_fp_relaxed
+#include "ip.rsh"
#include "vignette_approx.rsh"
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette_approx_relaxed.rs b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/vignette_approx_relaxed.fs
similarity index 86%
copy from tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette_approx_relaxed.rs
copy to tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/vignette_approx_relaxed.fs
index b714e9b..00cbbc4 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette_approx_relaxed.rs
+++ b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/vignette_approx_relaxed.fs
@@ -14,9 +14,7 @@
* limitations under the License.
*/
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.image2)
-#pragma rs_fp_relaxed
+#include "ip.rsh"
#include "vignette_approx.rsh"
diff --git a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/vignette_full.rs b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/vignette_full.rs
index c5b08a9..8202c5c 100644
--- a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/vignette_full.rs
+++ b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/vignette_full.rs
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.imagejb)
+#include "ip.rsh"
#include "vignette.rsh"
diff --git a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/vignette_relaxed.rs b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/vignette_relaxed.fs
similarity index 86%
rename from tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/vignette_relaxed.rs
rename to tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/vignette_relaxed.fs
index 339b747..8202c5c 100644
--- a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/vignette_relaxed.rs
+++ b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/vignette_relaxed.fs
@@ -14,9 +14,7 @@
* limitations under the License.
*/
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.imagejb)
-#pragma rs_fp_relaxed
+#include "ip.rsh"
#include "vignette.rsh"
diff --git a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/wbalance.rs b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/wbalance.rs
new file mode 100644
index 0000000..6650671
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/wbalance.rs
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ip.rsh"
+//#pragma rs_fp_relaxed
+
+static int histR[256] = {0}, histG[256] = {0}, histB[256] = {0};
+
+rs_allocation histogramSource;
+uint32_t histogramHeight;
+uint32_t histogramWidth;
+
+static float scaleR;
+static float scaleG;
+static float scaleB;
+
+static uchar4 estimateWhite() {
+
+ for (int i = 0; i < 256; i++) {
+ histR[i] = 0; histG[i] = 0; histB[i] = 0;
+ }
+
+ for (uint32_t i = 0; i < histogramHeight; i++) {
+ for (uint32_t j = 0; j < histogramWidth; j++) {
+ uchar4 in = rsGetElementAt_uchar4(histogramSource, j, i);
+ histR[in.r]++;
+ histG[in.g]++;
+ histB[in.b]++;
+ }
+ }
+
+ int min_r = -1, min_g = -1, min_b = -1;
+ int max_r = 0, max_g = 0, max_b = 0;
+ int sum_r = 0, sum_g = 0, sum_b = 0;
+
+ for (int i = 1; i < 255; i++) {
+ int r = histR[i];
+ int g = histG[i];
+ int b = histB[i];
+ sum_r += r;
+ sum_g += g;
+ sum_b += b;
+
+ if (r>0){
+ if (min_r < 0) min_r = i;
+ max_r = i;
+ }
+ if (g>0){
+ if (min_g < 0) min_g = i;
+ max_g = i;
+ }
+ if (b>0){
+ if (min_b < 0) min_b = i;
+ max_b = i;
+ }
+ }
+
+ int sum15r = 0, sum15g = 0, sum15b = 0;
+ int count15r = 0, count15g = 0, count15b = 0;
+ int tmp_r = 0, tmp_g = 0, tmp_b = 0;
+
+ for (int i = 254; i >0; i--) {
+ int r = histR[i];
+ int g = histG[i];
+ int b = histB[i];
+ tmp_r += r;
+ tmp_g += g;
+ tmp_b += b;
+
+ if ((tmp_r > sum_r/20) && (tmp_r < sum_r/5)) {
+ sum15r += r*i;
+ count15r += r;
+ }
+ if ((tmp_g > sum_g/20) && (tmp_g < sum_g/5)) {
+ sum15g += g*i;
+ count15g += g;
+ }
+ if ((tmp_b > sum_b/20) && (tmp_b < sum_b/5)) {
+ sum15b += b*i;
+ count15b += b;
+ }
+
+ }
+
+ uchar4 out;
+
+ if ((count15r>0) && (count15g>0) && (count15b>0) ){
+ out.r = sum15r/count15r;
+ out.g = sum15g/count15g;
+ out.b = sum15b/count15b;
+ }else {
+ out.r = out.g = out.b = 255;
+ }
+
+ return out;
+
+}
+
+void prepareWhiteBalance() {
+ uchar4 estimation = estimateWhite();
+ int minimum = min(estimation.r, min(estimation.g, estimation.b));
+ int maximum = max(estimation.r, max(estimation.g, estimation.b));
+ float avg = (minimum + maximum) / 2.f;
+
+ scaleR = avg/estimation.r;
+ scaleG = avg/estimation.g;
+ scaleB = avg/estimation.b;
+
+}
+
+static unsigned char contrastClamp(int c)
+{
+ int N = 255;
+ c &= ~(c >> 31);
+ c -= N;
+ c &= (c >> 31);
+ c += N;
+ return (unsigned char) c;
+}
+
+void whiteBalanceKernel(const uchar4 *in, uchar4 *out) {
+ float Rc = in->r*scaleR;
+ float Gc = in->g*scaleG;
+ float Bc = in->b*scaleB;
+
+ out->r = contrastClamp(Rc);
+ out->g = contrastClamp(Gc);
+ out->b = contrastClamp(Bc);
+}
diff --git a/tests/RenderScriptTests/tests_v14/src/com/android/rs/test/UT_alloc.java b/tests/RenderScriptTests/tests_v14/src/com/android/rs/test/UT_alloc.java
index da42b29..079fcce 100644
--- a/tests/RenderScriptTests/tests_v14/src/com/android/rs/test/UT_alloc.java
+++ b/tests/RenderScriptTests/tests_v14/src/com/android/rs/test/UT_alloc.java
@@ -39,6 +39,7 @@
typeBuilder.setX(X).setY(Y);
Allocation A = Allocation.createTyped(RS, typeBuilder.create());
s.bind_a(A);
+ s.set_aRaw(A);
typeBuilder = new Type.Builder(RS, Element.I32(RS));
typeBuilder.setX(X).setY(Y).setFaces(true);
@@ -56,9 +57,10 @@
public void run() {
RenderScript pRS = RenderScript.create(mCtx);
- ScriptC_alloc s = new ScriptC_alloc(pRS, mRes, R.raw.alloc);
+ ScriptC_alloc s = new ScriptC_alloc(pRS);
pRS.setMessageHandler(mRsMessage);
initializeGlobals(pRS, s);
+ s.forEach_root(s.get_aRaw());
s.invoke_alloc_test();
pRS.finish();
waitForMessage();
diff --git a/tests/RenderScriptTests/tests_v14/src/com/android/rs/test/UT_foreach.java b/tests/RenderScriptTests/tests_v14/src/com/android/rs/test/UT_foreach.java
index aeb5bb7..31f4114 100644
--- a/tests/RenderScriptTests/tests_v14/src/com/android/rs/test/UT_foreach.java
+++ b/tests/RenderScriptTests/tests_v14/src/com/android/rs/test/UT_foreach.java
@@ -37,17 +37,18 @@
s.set_dimY(Y);
typeBuilder.setX(X).setY(Y);
A = Allocation.createTyped(RS, typeBuilder.create());
- s.bind_a(A);
+ s.set_aRaw(A);
return;
}
public void run() {
RenderScript pRS = RenderScript.create(mCtx);
- ScriptC_foreach s = new ScriptC_foreach(pRS, mRes, R.raw.foreach);
+ ScriptC_foreach s = new ScriptC_foreach(pRS);
pRS.setMessageHandler(mRsMessage);
initializeGlobals(pRS, s);
s.forEach_root(A);
+ s.invoke_verify_root();
s.invoke_foreach_test();
pRS.finish();
waitForMessage();
diff --git a/tests/RenderScriptTests/tests_v14/src/com/android/rs/test/alloc.rs b/tests/RenderScriptTests/tests_v14/src/com/android/rs/test/alloc.rs
index 3116e5a..1b5e2ac 100644
--- a/tests/RenderScriptTests/tests_v14/src/com/android/rs/test/alloc.rs
+++ b/tests/RenderScriptTests/tests_v14/src/com/android/rs/test/alloc.rs
@@ -5,39 +5,37 @@
int dimY;
int dimZ;
+rs_allocation aRaw;
rs_allocation aFaces;
rs_allocation aLOD;
rs_allocation aFacesLOD;
+void root(int *o, uint32_t x, uint32_t y) {
+ *o = x + y * dimX;
+}
+
static bool test_alloc_dims() {
bool failed = false;
int i, j;
- for (j = 0; j < dimY; j++) {
- for (i = 0; i < dimX; i++) {
- a[i + j * dimX] = i + j * dimX;
- }
- }
-
- rs_allocation alloc = rsGetAllocation(a);
- _RS_ASSERT(rsAllocationGetDimX(alloc) == dimX);
- _RS_ASSERT(rsAllocationGetDimY(alloc) == dimY);
- _RS_ASSERT(rsAllocationGetDimZ(alloc) == dimZ);
+ _RS_ASSERT(rsAllocationGetDimX(aRaw) == dimX);
+ _RS_ASSERT(rsAllocationGetDimY(aRaw) == dimY);
+ _RS_ASSERT(rsAllocationGetDimZ(aRaw) == dimZ);
// Test 2D addressing
for (j = 0; j < dimY; j++) {
for (i = 0; i < dimX; i++) {
rsDebug("Verifying ", i + j * dimX);
- const void *p = rsGetElementAt(alloc, i, j);
+ const void *p = rsGetElementAt(aRaw, i, j);
int val = *(const int *)p;
_RS_ASSERT(val == (i + j * dimX));
}
}
// Test 1D addressing
- for (i = 0; i < dimX * dimY; i++) {
+ for (i = 0; i < dimX; i++) {
rsDebug("Verifying ", i);
- const void *p = rsGetElementAt(alloc, i);
+ const void *p = rsGetElementAt(aRaw, i);
int val = *(const int *)p;
_RS_ASSERT(val == i);
}
@@ -46,7 +44,7 @@
for (j = 0; j < dimY; j++) {
for (i = 0; i < dimX; i++) {
rsDebug("Verifying ", i + j * dimX);
- const void *p = rsGetElementAt(alloc, i, j, 0);
+ const void *p = rsGetElementAt(aRaw, i, j, 0);
int val = *(const int *)p;
_RS_ASSERT(val == (i + j * dimX));
}
diff --git a/tests/RenderScriptTests/tests_v14/src/com/android/rs/test/foreach.rs b/tests/RenderScriptTests/tests_v14/src/com/android/rs/test/foreach.rs
index 3ba3eef..3fa8f85 100644
--- a/tests/RenderScriptTests/tests_v14/src/com/android/rs/test/foreach.rs
+++ b/tests/RenderScriptTests/tests_v14/src/com/android/rs/test/foreach.rs
@@ -1,37 +1,40 @@
#include "shared.rsh"
-int *a;
+rs_allocation aRaw;
int dimX;
int dimY;
+static bool failed = false;
void root(int *out, uint32_t x, uint32_t y) {
*out = x + y * dimX;
}
-static bool test_foreach_output() {
+static bool test_root_output() {
bool failed = false;
int i, j;
for (j = 0; j < dimY; j++) {
for (i = 0; i < dimX; i++) {
- _RS_ASSERT(a[i + j * dimX] == (i + j * dimX));
+ int v = rsGetElementAt_int(aRaw, i, j);
+ _RS_ASSERT(v == (i + j * dimX));
}
}
if (failed) {
- rsDebug("test_foreach_output FAILED", 0);
+ rsDebug("test_root_output FAILED", 0);
}
else {
- rsDebug("test_foreach_output PASSED", 0);
+ rsDebug("test_root_output PASSED", 0);
}
return failed;
}
-void foreach_test() {
- bool failed = false;
- failed |= test_foreach_output();
+void verify_root() {
+ failed |= test_root_output();
+}
+void foreach_test() {
if (failed) {
rsSendToClientBlocking(RS_MSG_TEST_FAILED);
}
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index d4ec289..ed5d22c 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -3319,9 +3319,14 @@
}
case CMD_RECONNECT:
case CMD_REASSOCIATE:
- // Drop a third party reconnect/reassociate if we are
- // tempoarily disconnected for p2p
- if (mTemporarilyDisconnectWifi) ret = NOT_HANDLED;
+ if (mTemporarilyDisconnectWifi) {
+ // Drop a third party reconnect/reassociate if STA is
+ // temporarily disconnected for p2p
+ break;
+ } else {
+ // ConnectModeState handles it
+ ret = NOT_HANDLED;
+ }
break;
default:
ret = NOT_HANDLED;