Merge "Revert "Always show emergency button on selector view screen in keyguard." I'm reverting for now while we sort out the actual requirements. Sorry for the thrash, Jaggies. I'll handle re-adding it if needed." into jb-mr1-dev
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 8711ad7..2287859 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -135,6 +135,7 @@
$(call add-clean-step, rm -f $(PRODUCT_OUT)/system/media/video/Disco*)
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates)
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/ImageProcessing_intermediates)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/ImageProcessing2_intermediates)
# ************************************************
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
# ************************************************
diff --git a/api/17.txt b/api/17.txt
index 7cadf9b..7b2f161 100644
--- a/api/17.txt
+++ b/api/17.txt
@@ -27448,6 +27448,7 @@
method public void setInitialScale(int);
method public deprecated void setMapTrackballToArrowKeys(boolean);
method public void setNetworkAvailable(boolean);
+ method public deprecated void setPictureListener(android.webkit.WebView.PictureListener);
method public void setVerticalScrollbarOverlay(boolean);
method public void setWebChromeClient(android.webkit.WebChromeClient);
method public void setWebViewClient(android.webkit.WebViewClient);
diff --git a/api/current.txt b/api/current.txt
index 7cadf9b..7b2f161 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -27448,6 +27448,7 @@
method public void setInitialScale(int);
method public deprecated void setMapTrackballToArrowKeys(boolean);
method public void setNetworkAvailable(boolean);
+ method public deprecated void setPictureListener(android.webkit.WebView.PictureListener);
method public void setVerticalScrollbarOverlay(boolean);
method public void setWebChromeClient(android.webkit.WebChromeClient);
method public void setWebViewClient(android.webkit.WebViewClient);
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index c455b7d..463a18c 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -990,7 +990,10 @@
}
name = arg;
try {
- if (mUm.createUser(name, 0) == null) {
+ final UserInfo info = mUm.createUser(name, 0);
+ if (info != null) {
+ System.out.println("Success: created user id " + info.id);
+ } else {
System.err.println("Error: couldn't create User.");
}
} catch (RemoteException e) {
diff --git a/core/java/android/service/dreams/Sandman.java b/core/java/android/service/dreams/Sandman.java
new file mode 100644
index 0000000..70142ce
--- /dev/null
+++ b/core/java/android/service/dreams/Sandman.java
@@ -0,0 +1,122 @@
+/*
+ * 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 android.service.dreams;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.os.PowerManager;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.SystemClock;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.util.Slog;
+
+/**
+ * Internal helper for launching dreams to ensure consistency between the
+ * <code>UiModeManagerService</code> system service and the <code>Somnambulator</code> activity.
+ *
+ * @hide
+ */
+public final class Sandman {
+ private static final String TAG = "Sandman";
+
+ private static final int DEFAULT_SCREENSAVER_ENABLED = 1;
+ private static final int DEFAULT_SCREENSAVER_ACTIVATED_ON_DOCK = 1;
+
+ // The component name of a special dock app that merely launches a dream.
+ // We don't want to launch this app when docked because it causes an unnecessary
+ // activity transition. We just want to start the dream.
+ private static final ComponentName SOMNAMBULATOR_COMPONENT =
+ new ComponentName("com.android.systemui", "com.android.systemui.Somnambulator");
+
+
+ // The sandman is eternal. No one instantiates him.
+ private Sandman() {
+ }
+
+ /**
+ * Returns true if the specified dock app intent should be started.
+ * False if we should dream instead, if appropriate.
+ */
+ public static boolean shouldStartDockApp(Context context, Intent intent) {
+ ComponentName name = intent.resolveActivity(context.getPackageManager());
+ return name != null && !name.equals(SOMNAMBULATOR_COMPONENT);
+ }
+
+ /**
+ * Starts a dream manually.
+ */
+ public static void startDreamByUserRequest(Context context) {
+ startDream(context, false);
+ }
+
+ /**
+ * Starts a dream when docked if the system has been configured to do so,
+ * otherwise does nothing.
+ */
+ public static void startDreamWhenDockedIfAppropriate(Context context) {
+ if (!isScreenSaverEnabled(context)
+ || !isScreenSaverActivatedOnDock(context)) {
+ Slog.i(TAG, "Dreams currently disabled for docks.");
+ return;
+ }
+
+ startDream(context, true);
+ }
+
+ private static void startDream(Context context, boolean docked) {
+ try {
+ IDreamManager dreamManagerService = IDreamManager.Stub.asInterface(
+ ServiceManager.getService(DreamService.DREAM_SERVICE));
+ if (dreamManagerService != null && !dreamManagerService.isDreaming()) {
+ if (docked) {
+ Slog.i(TAG, "Activating dream while docked.");
+
+ // Wake up.
+ // The power manager will wake up the system automatically when it starts
+ // receiving power from a dock but there is a race between that happening
+ // and the UI mode manager starting a dream. We want the system to already
+ // be awake by the time this happens. Otherwise the dream may not start.
+ PowerManager powerManager =
+ (PowerManager)context.getSystemService(Context.POWER_SERVICE);
+ powerManager.wakeUp(SystemClock.uptimeMillis());
+ } else {
+ Slog.i(TAG, "Activating dream by user request.");
+ }
+
+ // Dream.
+ dreamManagerService.dream();
+ }
+ } catch (RemoteException ex) {
+ Slog.e(TAG, "Could not start dream when docked.", ex);
+ }
+ }
+
+ private static boolean isScreenSaverEnabled(Context context) {
+ return Settings.Secure.getIntForUser(context.getContentResolver(),
+ Settings.Secure.SCREENSAVER_ENABLED, DEFAULT_SCREENSAVER_ENABLED,
+ UserHandle.USER_CURRENT) != 0;
+ }
+
+ private static boolean isScreenSaverActivatedOnDock(Context context) {
+ return Settings.Secure.getIntForUser(context.getContentResolver(),
+ Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK,
+ DEFAULT_SCREENSAVER_ACTIVATED_ON_DOCK, UserHandle.USER_CURRENT) != 0;
+ }
+}
diff --git a/core/java/android/webkit/AccessibilityInjector.java b/core/java/android/webkit/AccessibilityInjector.java
index d6576e1..357a16e 100644
--- a/core/java/android/webkit/AccessibilityInjector.java
+++ b/core/java/android/webkit/AccessibilityInjector.java
@@ -96,11 +96,26 @@
// Template for JavaScript that performs AndroidVox actions.
private static final String ACCESSIBILITY_ANDROIDVOX_TEMPLATE =
- "cvox.AndroidVox.performAction('%1s')";
+ "(function() {" +
+ " if ((typeof(cvox) != 'undefined')"+
+ " && (typeof(cvox.ChromeVox) != 'undefined')" +
+ " && (typeof(cvox.AndroidVox) != 'undefined')" +
+ " && cvox.ChromeVox.isActive) {" +
+ " return cvox.AndroidVox.performAction('%1s');" +
+ " } else {" +
+ " return false;" +
+ " }" +
+ "})()";
// JS code used to shut down an active AndroidVox instance.
private static final String TOGGLE_CVOX_TEMPLATE =
- "javascript:(function() { cvox.ChromeVox.host.activateOrDeactivateChromeVox(%b); })();";
+ "javascript:(function() {" +
+ " if ((typeof(cvox) != 'undefined')"+
+ " && (typeof(cvox.ChromeVox) != 'undefined')" +
+ " && (typeof(cvox.ChromeVox.host) != 'undefined')) {" +
+ " cvox.ChromeVox.host.activateOrDeactivateChromeVox(%b);" +
+ " }" +
+ "})();";
/**
* Creates an instance of the AccessibilityInjector based on
@@ -776,20 +791,26 @@
while (true) {
try {
if (mResultId == resultId) {
+ if (DEBUG)
+ Log.w(TAG, "Received CVOX result");
return true;
}
if (mResultId > resultId) {
+ if (DEBUG)
+ Log.w(TAG, "Obsolete CVOX result");
return false;
}
final long elapsedTimeMillis = SystemClock.uptimeMillis() - startTimeMillis;
waitTimeMillis = RESULT_TIMEOUT - elapsedTimeMillis;
if (waitTimeMillis <= 0) {
+ if (DEBUG)
+ Log.w(TAG, "Timed out while waiting for CVOX result");
return false;
}
mResultLock.wait(waitTimeMillis);
} catch (InterruptedException ie) {
if (DEBUG)
- Log.w(TAG, "Timed out while waiting for CVOX result");
+ Log.w(TAG, "Interrupted while waiting for CVOX result");
/* ignore */
}
}
@@ -805,6 +826,8 @@
@JavascriptInterface
@SuppressWarnings("unused")
public void onResult(String id, String result) {
+ if (DEBUG)
+ Log.w(TAG, "Saw CVOX result of '" + result + "'");
final long resultId;
try {
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 4202a7f..6df7820 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -1480,7 +1480,6 @@
*
* @param listener an implementation of WebView.PictureListener
* @deprecated This method is now obsolete.
- * @hide Since API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}
*/
@Deprecated
public void setPictureListener(PictureListener listener) {
diff --git a/core/java/android/webkit/WebViewClassic.java b/core/java/android/webkit/WebViewClassic.java
index d68511c..7d0d0ba 100644
--- a/core/java/android/webkit/WebViewClassic.java
+++ b/core/java/android/webkit/WebViewClassic.java
@@ -5185,7 +5185,7 @@
if (cm.hasPrimaryClip()) {
Point cursorPoint = new Point(contentToViewX(mSelectCursorBase.x),
contentToViewY(mSelectCursorBase.y));
- Point cursorTop = calculateCaretTop();
+ Point cursorTop = calculateBaseCaretTop();
cursorTop.set(contentToViewX(cursorTop.x),
contentToViewY(cursorTop.y));
@@ -5229,17 +5229,22 @@
return scale;
}
+ private Point calculateBaseCaretTop() {
+ return calculateCaretTop(mSelectCursorBase, mSelectCursorBaseTextQuad);
+ }
+
+ private Point calculateDraggingCaretTop() {
+ return calculateCaretTop(mSelectDraggingCursor, mSelectDraggingTextQuad);
+ }
+
/**
* Assuming arbitrary shape of a quadralateral forming text bounds, this
* calculates the top of a caret.
*/
- private Point calculateCaretTop() {
- float scale = scaleAlongSegment(mSelectCursorBase.x, mSelectCursorBase.y,
- mSelectCursorBaseTextQuad.p4, mSelectCursorBaseTextQuad.p3);
- int x = Math.round(scaleCoordinate(scale,
- mSelectCursorBaseTextQuad.p1.x, mSelectCursorBaseTextQuad.p2.x));
- int y = Math.round(scaleCoordinate(scale,
- mSelectCursorBaseTextQuad.p1.y, mSelectCursorBaseTextQuad.p2.y));
+ private static Point calculateCaretTop(Point base, QuadF quad) {
+ float scale = scaleAlongSegment(base.x, base.y, quad.p4, quad.p3);
+ int x = Math.round(scaleCoordinate(scale, quad.p1.x, quad.p2.x));
+ int y = Math.round(scaleCoordinate(scale, quad.p1.y, quad.p2.y));
return new Point(x, y);
}
@@ -5269,12 +5274,20 @@
return true;
}
- private void updateWebkitSelection() {
+ private void updateWebkitSelection(boolean isSnapped) {
int handleId = (mSelectDraggingCursor == mSelectCursorBase)
? HANDLE_ID_BASE : HANDLE_ID_EXTENT;
+ int x = mSelectDraggingCursor.x;
+ int y = mSelectDraggingCursor.y;
+ if (isSnapped) {
+ // "center" the cursor in the snapping quad
+ Point top = calculateDraggingCaretTop();
+ x = Math.round((top.x + x) / 2);
+ y = Math.round((top.y + y) / 2);
+ }
mWebViewCore.removeMessages(EventHub.SELECT_TEXT);
mWebViewCore.sendMessageAtFrontOfQueue(EventHub.SELECT_TEXT,
- mSelectDraggingCursor.x, mSelectDraggingCursor.y, (Integer)handleId);
+ x, y, (Integer)handleId);
}
private void resetCaretTimer() {
@@ -5616,7 +5629,7 @@
Math.max(0, mEditTextContentBounds.top - buffer),
mEditTextContentBounds.right + buffer,
mEditTextContentBounds.bottom + buffer);
- Point caretTop = calculateCaretTop();
+ Point caretTop = calculateBaseCaretTop();
if (visibleRect.width() < mEditTextContentBounds.width()) {
// The whole edit won't fit in the width, so use the caret rect
if (mSelectCursorBase.x < caretTop.x) {
@@ -5947,10 +5960,12 @@
} else {
endScrollEdit();
}
+ boolean snapped = false;
if (inCursorText || (mIsEditingText && !inEditBounds)) {
snapDraggingCursor();
+ snapped = true;
}
- updateWebkitSelection();
+ updateWebkitSelection(snapped);
if (!inCursorText && mIsEditingText && inEditBounds) {
// Visually snap even if we have moved the handle.
snapDraggingCursor();
@@ -6277,7 +6292,7 @@
int oldX = mSelectDraggingCursor.x;
int oldY = mSelectDraggingCursor.y;
mSelectDraggingCursor.set(selectionX, selectionY);
- updateWebkitSelection();
+ updateWebkitSelection(false);
scrollEditText(scrollX, scrollY);
mSelectDraggingCursor.set(oldX, oldY);
}
diff --git a/core/jni/android_os_UEventObserver.cpp b/core/jni/android_os_UEventObserver.cpp
index 7033ff3c..3f7c7d28 100644
--- a/core/jni/android_os_UEventObserver.cpp
+++ b/core/jni/android_os_UEventObserver.cpp
@@ -49,7 +49,7 @@
// Consider all zero-delimited fields of the buffer.
const char* field = buffer;
- const char* end = buffer + length;
+ const char* end = buffer + length + 1;
do {
if (strstr(field, match.string())) {
ALOGV("Matched uevent message with pattern: %s", match.string());
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 9ce7f8a..384f1ab 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -1197,8 +1197,8 @@
<!-- A coordinate in the Y dimension. -->
<attr name="y" format="dimension" />
- <!-- Specifies how to place the content of an object, both
- on the x- and y-axis, within the object itself. -->
+ <!-- Specifies how an object should position its content, on both the X and Y axes,
+ within its own bounds. -->
<attr name="gravity">
<!-- Push object to the top of its container, not changing its size. -->
<flag name="top" value="0x30" />
@@ -1257,8 +1257,8 @@
<!-- Reference to an array resource that will populate a list/adapter. -->
<attr name="entries" format="reference" />
- <!-- Standard gravity constant that a child can supply to its parent.
- Defines how to place the view, both its x- and y-axis, within its parent view group. -->
+ <!-- Standard gravity constant that a child supplies to its parent.
+ Defines how the child view should be positioned, on both the X and Y axes, within its enclosing layout. -->
<attr name="layout_gravity">
<!-- Push object to the top of its container, not changing its size. -->
<flag name="top" value="0x30" />
diff --git a/data/sounds/AudioPackage8.mk b/data/sounds/AudioPackage8.mk
new file mode 100755
index 0000000..93c43da
--- /dev/null
+++ b/data/sounds/AudioPackage8.mk
@@ -0,0 +1,70 @@
+#
+# Audio Package 7 - Tuna
+#
+# Include this file in a product makefile to include these audio files
+#
+#
+
+LOCAL_PATH:= frameworks/base/data/sounds
+
+PRODUCT_COPY_FILES += \
+ $(LOCAL_PATH)/alarms/ogg/Cesium.ogg:system/media/audio/alarms/Cesium.ogg \
+ $(LOCAL_PATH)/alarms/ogg/Fermium.ogg:system/media/audio/alarms/Fermium.ogg \
+ $(LOCAL_PATH)/alarms/ogg/Hassium.ogg:system/media/audio/alarms/Hassium.ogg \
+ $(LOCAL_PATH)/alarms/ogg/Neptunium.ogg:system/media/audio/alarms/Neptunium.ogg \
+ $(LOCAL_PATH)/alarms/ogg/Nobelium.ogg:system/media/audio/alarms/Nobelium.ogg \
+ $(LOCAL_PATH)/alarms/ogg/Osmium.ogg:system/media/audio/alarms/Osmium.ogg \
+ $(LOCAL_PATH)/alarms/ogg/Plutonium.ogg:system/media/audio/alarms/Plutonium.ogg \
+ $(LOCAL_PATH)/alarms/ogg/Promethium.ogg:system/media/audio/alarms/Promethium.ogg \
+ $(LOCAL_PATH)/effects/ogg/Effect_Tick.ogg:system/media/audio/ui/Effect_Tick.ogg \
+ $(LOCAL_PATH)/effects/ogg/KeypressStandard_120.ogg:system/media/audio/ui/KeypressStandard.ogg \
+ $(LOCAL_PATH)/effects/ogg/KeypressSpacebar_120.ogg:system/media/audio/ui/KeypressSpacebar.ogg \
+ $(LOCAL_PATH)/effects/ogg/KeypressDelete_120.ogg:system/media/audio/ui/KeypressDelete.ogg \
+ $(LOCAL_PATH)/effects/ogg/KeypressReturn_120.ogg:system/media/audio/ui/KeypressReturn.ogg \
+ $(LOCAL_PATH)/effects/ogg/VideoRecord.ogg:system/media/audio/ui/VideoRecord.ogg \
+ $(LOCAL_PATH)/effects/ogg/camera_click.ogg:system/media/audio/ui/camera_click.ogg \
+ $(LOCAL_PATH)/effects/ogg/camera_focus.ogg:system/media/audio/ui/camera_focus.ogg \
+ $(LOCAL_PATH)/effects/ogg/LowBattery.ogg:system/media/audio/ui/LowBattery.ogg \
+ $(LOCAL_PATH)/effects/ogg/Dock.ogg:system/media/audio/ui/Dock.ogg \
+ $(LOCAL_PATH)/effects/ogg/Undock.ogg:system/media/audio/ui/Undock.ogg \
+ $(LOCAL_PATH)/effects/ogg/Lock.ogg:system/media/audio/ui/Lock.ogg \
+ $(LOCAL_PATH)/effects/ogg/Unlock.ogg:system/media/audio/ui/Unlock.ogg \
+ $(LOCAL_PATH)/notifications/ogg/Adara.ogg:system/media/audio/notifications/Adara.ogg \
+ $(LOCAL_PATH)/notifications/ogg/Arcturus.ogg:system/media/audio/notifications/Arcturus.ogg \
+ $(LOCAL_PATH)/notifications/ogg/Bellatrix.ogg:system/media/audio/notifications/Bellatrix.ogg \
+ $(LOCAL_PATH)/notifications/ogg/Capella.ogg:system/media/audio/notifications/Capella.ogg \
+ $(LOCAL_PATH)/notifications/ogg/CetiAlpha.ogg:system/media/audio/notifications/CetiAlpha.ogg \
+ $(LOCAL_PATH)/notifications/ogg/Hojus.ogg:system/media/audio/notifications/Hojus.ogg \
+ $(LOCAL_PATH)/notifications/ogg/Lalande.ogg:system/media/audio/notifications/Lalande.ogg \
+ $(LOCAL_PATH)/notifications/ogg/Mira.ogg:system/media/audio/notifications/Mira.ogg \
+ $(LOCAL_PATH)/notifications/ogg/Polaris.ogg:system/media/audio/notifications/Polaris.ogg \
+ $(LOCAL_PATH)/notifications/ogg/Pollux.ogg:system/media/audio/notifications/Pollux.ogg \
+ $(LOCAL_PATH)/notifications/ogg/Procyon.ogg:system/media/audio/notifications/Procyon.ogg \
+ $(LOCAL_PATH)/notifications/ogg/Proxima.ogg:system/media/audio/notifications/Proxima.ogg \
+ $(LOCAL_PATH)/notifications/ogg/Shaula.ogg:system/media/audio/notifications/Shaula.ogg \
+ $(LOCAL_PATH)/notifications/ogg/Spica.ogg:system/media/audio/notifications/Spica.ogg \
+ $(LOCAL_PATH)/notifications/ogg/Tejat.ogg:system/media/audio/notifications/Tejat.ogg \
+ $(LOCAL_PATH)/notifications/ogg/Upsilon.ogg:system/media/audio/notifications/Upsilon.ogg \
+ $(LOCAL_PATH)/notifications/ogg/Vega.ogg:system/media/audio/notifications/Vega.ogg \
+ $(LOCAL_PATH)/ringtones/ogg/Andromeda.ogg:system/media/audio/ringtones/Andromeda.ogg \
+ $(LOCAL_PATH)/ringtones/ogg/Aquila.ogg:system/media/audio/ringtones/Aquila.ogg \
+ $(LOCAL_PATH)/ringtones/ogg/ArgoNavis.ogg:system/media/audio/ringtones/ArgoNavis.ogg \
+ $(LOCAL_PATH)/ringtones/ogg/CanisMajor.ogg:system/media/audio/ringtones/CanisMajor.ogg \
+ $(LOCAL_PATH)/ringtones/ogg/Carina.ogg:system/media/audio/ringtones/Carina.ogg \
+ $(LOCAL_PATH)/ringtones/ogg/Centaurus.ogg:system/media/audio/ringtones/Centaurus.ogg \
+ $(LOCAL_PATH)/ringtones/ogg/Cygnus.ogg:system/media/audio/ringtones/Cygnus.ogg \
+ $(LOCAL_PATH)/ringtones/ogg/Draco.ogg:system/media/audio/ringtones/Draco.ogg \
+ $(LOCAL_PATH)/ringtones/ogg/Girtab.ogg:system/media/audio/ringtones/Girtab.ogg \
+ $(LOCAL_PATH)/ringtones/ogg/Hydra.ogg:system/media/audio/ringtones/Hydra.ogg \
+ $(LOCAL_PATH)/ringtones/ogg/Machina.ogg:system/media/audio/ringtones/Machina.ogg \
+ $(LOCAL_PATH)/ringtones/ogg/Orion.ogg:system/media/audio/ringtones/Orion.ogg \
+ $(LOCAL_PATH)/ringtones/ogg/Pegasus.ogg:system/media/audio/ringtones/Pegasus.ogg \
+ $(LOCAL_PATH)/ringtones/ogg/Perseus.ogg:system/media/audio/ringtones/Perseus.ogg \
+ $(LOCAL_PATH)/ringtones/ogg/Pyxis.ogg:system/media/audio/ringtones/Pyxis.ogg \
+ $(LOCAL_PATH)/ringtones/ogg/Rigel.ogg:system/media/audio/ringtones/Rigel.ogg \
+ $(LOCAL_PATH)/ringtones/ogg/Scarabaeus.ogg:system/media/audio/ringtones/Scarabaeus.ogg \
+ $(LOCAL_PATH)/ringtones/ogg/Sceptrum.ogg:system/media/audio/ringtones/Sceptrum.ogg \
+ $(LOCAL_PATH)/ringtones/ogg/Solarium.ogg:system/media/audio/ringtones/Solarium.ogg \
+ $(LOCAL_PATH)/ringtones/ogg/Themos.ogg:system/media/audio/ringtones/Themos.ogg \
+ $(LOCAL_PATH)/ringtones/ogg/UrsaMinor.ogg:system/media/audio/ringtones/UrsaMinor.ogg \
+ $(LOCAL_PATH)/ringtones/ogg/Zeta.ogg:system/media/audio/ringtones/Zeta.ogg
diff --git a/data/sounds/alarms/ogg/Fermium.ogg b/data/sounds/alarms/ogg/Fermium.ogg
index fecc2ba..d8f6124 100644
--- a/data/sounds/alarms/ogg/Fermium.ogg
+++ b/data/sounds/alarms/ogg/Fermium.ogg
Binary files differ
diff --git a/data/sounds/alarms/ogg/Hassium.ogg b/data/sounds/alarms/ogg/Hassium.ogg
index 260bf7d..793c269 100644
--- a/data/sounds/alarms/ogg/Hassium.ogg
+++ b/data/sounds/alarms/ogg/Hassium.ogg
Binary files differ
diff --git a/data/sounds/alarms/ogg/Neptunium.ogg b/data/sounds/alarms/ogg/Neptunium.ogg
index b1ea741..d99f133 100644
--- a/data/sounds/alarms/ogg/Neptunium.ogg
+++ b/data/sounds/alarms/ogg/Neptunium.ogg
Binary files differ
diff --git a/data/sounds/alarms/ogg/Osmium.ogg b/data/sounds/alarms/ogg/Osmium.ogg
new file mode 100644
index 0000000..4c76080
--- /dev/null
+++ b/data/sounds/alarms/ogg/Osmium.ogg
Binary files differ
diff --git a/data/sounds/alarms/ogg/Promethium.ogg b/data/sounds/alarms/ogg/Promethium.ogg
new file mode 100644
index 0000000..2a195a3
--- /dev/null
+++ b/data/sounds/alarms/ogg/Promethium.ogg
Binary files differ
diff --git a/data/sounds/alarms/wav/Fermium.wav b/data/sounds/alarms/wav/Fermium.wav
index 0174884..56e57fc 100644
--- a/data/sounds/alarms/wav/Fermium.wav
+++ b/data/sounds/alarms/wav/Fermium.wav
Binary files differ
diff --git a/data/sounds/alarms/wav/Hassium.wav b/data/sounds/alarms/wav/Hassium.wav
index e3992cf..17710b0 100644
--- a/data/sounds/alarms/wav/Hassium.wav
+++ b/data/sounds/alarms/wav/Hassium.wav
Binary files differ
diff --git a/data/sounds/alarms/wav/Neptunium.wav b/data/sounds/alarms/wav/Neptunium.wav
index cf3684a..2b855e1 100644
--- a/data/sounds/alarms/wav/Neptunium.wav
+++ b/data/sounds/alarms/wav/Neptunium.wav
Binary files differ
diff --git a/data/sounds/alarms/wav/Osmium.wav b/data/sounds/alarms/wav/Osmium.wav
new file mode 100755
index 0000000..2dcc47f
--- /dev/null
+++ b/data/sounds/alarms/wav/Osmium.wav
Binary files differ
diff --git a/data/sounds/alarms/wav/Promethium.wav b/data/sounds/alarms/wav/Promethium.wav
new file mode 100755
index 0000000..08ea03e
--- /dev/null
+++ b/data/sounds/alarms/wav/Promethium.wav
Binary files differ
diff --git a/docs/html/guide/topics/ui/notifiers/notifications.jd b/docs/html/guide/topics/ui/notifiers/notifications.jd
index 273b5f7..fbff532 100644
--- a/docs/html/guide/topics/ui/notifiers/notifications.jd
+++ b/docs/html/guide/topics/ui/notifiers/notifications.jd
@@ -1,646 +1,902 @@
-page.title=Status Notifications
-parent.title=Notifications
-parent.link=index.html
+page.title=Notifications
@jd:body
<div id="qv-wrapper">
- <div id="qv">
- <h2>Quickview</h2>
- <ul>
- <li>A status notification allows your application to notify the user of an event
-without interupting their current activity</li>
- <li>You can attach an intent to your notification that the system will initiate when the
-user clicks it</li>
- </ul>
-
- <h2>In this document</h2>
+<div id="qv">
+<h2>In this document</h2>
<ol>
- <li><a href="#Basics">The Basics</a></li>
- <li><a href="#HandlingNotifications">Responding to Notifications</a></li>
- <li><a href="#ManageYourNotifications">Managing your Notifications</a></li>
- <li><a href="#CreateANotification">Creating a Notification</a>
- <ol>
- <li><a href="#Updating">Updating the notification</a></li>
- <li><a href="#Sound">Adding a sound</a></li>
- <li><a href="#Vibration">Adding vibration</a></li>
- <li><a href="#Lights">Adding flashing lights</a></li>
- <li><a href="#More">More features</a></li>
- </ol>
- </li>
- <li><a href="#CustomExpandedView">Creating a Custom Notification Layout</a></li>
+ <li>
+ <a href="#NotificationUI">Notification Display Elements</a>
+ </li>
+ <li>
+ <a href="#CreateNotification">Creating a Notification</a>
+ </li>
+ <li>
+ <a href="#Managing">Managing Notifications</a>
+ </li>
+ <li>
+ <a href="#NotificationResponse">Preserving Navigation when Starting an Activity</a>
+ </li>
+ <li>
+ <a href="#Progress">Displaying Progress in a Notification</a>
+ </li>
+ <li>
+ <a href="#CustomNotification">Custom Notification Layouts</a>
+ </li>
</ol>
<h2>Key classes</h2>
<ol>
- <li>{@link android.app.Notification}</li>
- <li>{@link android.app.NotificationManager}</li>
+ <li>{@link android.app.NotificationManager}</li>
+ <li>{@link android.support.v4.app.NotificationCompat}</li>
</ol>
-
- <h2>See also</h2>
+ <h2>Videos</h2>
<ol>
- <li><a href="{@docRoot}design/patterns/notifications.html">Android
-Design: Notifications</a></li>
+ <li>
+ <a href="http://www.youtube.com/watch?v=Yc8YrVc47TI&feature=player_detailpage#t=1672s">
+ Notifications in 4.1</a>
+ </li>
</ol>
- </div>
+<h2>See also</h2>
+<ol>
+ <li>
+ <a href="{@docRoot}design/patterns/notifications.html">Android Design: Notifications</a>
+ </li>
+</ol>
</div>
-
-<p>A status notification adds an icon to the system's status bar
-(with an optional ticker-text message) and a notification message in the notifications window.
-When the user selects the notification, Android fires an
-{@link android.content.Intent} that is defined by the {@link android.app.Notification} (usually to
-launch an {@link android.app.Activity}).
-You can also configure the notification to alert the user with a sound, a vibration, and flashing
-lights on the device.</p>
-
-<p>A status notification should be used for any case in
-which a background service needs to alert the user about an event that requires a response. A
-background service
-<strong>should never</strong> launch an activity on its own in order to receive user interaction.
-The service should instead create a status notification that will launch the activity
-when selected by the user.</p>
-
-<p>Figure 1 shows the status bar with a notification icon on the left side.</p>
-<img src="{@docRoot}images/status_bar.png" alt="" />
-<p class="img-caption"><strong>Figure 1.</strong> Status bar with a notification.</p>
-
-<p>Figure 2 shows the notification's message in the notifications window.</p>
-
-<img src="{@docRoot}images/notifications_window.png" alt="" />
-<p class="img-caption"><strong>Figure 2.</strong> The notifications window.</p>
-
-
+</div>
+<p>
+ A notification is a message you can display to the user outside of your application's
+ normal UI. When you tell the system to issue a notification, it first appears as an icon in the
+ <strong>notification area</strong>. To see the details of the notification, the user opens the
+ <strong>notification drawer</strong>. Both the notification area and the notification drawer
+ are system-controlled areas that the user can view at any time.
+</p>
+<img
+ id="figure1"
+ src="{@docRoot}images/ui/notifications/iconic_notification.png"
+ height="32"
+ alt="" />
+<p class="img-caption">
+ <strong>Figure 1.</strong> Notifications in the notification area.
+</p>
+<img id="figure2" src="{@docRoot}images/ui/notifications/normal_notification.png"
+ height="240" alt="" />
+<p class="img-caption">
+ <strong>Figure 2.</strong> Notifications in the notification drawer.
+</p>
<div class="note design">
-<p><strong>Notification Design</strong></p>
- <p>For design guidelines, read Android Design's <a
-href="{@docRoot}design/patterns/notifications.html">Notifications</a> guide.</p>
+ <p>
+ <strong>Notification Design</strong>
+ </p>
+ <p>
+ Notifications, as an important part of the Android UI, have their own design guidelines. To
+ learn how to design notifications and their interactions, read the Android Design Guide
+ <a href="{@docRoot}design/patterns/notifications.html">Notifications</a> topic.
+ </p>
</div>
-
-
-
-<h2 id="Basics">The Basics</h2>
-
-<p>An {@link android.app.Activity} or {@link android.app.Service} can initiate a status
-notification. Because an activity can perform actions only while it is
-running in the foreground and its window has focus, you will usually create status notifications
-from a
-service. This way, the notification can be created from the background,
-while the user is using another application or
-while the device is asleep. To create a notification, you must use two
-classes: {@link android.app.Notification} and {@link android.app.NotificationManager}.</p>
-
-<p>Use an instance of the {@link android.app.Notification} class to define the properties of your
-status notification, such as the status icon, the notification message, and extra settings
-such as a sound to play. The {@link android.app.NotificationManager} is an Android system service
-that executes and manages all status notifications. You do not instantiate the
-{@link android.app.NotificationManager} directly. In order
-to give it your {@link android.app.Notification}, you must retrieve a reference to the
-{@link android.app.NotificationManager} with
-{@link android.app.Activity#getSystemService(String) getSystemService()} and
-then, when you want to notify the user, pass it your {@link android.app.Notification} with
-{@link android.app.NotificationManager#notify(int,Notification) notify()}. </p>
-
-<p>To create a status notification:</p>
-<ol>
- <li>Get a reference to the {@link android.app.NotificationManager}:
-<pre>
-String ns = Context.NOTIFICATION_SERVICE;
-NotificationManager mNotificationManager = (NotificationManager) getSystemService(ns);
-</pre>
- </li>
- <!-- use Notification.Builder in 3.0 -->
- <li>Instantiate the {@link android.app.Notification}:
-<pre>
-int icon = R.drawable.notification_icon;
-CharSequence tickerText = "Hello";
-long when = System.currentTimeMillis();
-
-Notification notification = new Notification(icon, tickerText, when);
-</pre>
- </li>
- <li>Define the notification's message and {@link android.app.PendingIntent}:
-<pre>
-Context context = getApplicationContext();
-CharSequence contentTitle = "My notification";
-CharSequence contentText = "Hello World!";
-Intent notificationIntent = new Intent(this, MyClass.class);
-PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
-
-notification.setLatestEventInfo(context, contentTitle, contentText, contentIntent);
-</pre>
- </li>
- <li>Pass the {@link android.app.Notification} to the {@link android.app.NotificationManager}:
-<pre>
-private static final int HELLO_ID = 1;
-
-mNotificationManager.notify(HELLO_ID, notification);
-</pre>
- <p>That's it. Your user has now been notified.</p>
- </li>
-</ol>
-
-
-<h2 id="HandlingNotifications">Responding to Notifications</h2>
-
-<p>A central part of the user's experience with a notification revolves around
-how it interacts with the application's UI flow. You must implement
-this correctly to provide a consistent user experience within your app.</p>
-
-<p>Two typical examples of notifications are provided by Calendar, which can send out
-notifications of upcoming events, and Email, which can send out notifications
-when new messages arrive. These represent the two recommended patterns for handling
-notifications: either launching into an activity that is separate from the
-main application, or launching an entirely new instance of the application
-showing the appropriate point for the notification.</p>
-
-<p>The following scenario shows how the activity stack should work
-in these two typical notification flows, first handling a Calendar notification:
+<p class="note">
+ <strong>Note:</strong> This guide refers to the
+ {@link android.support.v4.app.NotificationCompat.Builder NotificationCompat.Builder} class
+ in the version 4 <a href="{@docRoot}tools/extras/support-library.html">Support Library</a>.
+ The class {@link android.app.Notification.Builder Notification.Builder} was added in API
+ level 11.
</p>
-
-<ol>
- <li>User is creating a new event in Calendar. They realize they
- need to copy part of an email message into this event.
- </li>
- <li>
- The user chooses Home > Email.
- </li>
- <li>
- While in Email, they receive a notification from Calendar for an upcoming
- meeting.
- </li>
- <li>
- So they choose that notification, which takes them to a
- dedicated Calendar activity that displays brief details of the
- upcoming meeting.
- </li>
- <li>
- The user has seen enough to know they have a meeting coming up,
- so they press the <em>Back</em> button. They are now returned to Email, which
- is where they were when they took the notification.
- </li>
-</ol>
-
-<p>Handling an Email notification:</p>
-
-<ol>
- <li>
- The user is currently in Email composing a message, and needs to
- check a date in their calendar.
- </li>
- <li>
- The user chooses Home > Calendar.
- </li>
- <li>
- While in Calendar, they receive a notification from Email about a new
- message.
- </li>
- <li>
- They select the notification, which brings them to Email with the message
- details displayed. This has replaced what they were previously doing
- (writing an e-mail), but that message is still saved in their drafts.
- </li>
- <li>
- The user presses <em>Back</em> once to go to the message list (the typical flow in the
- Email app), and press <em>Back</em> again to return to Calendar as they left it.
- </li>
-</ol>
-
-<p>In an Email style of notification, the UI launched by the notification
-shows the main application in a state representing that notification.
-For example, when the Email application comes to the foreground from its
-notification, it displays either the conversion list or a specific
-conversation depending on whether there are multiple or only one new
-email. To achieve this, we want to completely replace whatever current
-state the application is in with a new activity stack representing the
-new notification state.</p>
-
-<p>The following code illustrates how to show this kind of notification. Of
-most interest is the <code>makeMessageIntentStack()</code> method, which constructs
-an array of intents representing the app's new activity stack for this state.
-(If you are using fragments, you may need to initialize your fragment and
-app state so that pressing <em>Back</em> will switch the UI back to its parent state.)
-The core of this is the {@link android.content.Intent#makeRestartActivityTask
-Intent.makeRestartActivityTask()} method, which constructs the root activity
-of the stack with the appropriate flags, such as
-{@link android.content.Intent#FLAG_ACTIVITY_CLEAR_TASK Intent.FLAG_ACTIVITY_CLEAR_TASK}.</p>
-
-{@sample development/samples/ApiDemos/src/com/example/android/apis/app/IncomingMessage.java
- app_notification}
-
-<p>In a Calendar style of notification, the UI launched by the notification
-is a dedicated activity that is not part of the normal application flow.
-For example, when the user receives a Calendar notification, choosing that
-notification starts a special activity that displays a list
-of upcoming calendar events — this view is available only
-from the notification, not through the Calendar's normal user
-interface.</p>
-
-<p>The code for posting this type of notification is very straight-forward; it
-is like the above, but the {@link android.app.PendingIntent} is for just a single
-activity, our dedicated notification activity.</p>
-
-{@sample development/samples/ApiDemos/src/com/example/android/apis/app/IncomingMessage.java
- interstitial_notification}
-
-<p>This is not enough, however. Normally Android considers all activities within
-an application to be part of that application's UI flow, so simply launching the
-activity like this can cause it to be mixed with your normal application back stack
-in undesired ways. To make it behave correctly, in the manifest declaration
-for the activity the attributes
-<code>android:launchMode="singleTask"</code>,
-<code>android:taskAffinity=""</code> and
-<code>android:excludeFromRecents="true"</code>
-must be set. The full activity declaration for this sample is:</p>
-
-{@sample development/samples/ApiDemos/AndroidManifest.xml interstitial_affinity}
-
-<p>You must be careful when launching other activities from this initial activity,
-because this is not a top-level part of the application, does not appear in
-recents, and needs to be relaunched at any point from the notification with new data
-to show. This best approach is to make sure any activity launched from it is
-launched in its own task. When doing this care must be taken to make sure this
-new task interacts well with the current state of your exiting application's
-task. This is essentially
-the same as switching to the main application as described for the Email style
-notification shown before. Given the <code>makeMessageIntentStack()</code>
-method previously shown, handling a click then would look something like this:</p>
-
-{@sample development/samples/ApiDemos/src/com/example/android/apis/app/IncomingMessageInterstitial.java
- app_launch}
-
-<h2 id="ManageYourNotifications">Managing your Notifications</h2>
-
-<p>The {@link android.app.NotificationManager} is a system service that manages all
-notifications. You must retrieve a reference to it with the
-{@link android.app.Activity#getSystemService(String) getSystemService()} method.
-For example:</p>
-<pre>
-String ns = Context.NOTIFICATION_SERVICE;
-NotificationManager mNotificationManager = (NotificationManager) getSystemService(ns);
-</pre>
-
-<p>When you want to deliver your status notification, pass the {@link android.app.Notification}
-to the {@link android.app.NotificationManager} with {@link
-android.app.NotificationManager#notify(int,Notification)}.
-The first parameter is the unique ID for the notification and the second is the {@link
-android.app.Notification} object.
-The ID uniquely identifies the notification from within your
-application. The ID is necessary if you need to update the notification or (if
-your application manages different kinds of notifications) select the appropriate action
-when the user returns to your application via the intent defined in the notification.</p>
-
-<p>To clear the status notification when the user selects it from the notifications
-window, add the "FLAG_AUTO_CANCEL" flag to your {@link android.app.Notification}. You can
-also clear it manually with {@link android.app.NotificationManager#cancel(int)}, passing it the
-notification ID, or clear all your notifications with {@link
-android.app.NotificationManager#cancelAll()}.</p>
-
-
-<h2 id="CreateANotification">Creating a Notification</h2>
-
-<p>A {@link android.app.Notification} object defines the details of the notification
-message that is displayed in the status bar and notifications window, and any other
-alert settings, such as sounds and blinking lights.</p>
-
-<p>A status notification <em>requires</em> all of the following:</p>
-<ul>
- <li>An icon for the status bar</li>
- <li>A title and message, unless you define a
- <a href="#CustomExpandedView">custom notification layout</a></li>
- <li>A {@link android.app.PendingIntent}, to be fired when the notification is selected</li>
-</ul>
-<p>Optional settings for the status notification include:</p>
-<ul>
- <li>A ticker-text message for the status bar</li>
- <li>An alert sound</li>
- <li>A vibrate setting</li>
- <li>A flashing LED setting</li>
-</ul>
-
-<p>The starter-kit for a new notification includes the
-{@link android.app.Notification#Notification(int,CharSequence,long)} constructor and the
-{@link android.app.Notification#setLatestEventInfo(Context,CharSequence,CharSequence,PendingIntent)}
-method. These define all the required settings for a notification.
-The following snippet demonstrates a basic notification setup:</p>
-<pre>
-int icon = R.drawable.notification_icon; // icon from resources
-CharSequence tickerText = "Hello"; // ticker-text
-long when = System.currentTimeMillis(); // notification time
-Context context = getApplicationContext(); // application Context
-CharSequence contentTitle = "My notification"; // message title
-CharSequence contentText = "Hello World!"; // message text
-
-Intent notificationIntent = new Intent(this, MyClass.class);
-PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
-
-// the next two lines initialize the Notification, using the configurations above
-Notification notification = new Notification(icon, tickerText, when);
-notification.setLatestEventInfo(context, contentTitle, contentText, contentIntent);
-</pre>
-
-
-<h3 id="Updating">Updating the notification</h3>
-
-<p>You can update the information in your status notification as events
-continue to occur in your application. For example, when a new SMS text message arrives
-before previous messages have been read, the Messaging application updates the existing
-notification to display the total number of new messages received.
-This practice of updating an existing notification is much better than adding new
-notifications, because it avoids clutter in the notifications window.</p>
-
-<p>Because each notification is uniquely identified
-by the {@link android.app.NotificationManager} with an integer ID, you can revise the notification
-by calling {@link
-android.app.Notification#setLatestEventInfo(Context,CharSequence,CharSequence,PendingIntent)
-setLatestEventInfo()} with new values, change some field values of the notification, and then call
-{@link android.app.NotificationManager#notify(int,Notification) notify()} again.</p>
-
-<p>You can revise each property with the object member fields
-(except for the {@link android.content.Context} and the notification title and text). You
-should always revise the text message when you update the notification by calling
-{@link android.app.Notification#setLatestEventInfo(Context,CharSequence,CharSequence,PendingIntent)
-setLatestEventInfo()} with new values for <var>contentTitle</var> and <var>contentText</var>.
-Then call {@link android.app.NotificationManager#notify(int,Notification) notify()} to update the
-notification. (Of course, if you've created a <a href="#CustomExpandedView">custom notification
-layout</a>, then updating these title and text values has no effect.)</p>
-
-
-<h3 id="Sound">Adding a sound</h3>
-
-<p>You can alert the user with the default notification sound
-(which is defined by the user) or with a sound specified by your application.</p>
-
-<p>To use the user's default sound, add "DEFAULT_SOUND" to the <var>defaults</var> field:</p>
-<pre>
-notification.defaults |= Notification.DEFAULT_SOUND;
-</pre>
-
-<p>To use a different sound with your notifications, pass a Uri reference to the
-<var>sound</var> field.
-The following example uses a known audio file saved to the device SD card:</p>
-<pre>
-notification.sound = Uri.parse("file:///sdcard/notification/ringer.mp3");
-</pre>
-
-<p>In the next example, the audio file is chosen from the internal
-{@link android.provider.MediaStore.Audio.Media MediaStore}'s {@link android.content.ContentProvider}:</p>
-<pre>
-notification.sound = Uri.withAppendedPath(Audio.Media.INTERNAL_CONTENT_URI, "6");
-</pre>
-
-<p>In this case, the exact ID of the media file ("6") is known and appended to the content
-{@link android.net.Uri}. If you don't know the exact ID, you must query all the
-media available in the {@link android.provider.MediaStore} with a {@link
-android.content.ContentResolver}.
-See the <a href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a>
-documentation for more information on using a ContentResolver.</p>
-
-<p>If you want the sound to continuously repeat until the user responds to the notification
-or the notification is cancelled, add {@link android.app.Notification#FLAG_INSISTENT} to the
-<var>flags</var> field.</p>
-
-<p class="note"><strong>Note:</strong> If the <var>defaults</var> field includes
-{@link android.app.Notification#DEFAULT_SOUND}, then the default sound overrides any sound defined
-by the <var>sound</var> field.</p>
-
-
-<h3 id="Vibration">Adding vibration</h3>
-
-<p>You can alert the user with the the default
-vibration pattern or with a vibration pattern defined by your application.</p>
-
-<p>To use the default pattern, add {@link android.app.Notification#DEFAULT_VIBRATE} to the
-<var>defaults</var> field:</p>
-<pre>
-notification.defaults |= Notification.DEFAULT_VIBRATE;
-</pre>
-
-<p>To define your own vibration pattern, pass an array of <em>long</em> values to the
-<var>vibrate</var> field:</p>
-<pre>
-long[] vibrate = {0,100,200,300};
-notification.vibrate = vibrate;
-</pre>
-
-<p>The long array defines the alternating pattern for the length of vibration off and on
-(in milliseconds). The first value is how long to wait (off) before beginning, the second
-value is the length of the first vibration, the third is the next length off, and so on.
-The pattern can be as long as you like, but it can't be set to repeat.
+<!-- ------------------------------------------------------------------------------------------ -->
+<!-- ------------------------------------------------------------------------------------------ -->
+<h2 id="NotificationUI">Notification Display Elements</h2>
+<p>
+ Notifications in the notification drawer appear in two main visual styles, normal view and
+ big view.
</p>
-
-<p class="note"><strong>Note:</strong> If the <var>defaults</var> field includes
-{@link android.app.Notification#DEFAULT_VIBRATE}, then the default vibration overrides any vibration
-defined by the
-<var>vibrate</var> field.</p>
-
-
-<h3 id="Lights">Adding flashing lights</h3>
-
-<p>To alert the user by flashing LED lights, you can implement the default
-light pattern (if available), or define your own color and pattern for the lights.</p>
-
-<p>To use the default light setting, add {@link android.app.Notification#DEFAULT_LIGHTS} to the
-<var>defaults</var> field:</p>
-<pre>
-notification.defaults |= Notification.DEFAULT_LIGHTS;
-</pre>
-
-<p>To define your own color and pattern, define a value for the <var>ledARGB</var> field
-(for the color), the <var>ledOffMS</var> field (length of time, in milliseconds, to
-keep the light off), the <var>ledOnMS</var> (length of time, in milliseconds, to keep the light on),
-and also add {@link android.app.Notification#FLAG_SHOW_LIGHTS} to the <var>flags</var> field:</p>
-<pre>
-notification.ledARGB = 0xff00ff00;
-notification.ledOnMS = 300;
-notification.ledOffMS = 1000;
-notification.flags |= Notification.FLAG_SHOW_LIGHTS;
-</pre>
-
-<p>In this example, the green light repeatedly flashes on for 300 milliseconds and
-turns off for one second. Not every color in the spectrum is supported by the
-device LEDs, and not every device supports the same colors, so the hardware
-estimates to the best of its ability. Green is the most common notification color.</p>
-
-
-<h3 id="More">More features</h3>
-
-<p>You can add several more features to your notifications
-using {@link android.app.Notification} fields and flags. Some useful features include the
-following:</p>
-
+<!-- ------------------------------------------------------------------------------------------ -->
+<h3 id="NormalNotify">Normal view</h3>
+<p>
+ A notification in normal view appears in an area that's up to 64 dp tall. Even if you create a
+ notification with a big view style, it will appear in normal view until it's expanded. This
+ is an example of a normal view:
+</p>
+<img
+ src="{@docRoot}images/ui/notifications/normal_notification_callouts.png"
+ alt=""
+ height="204"
+ id="figure3" />
+<p class="img-caption">
+ <strong>Figure 3.</strong> Notification in normal view.
+</p>
+<p>
+ The callouts in the illustration refer to the following:
+</p>
+<ol>
+ <li>Content title</li>
+ <li>Large icon</li>
+ <li>Content text</li>
+ <li>Content info</li>
+ <li>Small icon</li>
+ <li>
+ Time that the notification was issued. You can set an explicit value with
+ {@link android.support.v4.app.NotificationCompat.Builder#setWhen setWhen()}; if you don't
+ it defaults to the time that the system received the notification.
+ </li>
+</ol>
+<!-- ------------------------------------------------------------------------------------------ -->
+<h3 id="BigNotify">Big view</h3>
+<p>
+ A notification's big view appears only when the notification is expanded, which happens when the
+ notification is at the top of the notification drawer, or when the user expands the
+ notification with a gesture.
+</p>
+<p>
+ The following screenshot shows an inbox-style notification:
+</p>
+<img src="{@docRoot}images/ui/notifications/bigpicture_notification_callouts.png"
+ alt=""
+ height="240"
+ id="figure4" />
+<p class="img-caption">
+ <strong>Figure 4.</strong> Big view notification.
+</p>
+<p>
+ Notice that the big view shares most of its visual elements with the normal view. The
+ only difference is callout number 7, the details area. Each big view style sets this area in
+ a different way. The available styles are:
+</p>
<dl>
- <dt>{@link android.app.Notification#FLAG_AUTO_CANCEL} flag</dt>
- <dd>Add this to the <var>flags</var> field to automatically cancel the notification
- after it is selected from the notifications window.</dd>
- <dt>{@link android.app.Notification#FLAG_INSISTENT} flag</dt>
- <dd>Add this to the <var>flags</var> field to repeat the audio until the
- user responds.</dd>
- <dt>{@link android.app.Notification#FLAG_ONGOING_EVENT} flag</dt>
- <dd>Add this to the <var>flags</var> field to group the notification under the "Ongoing"
- title in the notifications window. This indicates that the application is on-going —
- its processes are still running in the background, even when the application is not
- visible (such as with music or a phone call).</dd>
- <dt>{@link android.app.Notification#FLAG_NO_CLEAR} flag</dt>
- <dd>Add this to the <var>flags</var> field to indicate that the notification should
- <em>not</em> be cleared by the "Clear notifications" button. This is particularly useful if
- your notification is on-going.</dd>
- <dt>{@link android.app.Notification#number} field</dt>
- <dd>This value indicates the current number of events represented by the notification.
- The appropriate number is overlaid on top of the status icon.
- If you intend to use this field, then you must start with "1" when the Notification is first
- created. (If you change the value from zero to anything greater during an update, the number
- is not shown.)</dd>
- <dt>{@link android.app.Notification#iconLevel} field</dt>
- <dd>This value indicates the current level of a
- {@link android.graphics.drawable.LevelListDrawable} that is used for the notification icon.
- You can animate the icon in the status bar by changing this value to correlate with the
- drawable's defined in a LevelListDrawable. See the {@link android.graphics.drawable.LevelListDrawable}
- reference for more information.</dd>
+ <dt>
+ Big picture style
+ </dt>
+ <dd>
+ The details area contains a bitmap up to 256 dp tall in its detail section.
+ </dd>
+ <dt>
+ Big text style
+ </dt>
+ <dd>
+ Displays a large text block in the details section.
+ </dd>
+ <dt>
+ Inbox style
+ </dt>
+ <dd>
+ Displays lines of text in the details section.
+ </dd>
</dl>
+<p>
+ All of the big view styles also have the following content options that aren't
+ available in normal view:
+</p>
+<dl>
+ <dt>
+ Big content title
+ </dt>
+ <dd>
+ Allows you to override the normal view's content title with a title that appears only in
+ the expanded view.
+ </dd>
+ <dt>
+ Summary text
+ </dt>
+ <dd>
+ Allows you to add a line of text below the details area.
+ </dd>
+</dl>
+<p>
+ Applying a big view style to a notification is described in the section
+ <a href="#ApplyStyle">Applying a big view style to a notification</a>.
+</p>
+<!-- ------------------------------------------------------------------------------------------ -->
+<!-- ------------------------------------------------------------------------------------------ -->
+<h2 id="CreateNotification">Creating a Notification</h2>
+<p>
+ You specify the UI information and actions for a notification in a
+ {@link android.support.v4.app.NotificationCompat.Builder NotificationCompat.Builder} object.
+ To create the notification itself, you call
+ {@link android.support.v4.app.NotificationCompat.Builder#build
+ NotificationCompat.Builder.build()}, which returns a {@link android.app.Notification} object
+ containing your specifications.
+ To issue the notification, you pass the {@link android.app.Notification} object to the system
+ by calling {@link android.app.NotificationManager#notify NotificationManager.notify()}.
+</p>
+<!-- ------------------------------------------------------------------------------------------ -->
+<h3 id="Required">Required notification contents</h3>
+<p>
+ A {@link android.app.Notification} object <em>must</em> contain the following:
+</p>
+<ul>
+ <li>
+ A small icon, set by
+ {@link android.support.v4.app.NotificationCompat.Builder#setSmallIcon setSmallIcon()}
+ </li>
+ <li>
+ A title, set by
+ {@link android.support.v4.app.NotificationCompat.Builder#setContentTitle setContentTitle()}
+ </li>
+ <li>
+ Detail text, set by
+ {@link android.support.v4.app.NotificationCompat.Builder#setContentText setContentText()}
+ </li>
+</ul>
+<h3 id="Optional">Optional notification contents and settings</h3>
+<p>
+ All other notification settings and contents are optional. To learn more about them,
+ see the reference documentation for {@link android.support.v4.app.NotificationCompat.Builder}.
+</p>
+<!-- ------------------------------------------------------------------------------------------ -->
+<h3 id="Actions">Notification actions</h3>
+<p>
+ Although they're optional, you should add at least one action to your notification.
+ An action allows users to go directly from the notification to an
+ {@link android.app.Activity} in your application, where they can look at one or more events
+ or do further work.
+</p>
+<p>
+ A notification can provide multiple actions. You should always define the action that's
+ triggered when the user touches the notification; usually this action opens an
+ {@link android.app.Activity} in your application. You can also add buttons to the notification
+ that perform additional actions such as snoozing an alarm or responding immediately to a text
+ message.
+</p>
+<p>
+ Inside a {@link android.app.Notification}, the action itself is defined by a
+ {@link android.app.PendingIntent} containing an {@link android.content.Intent} that starts
+ an {@link android.app.Activity} in your application. To associate the
+ {@link android.app.PendingIntent} with a gesture, call the appropriate method of
+ {@link android.support.v4.app.NotificationCompat.Builder}. For example, if you want to start
+ {@link android.app.Activity} when the user touches the notification text in
+ the notification drawer, you add the {@link android.app.PendingIntent} by calling
+ {@link android.support.v4.app.NotificationCompat.Builder#setContentIntent setContentIntent()}.
+</p>
+<p>
+ Starting an {@link android.app.Activity} when the user touches the notification is the most
+ common action scenario. You can also start an {@link android.app.Activity} when the user
+ dismisses an {@link android.app.Activity}, and you can start an {@link android.app.Activity}
+ from an action button. To learn more, read the reference guide for
+ {@link android.support.v4.app.NotificationCompat.Builder}.
+</p>
+<!-- ------------------------------------------------------------------------------------------ -->
+<h3 id="SimpleNotification">Creating a simple notification</h3>
+<p>
+ The following snippet illustrates a simple notification that specifies an activity to open when
+ the user touches the notification. Notice that the code creates a
+ {@link android.support.v4.app.TaskStackBuilder} object and uses it to create the
+ {@link android.app.PendingIntent} for the action. This pattern is explained in more detail
+ in the section <a href="#NotificationResponse">
+ Preserving Navigation when Starting an Activity</a>:
+</p>
+<pre>
+NotificationCompat.Builder mBuilder =
+ new NotificationCompat.Builder(this)
+ .setSmallIcon(R.drawable.notification_icon)
+ .setContentTitle("My notification")
+ .setContentText("Hello World!");
+// Creates an explicit intent for an Activity in your app
+Intent resultIntent = new Intent(this, ResultActivity.class);
-<p>See the {@link android.app.Notification} class reference for more information about additional
-features that you can customize for your application.</p>
+// The stack builder object will contain an artificial back stack for the
+// started Activity.
+// This ensures that navigating backward from the Activity leads out of
+// your application to the Home screen.
+TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
+// Adds the back stack for the Intent (but not the Intent itself)
+stackBuilder.addParentStack(ResultActivity.class);
+// Adds the Intent that starts the Activity to the top of the stack
+stackBuilder.addNextIntent(resultIntent);
+PendingIntent resultPendingIntent =
+ stackBuilder.getPendingIntent(
+ 0,
+ PendingIntent.FLAG_UPDATE_CURRENT
+ );
+mBuilder.setContentIntent(resultPendingIntent);
+NotificationManager mNotificationManager =
+ (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
+// mId allows you to update the notification later on.
+mNotificationManager.notify(mId, mBuilder.build());
+</pre>
+<p>That's it. Your user has now been notified.</p>
+<!-- ------------------------------------------------------------------------------------------ -->
+<h3 id="ApplyStyle">Applying a big view style to a notification</h3>
+<p>
+ To have a notification appear in a big view when it's expanded, first create a
+ {@link android.support.v4.app.NotificationCompat.Builder} object with the normal view options
+ you want. Next, call {@link android.support.v4.app.NotificationCompat.Builder#setStyle
+ Builder.setStyle()} with a big view style object as its argument.
+</p>
+<p>
+ For example, the following code snippet demonstrates how to alter the notification created
+ in the previous snippet to use the Inbox big view style:
+</p>
+<pre>
+NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
+ .setSmallIcon(R.drawable.notification_icon)
+ .setContentTitle("Event tracker")
+ .setContentText("Events received")
+NotificationCompat.InboxStyle inboxStyle =
+ new NotificationCompat.InboxStyle();
+String[] events = new String[6];
+// Sets a title for the Inbox style big view
+inboxStyle.SetBigContentTitle("Event tracker details:");
+...
+// Moves events into the big view
+for (int i=0; i < events.length; i++) {
-
-<h2 id="CustomExpandedView">Creating a Custom Notification Layout</h2>
-
-<div class="figure" style="width:200px;margin-top:0">
-<img src="{@docRoot}images/custom_message.png" alt="" />
-<p class="img-caption"><strong>Figure 3.</strong> Notification with a custom layout.</p>
-</div>
-
-<p>By default, the notification that appears in the notifications window includes a title
-and the message text.
-These are defined by the <var>contentTitle</var> and <var>contentText</var>
-parameters of the {@link android.app.Notification#setLatestEventInfo(Context,CharSequence,CharSequence,PendingIntent)
-setLatestEventInfo()} method. However, you can also define a custom layout for the
-notification using
-{@link android.widget.RemoteViews}. Figure 3 shows an example of a
-custom notification layout. It looks similar to the default notification, but is
-actually created with a custom XML layout.</p>
-
-<p>To define your own layout for the notification,
-instantiate a {@link android.widget.RemoteViews} object that inflates a custom layout file, then
-pass the {@link android.widget.RemoteViews} to the <var>contentView</var> field of your
-Notification.</p>
-
-<p>Creating a custom notification layout is best understood with an example:</p>
-
+ inboxStyle.addLine(events[i]);
+}
+// Moves the big view style object into the notification object.
+mBuilder.setStyle(inBoxStyle);
+...
+// Issue the notification here.
+</pre>
+<!-- ------------------------------------------------------------------------------------------ -->
+<!-- ------------------------------------------------------------------------------------------ -->
+<h2 id="Managing">Managing Notifications</h2>
+<p>
+ When you need to issue a notification multiple times for the same type of event, you
+ should avoid making a completely new notification. Instead, you should consider updating a
+ previous notification, either by changing some of its values or by adding to it, or both.
+</p>
+<p>
+ For example, Gmail notifies the user that new emails have arrived by increasing its count of
+ unread messages and by adding a summary of each email to the notification. This is called
+ "stacking" the notification; it's described in more detail in the
+ <a href="{@docRoot}design/patterns/notifications.html">Notifications</a> Design guide.
+</p>
+<p>
+ The following section describes how to update notifications and also how to remove them.
+</p>
+<h3 id="Updating">Updating notifications</h3>
+<p>
+ To set up a notification so it can be updated, issue it with a notification ID by
+ calling {@link android.app.NotificationManager#notify(int, Notification)
+ NotificationManager.notify(ID, notification)}. To update this notification once you've issued
+ it, update or create a {@link android.support.v4.app.NotificationCompat.Builder} object,
+ build a {@link android.app.Notification} object from it, and issue the
+ {@link android.app.Notification} with the same ID you used previously. If
+ the previous notification is still visible, the system updates it from the contents of
+ the {@link android.app.Notification} object. If the previous notification has been dismissed, a
+ new notification is created instead.
+</p>
+<p>
+ The following snippet demonstrates a notification that is updated to reflect the
+ number of events that have occurred. It stacks the notification, showing a summary:
+</p>
+<pre>
+mNotificationManager =
+ (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
+// Sets an ID for the notification, so it can be updated
+int notifyID = 1;
+mNotifyBuilder = new NotificationCompat.Builder(this)
+ .setContentTitle("New Message")
+ .setContentText("You've received new messages.")
+ .setSmallIcon(R.drawable.ic_notify_status)
+numMessages = 0;
+// Start of a loop that processes data and then notifies the user
+...
+ mNotifyBuilder.setContentText(currentText)
+ .setNumber(++numMessages);
+ // Because the ID remains unchanged, the existing notification is
+ // updated.
+ mNotificationManager.notify(
+ notifyID,
+ mNotifyBuilder.build());
+...
+</pre>
+<p>
+ This produces a notification that looks like this:
+</p>
+<img
+ id="figure5"
+ src="{@docRoot}images/ui/notifications/updated_notification.png"
+ alt=""
+ height="118"/>
+<p class="img-caption">
+ <strong>Figure 5.</strong> Updated notification displayed in the notification drawer.
+</p>
+<!-- ------------------------------------------------------------------------------------------ -->
+<h3 id="Removing">Removing notifications</h3>
+<p>
+ Notifications remain visible until one of the following happens:
+</p>
+<ul>
+ <li>
+ The user dismisses the notification either individually or by using "Clear All" (if
+ the notification can be cleared).
+ </li>
+ <li>
+ The user touches the notification, and you called
+ {@link android.support.v4.app.NotificationCompat.Builder#setAutoCancel setAutoCancel()} when
+ you created the notification.
+ </li>
+ <li>
+ You call {@link android.app.NotificationManager#cancel(int) cancel()} for a specific
+ notification ID. This method also deletes ongoing notifications.
+ </li>
+ <li>
+ You call {@link android.app.NotificationManager#cancelAll() cancelAll()}, which removes
+ all of the notifications you previously issued.
+ </li>
+</ul>
+<!-- ------------------------------------------------------------------------------------------ -->
+<!-- ------------------------------------------------------------------------------------------ -->
+<h2 id="NotificationResponse">Preserving Navigation when Starting an Activity</h2>
+<p>
+ When you start an {@link android.app.Activity} from a notification, you must preserve the
+ user's expected navigation experience. Clicking <i>Back</i> should take the user back through
+ the application's normal work flow to the Home screen, and clicking <i>Recents</i> should show
+ the {@link android.app.Activity} as a separate task. To preserve the navigation experience, you
+ should start the {@link android.app.Activity} in a fresh task. How you set up the
+ {@link android.app.PendingIntent} to give you a fresh task depends on the nature of the
+ {@link android.app.Activity} you're starting. There are two general situations:
+</p>
+<dl>
+ <dt>
+ Regular activity
+ </dt>
+ <dd>
+ You're starting an {@link android.app.Activity} that's part of the application's normal
+ workflow. In this situation, set up the {@link android.app.PendingIntent} to
+ start a fresh task, and provide the {@link android.app.PendingIntent} with a back stack
+ that reproduces the application's normal <i>Back</i> behavior.
+ <p>
+ Notifications from the Gmail app demonstrate this. When you touch a notification for
+ a single email message, you see the message itself. Touching <b>Back</b> takes you
+ backwards through Gmail to the Home screen, just as if you had entered Gmail from the
+ Home screen rather than entering it from a notification.
+ </p>
+ <p>
+ This happens regardless of the application you were in when you touched the
+ notification. For example, if you're in Gmail composing a message, and you click a
+ notification for a single email, you go immediately to that email. Touching <i>Back</i>
+ takes you to the inbox and then the Home screen, rather than taking you to the
+ message you were composing.
+ </p>
+ </dd>
+ <dt>
+ Special activity
+ </dt>
+ <dd>
+ The user only sees this {@link android.app.Activity} if it's started from a notification.
+ In a sense, the {@link android.app.Activity} extends the notification by providing
+ information that would be hard to display in the notification itself. For this situation,
+ set up the {@link android.app.PendingIntent} to start in a fresh task. There's no need to
+ create a back stack, though, because the started {@link android.app.Activity} isn't part of
+ the application's activity flow. Clicking <i>Back</i> will still take the user to the
+ Home screen.
+ </dd>
+</dl>
+<!-- ------------------------------------------------------------------------------------------ -->
+<h3 id="DirectEntry">Setting up a regular activity PendingIntent</h3>
+<p>
+ To set up a {@link android.app.PendingIntent} that starts a direct entry
+ {@link android.app.Activity}, follow these steps:
+</p>
<ol>
- <li>Create the XML layout for the notification.
- For example, the following layout is called <code>custom_notification.xml</code>:
+ <li>
+ Define your application's {@link android.app.Activity} hierarchy in the manifest.
+ <ol style="list-style-type: lower-alpha;">
+ <li>
+ Add support for API versions 15 and earlier. To do this, specify the parent of the
+ {@link android.app.Activity} you're starting by adding a
+<code><a href="{@docRoot}guide/topics/manifest/meta-data-element.html"><meta-data></a></code>
+ element as the child of the
+<code><a href="{@docRoot}guide/topics/manifest/activity-element.html"><activity></a></code>.
+ <p>
+ For this element, set
+<code><a href="{@docRoot}guide/topics/manifest/meta-data-element.html#nm">android:name</a>="android.support.PARENT_ACTIVITY"</code>.
+ Set
+<code><a href="{@docRoot}/guide/topics/manifest/meta-data-element.html#val">android:value</a>="<parent_activity_name>"</code>
+ where <code><parent_activity_name></code> is the value of
+<code><a href="{@docRoot}guide/topics/manifest/meta-data-element.html#nm">android:name</a></code>
+ for the parent
+<code><a href="{@docRoot}guide/topics/manifest/activity-element.html"><activity></a></code>
+ element. See the following XML for an example.
+ </p>
+ </li>
+ <li>
+ Also add support for API versions 16 and later. To do this, add the
+<code><a href="{@docRoot}guide/topics/manifest/activity-element.html#parent">android:parentActivityName</a></code>
+ attribute to the
+<code><a href="{@docRoot}guide/topics/manifest/activity-element.html"><activity></a></code>
+ element of the {@link android.app.Activity} you're starting.
+ </li>
+ </ol>
+ <p>
+ The final XML should look like this:
+ </p>
<pre>
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/layout"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:padding="10dp" >
- <ImageView android:id="@+id/image"
- android:layout_width="wrap_content"
- android:layout_height="fill_parent"
- android:layout_alignParentLeft="true"
- android:layout_marginRight="10dp" />
- <TextView android:id="@+id/title"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_toRightOf="@id/image"
- style="@style/NotificationTitle" />
- <TextView android:id="@+id/text"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_toRightOf="@id/image"
- android:layout_below="@id/title"
- style="@style/NotificationText" />
-</RelativeLayout>
+<activity
+ android:name=".MainActivity"
+ android:label="@string/app_name" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+</activity>
+<activity
+ android:name=".ResultActivity"
+ android:parentActivityName=".MainActivity">
+ <meta-data
+ android:name="android.support.PARENT_ACTIVITY"
+ android:value=".MainActivity"/>
+</activity>
</pre>
-
- <p>Notice that the two {@link android.widget.TextView} elements include the {@code style}
-attribute. It's important that you use style resources for the text in your custom
-notifications, because the background color of the notification can vary across different
-devices and platform versions. Beginning with Android 2.3 (API level 9), the system defines a
-style for the text it uses for the default notification layouts. Thus, you should apply
-that style when running on Android 2.3 or higher to ensure that your text is visible against
-the background.</p>
-
- <p>For example, to use the standard text colors on versions of Android lower than 2.3, you
-should use the following styles for {@code res/values/styles.xml}:</p>
-<pre>
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
- <style name="NotificationText">
- <item name="android:textColor">?android:attr/textColorPrimary</item>
- </style>
- <style name="NotificationTitle">
- <item name="android:textColor">?android:attr/textColorPrimary</item>
- <item name="android:textStyle">bold</item>
- </style>
- <!-- If you want a slightly different color for some text,
- consider using ?android:attr/textColorSecondary -->
-</resources>
-</pre>
- <p>Then, to apply the system's default colors for notifications on Android
-2.3 and higher, use the following styles for {@code res/values-v9/styles.xml}:</p>
-<pre>
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
- <style name="NotificationText" parent="android:TextAppearance.StatusBar.EventContent" />
- <style name="NotificationTitle" parent="android:TextAppearance.StatusBar.EventContent.Title" />
-</resources>
-</pre>
- <p>Now, when running on Android 2.3 (API level 9) or higher, the text in your custom view will
-use the same colors that the system does for default notifications. This is important because later
-versions of Android actually change the background color of the notifications to be dark. Inheriting
-the system's styles ensures that your text will be light in such cases, but also if the background
-is some other unexpected color, your text will also change as appropriate.</p>
- </li>
-
- <li>Now, in the application code, use the RemoveViews
- methods to define the image and text. Then pass the RemoteViews object to the <var>contentView</var>
- field of the Notification, as shown in this example:
-<pre>
-RemoteViews contentView = new RemoteViews(getPackageName(), R.layout.custom_notification_layout);
-contentView.setImageViewResource(R.id.image, R.drawable.notification_image);
-contentView.setTextViewText(R.id.title, "Custom notification");
-contentView.setTextViewText(R.id.text, "This is a custom layout");
-notification.contentView = contentView;
-</pre>
-
- <p>As shown here, pass the application's package name and the layout
- resource ID to the RemoteViews constructor. Then, define the content for the ImageView and TextView,
- using the {@link android.widget.RemoteViews#setImageViewResource(int, int) setImageViewResource()}
- and {@link android.widget.RemoteViews#setTextViewText(int, CharSequence) setTextViewText()}.
- In each case, pass the reference ID of the appropriate View object that you want to set, along with
- the value for that View. Finally, the RemoteViews object is passed to the Notification in the
- <var>contentView</var> field.</p>
- </li>
-
- <li>Because you don't need the
- {@link android.app.Notification#setLatestEventInfo(Context,CharSequence,CharSequence,PendingIntent)
- setLatestEventInfo()} method when using a custom view, you must define the Intent for the Notification
- with the <var>contentIntent</var> field, as in this example:
-<pre>
-Intent notificationIntent = new Intent(this, MyClass.class);
-PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
-notification.contentIntent = contentIntent;
-</pre>
- </li>
-
- <li>The notification can now be sent as usual:
- <pre>mNotificationManager.notify(CUSTOM_VIEW_ID, notification);</pre>
- </li>
+ </li>
+ <li>
+ Create a back stack based on the {@link android.content.Intent} that starts the
+ {@link android.app.Activity}:
+ <ol style="list-style-type: lower-alpha;">
+ <li>
+ Create the {@link android.content.Intent} to start the {@link android.app.Activity}.
+ </li>
+ <li>
+ Create a stack builder by calling {@link android.app.TaskStackBuilder#create
+ TaskStackBuilder.create()}.
+ </li>
+ <li>
+ Add the back stack to the stack builder by calling
+ {@link android.support.v4.app.TaskStackBuilder#addParentStack addParentStack()}.
+ For each {@link android.app.Activity} in the hierarchy you've defined in the
+ manifest, the back stack contains an {@link android.content.Intent} object that
+ starts the {@link android.app.Activity}. This method also adds flags that start the
+ stack in a fresh task.
+ <p class="note">
+ <strong>Note:</strong> Although the argument to
+ {@link android.support.v4.app.TaskStackBuilder#addParentStack addParentStack()}
+ is a reference to the started {@link android.app.Activity}, the method call
+ doesn't add the {@link android.content.Intent} that starts the
+ {@link android.app.Activity}. Instead, that's taken care of in the next step.
+ </p>
+ </li>
+ <li>
+ Add the {@link android.content.Intent} that starts the {@link android.app.Activity}
+ from the notification, by calling
+ {@link android.support.v4.app.TaskStackBuilder#addNextIntent addNextIntent()}.
+ Pass the {@link android.content.Intent} you created in the first step as the
+ argument to
+ {@link android.support.v4.app.TaskStackBuilder#addNextIntent addNextIntent()}.
+ </li>
+ <li>
+ If you need to, add arguments to {@link android.content.Intent} objects on the
+ stack by calling {@link android.support.v4.app.TaskStackBuilder#editIntentAt
+ TaskStackBuilder.editIntentAt()}. This is sometimes necessary to ensure that the
+ target {@link android.app.Activity} displays meaningful data when the user navigates
+ to it using <i>Back</i>.
+ </li>
+ <li>
+ Get a {@link android.app.PendingIntent} for this back stack by calling
+ {@link android.support.v4.app.TaskStackBuilder#getPendingIntent getPendingIntent()}.
+ You can then use this {@link android.app.PendingIntent} as the argument to
+ {@link android.support.v4.app.NotificationCompat.Builder#setContentIntent
+ setContentIntent()}.
+ </li>
+ </ol>
+ </li>
</ol>
+<p>
+ The following code snippet demonstrates the process:
+</p>
+<pre>
+...
+Intent resultIntent = new Intent(this, ResultActivity.class);
+TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
+// Adds the back stack
+stackBuilder.addParentStack(ResultActivity.class);
+// Adds the Intent to the top of the stack
+stackBuilder.addNextIntent(resultIntent);
+// Gets a PendingIntent containing the entire back stack
+PendingIntent resultPendingIntent =
+ stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
+...
+NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
+builder.setContentIntent(resultPendingIntent);
+NotificationManager mNotificationManager =
+ (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
+mNotificationManager.notify(id, builder.build());
+</pre>
+<!-- ------------------------------------------------------------------------------------------ -->
+<h3 id="ExtendedNotification">Setting up a special activity PendingIntent</h3>
+<p>
+ The following section describes how to set up a special activity
+ {@link android.app.PendingIntent}.
+</p>
+<p>
+ A special {@link android.app.Activity} doesn't need a back stack, so you don't have to
+ define its {@link android.app.Activity} hierarchy in the manifest, and you don't have
+ to call
+ {@link android.support.v4.app.TaskStackBuilder#addParentStack addParentStack()} to build a
+ back stack. Instead, use the manifest to set up the {@link android.app.Activity} task options,
+ and create the {@link android.app.PendingIntent} by calling
+ {@link android.app.PendingIntent#getActivity getActivity()}:
+</p>
+<ol>
+ <li>
+ In your manifest, add the following attributes to the
+<code><a href="{@docRoot}guide/topics/manifest/activity-element.html"><activity></a></code>
+ element for the {@link android.app.Activity}
+ <dl>
+ <dt>
+<code><a href="guide/topics/manifest/activity-element.html#nm">android:name</a>="<i>activityclass</i>"</code>
+ </dt>
+ <dd>
+ The activity's fully-qualified class name.
+ </dd>
+ <dt>
+<code><a href="{@docRoot}guide/topics/manifest/activity-element.html#aff">android:taskAffinity</a>=""</code>
+ </dt>
+ <dd>
+ Combined with the
+ {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK FLAG_ACTIVITY_NEW_TASK} flag
+ that you set in code, this ensures that this {@link android.app.Activity} doesn't
+ go into the application's default task. Any existing tasks that have the
+ application's default affinity are not affected.
+ </dd>
+ <dt>
+<code><a href="{@docRoot}guide/topics/manifest/activity-element.html#exclude">android:excludeFromRecents</a>="true"</code>
+ </dt>
+ <dd>
+ Excludes the new task from <i>Recents</i>, so that the user can't accidentally
+ navigate back to it.
+ </dd>
+ </dl>
+ <p>
+ This snippet shows the element:
+ </p>
+<pre>
+<activity
+ android:name=".ResultActivity"
+...
+ android:launchMode="singleTask"
+ android:taskAffinity=""
+ android:excludeFromRecents="true">
+</activity>
+...
+</pre>
+ </li>
+ <li>
+ Build and issue the notification:
+ <ol style="list-style-type: lower-alpha;">
+ <li>
+ Create an {@link android.content.Intent} that starts the
+ {@link android.app.Activity}.
+ </li>
+ <li>
+ Set the {@link android.app.Activity} to start in a new, empty task by calling
+ {@link android.content.Intent#setFlags setFlags()} with the flags
+ {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK FLAG_ACTIVITY_NEW_TASK}
+ and
+ {@link android.content.Intent#FLAG_ACTIVITY_CLEAR_TASK FLAG_ACTIVITY_CLEAR_TASK}.
+ </li>
+ <li>
+ Set any other options you need for the {@link android.content.Intent}.
+ </li>
+ <li>
+ Create a {@link android.app.PendingIntent} from the {@link android.content.Intent}
+ by calling {@link android.app.PendingIntent#getActivity getActivity()}.
+ You can then use this {@link android.app.PendingIntent} as the argument to
+ {@link android.support.v4.app.NotificationCompat.Builder#setContentIntent
+ setContentIntent()}.
+ </li>
+ </ol>
+ <p>
+ The following code snippet demonstrates the process:
+ </p>
+<pre>
+// Instantiate a Builder object.
+NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
+// Creates an Intent for the Activity
+Intent notifyIntent =
+ new Intent(new ComponentName(this, ResultActivity.class));
+// Sets the Activity to start in a new, empty task
+notifyIntent.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK);
+// Creates the PendingIntent
+PendingIntent notifyIntent =
+ PendingIntent.getActivity(
+ this,
+ 0,
+ notifyIntent
+ PendingIntent.FLAG_UPDATE_CURRENT
+);
+// Puts the PendingIntent into the notification builder
+builder.setContentIntent(notifyIntent);
+// Notifications are issued by sending them to the
+// NotificationManager system service.
+NotificationManager mNotificationManager =
+ (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
+// Builds an anonymous Notification object from the builder, and
+// passes it to the NotificationManager
+mNotificationManager.notify(id, builder.build());
+</pre>
+ </li>
+</ol>
+<!-- ------------------------------------------------------------------------------------------ -->
+<!-- ------------------------------------------------------------------------------------------ -->
+<h2 id="Progress">Displaying Progress in a Notification</h2>
+<p>
+ Notifications can include an animated progress indicator that shows users the status
+ of an ongoing operation. If you can estimate how long the operation takes and how much of it
+ is complete at any time, use the "determinate" form of the indicator
+ (a progress bar). If you can't estimate the length of the operation, use the
+ "indeterminate" form of the indicator (an activity indicator).
+</p>
+<p>
+ Progress indicators are displayed with the platform's implementation of the
+ {@link android.widget.ProgressBar} class.
+</p>
+<p>
+ To use a progress indicator, call
+ {@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress()}. The
+ determinate and indeterminate forms are described in the following sections.
+</p>
+<!-- ------------------------------------------------------------------------------------------ -->
+<h3 id="FixedProgress">Displaying a fixed-duration progress indicator</h3>
+<p>
+ To display a determinate progress bar, add the bar to your notification by calling
+ {@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress()
+ setProgress(max, progress, false)} and then issue the notification. As your operation proceeds,
+ increment <code>progress</code>, and update the notification. At the end of the operation,
+ <code>progress</code> should equal <code>max</code>. A common way to call
+ {@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress()}
+ is to set <code>max</code> to 100 and then increment <code>progress</code> as a
+ "percent complete" value for the operation.
+</p>
+<p>
+ You can either leave the progress bar showing when the operation is done, or remove it. In
+ either case, remember to update the notification text to show that the operation is complete.
+ To remove the progress bar, call
+ {@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress()
+ setProgress(0, 0, false)}. For example:
+</p>
+<pre>
+...
+mNotifyManager =
+ (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
+mBuilder = new NotificationCompat.Builder(this);
+mBuilder.setContentTitle("Picture Download")
+ .setContentText("Download in progress")
+ .setSmallIcon(R.drawable.ic_notification);
+// Start a lengthy operation in a background thread
+new Thread(
+ new Runnable() {
+ @Override
+ public void run() {
+ int incr;
+ // Do the "lengthy" operation 20 times
+ for (incr = 0; incr <= 100; incr+=5) {
+ // Sets the progress indicator to a max value, the
+ // current completion percentage, and "determinate"
+ // state
+ mBuilder.setProgress(100, incr, false);
+ // Displays the progress bar for the first time.
+ mNotifyManager.notify(0, mBuilder.build());
+ // Sleeps the thread, simulating an operation
+ // that takes time
+ try {
+ // Sleep for 5 seconds
+ Thread.sleep(5*1000);
+ } catch (InterruptedException e) {
+ Log.d(TAG, "sleep failure");
+ }
+ }
+ // When the loop is finished, updates the notification
+ mBuilder.setContentText("Download complete")
+ // Removes the progress bar
+ .setProgress(0,0,false);
+ mNotifyManager.notify(ID, mBuilder.build());
+ }
+ }
+// Starts the thread by calling the run() method in its Runnable
+).start();
+</pre>
+<p>
+ The resulting notifications are shown in figure 6. On the left side is a snapshot of the
+ notification during the operation; on the right side is a snapshot of it after the operation
+ has finished.
+</p>
+<img
+ id="figure6"
+ src="{@docRoot}images/ui/notifications/progress_bar_summary.png"
+ height="84"
+ alt="" />
+<p class="img-caption">
+<strong>Figure 6.</strong> The progress bar during and after the operation.</p>
+<!-- ------------------------------------------------------------------------------------------ -->
+<h3 id="ActivityIndicator">Displaying a continuing activity indicator</h3>
+<p>
+ To display an indeterminate activity indicator, add it to your notification with
+ {@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress(0, 0, true)}
+ (the first two arguments are ignored), and issue the notification. The result is an indicator
+ that has the same style as a progress bar, except that its animation is ongoing.
+</p>
+<p>
+ Issue the notification at the beginning of the operation. The animation will run until you
+ modify your notification. When the operation is done, call
+ {@link android.support.v4.app.NotificationCompat.Builder#setProgress setProgress()
+ setProgress(0, 0, false)} and then update the notification to remove the activity indicator.
+ Always do this; otherwise, the animation will run even when the operation is complete. Also
+ remember to change the notification text to indicate that the operation is complete.
+</p>
+<p>
+ To see how activity indicators work, refer to the preceding snippet. Locate the following lines:
+</p>
+<pre>
+// Sets the progress indicator to a max value, the current completion
+// percentage, and "determinate" state
+mBuilder.setProgress(100, incr, false);
+// Issues the notification
+mNotifyManager.notify(0, mBuilder.build());
+</pre>
+<p>
+ Replace the lines you've found with the following lines:
+</p>
+<pre>
+ // Sets an activity indicator for an operation of indeterminate length
+mBuilder.setProgress(0, 0, false);
+// Issues the notification
+mNotifyManager.notify(0, mBuilder.build());
+</pre>
+<p>
+ The resulting indicator is shown in figure 7:
+</p>
+<img
+ id="figure7"
+ src="{@docRoot}images/ui/notifications/activity_indicator.png"
+ height="99"
+ alt="" />
+<p class="img-caption"><strong>Figure 7.</strong> An ongoing activity indicator.</p>
-<p>The {@link android.widget.RemoteViews} class also includes methods that you can use to easily add
-a {@link android.widget.Chronometer} or {@link android.widget.ProgressBar}
-in your notification's layout. For more information about creating custom layouts for your
-notification, refer to the {@link android.widget.RemoteViews} class reference.</p>
+<!-- ------------------------------------------------------------------------------------------ -->
+<!-- ------------------------------------------------------------------------------------------ -->
+<!-- ------------------------------------------------------------------------------------------ -->
-<p class="caution"><strong>Caution:</strong>
-When creating a custom notification layout, you must take special care to ensure that your
-custom layout functions properly in different device orientations and resolutions. While this
-advice applies to all View layouts created on Android, it is especially important in this case
-because your layout real estate is very restricted. So don't make your custom layout too
-complex and be sure to test it in various configurations.</p>
-
-
-
-
+<!-- ------------------------------------------------------------------------------------------ -->
+<h2 id="CustomNotification">Custom Notification Layouts</h2>
+<p>
+ The notifications framework allows you to define a custom notification layout, which
+ defines the notification's appearance in a {@link android.widget.RemoteViews} object.
+ Custom layout notifications are similar to normal notifications, but they're based on a
+ {@link android.widget.RemoteViews} defined in a XML layout file.
+</p>
+<p>
+ To define a custom notification layout, start by instantiating a
+ {@link android.widget.RemoteViews} object that inflates an XML layout file. Then,
+ instead of calling methods such as
+ {@link android.support.v4.app.NotificationCompat.Builder#setContentTitle setContentTitle()},
+ call {@link android.support.v4.app.NotificationCompat.Builder#setContent setContent()}. To set
+ content details in the custom notification, use the methods in
+ {@link android.widget.RemoteViews} to set the values of the view's children:
+</p>
+<ol>
+ <li>
+ Create an XML layout for the notification in a separate file. You can use any file name
+ you wish, but you must use the extension <code>.xml</code>
+ </li>
+ <li>
+ In your app, use {@link android.widget.RemoteViews} methods to define your notification's
+ icons and text. Put this {@link android.widget.RemoteViews} object into your
+ {@link android.support.v4.app.NotificationCompat.Builder} by calling
+ {@link android.support.v4.app.NotificationCompat.Builder#setContent setContent()}. Avoid
+ setting a background {@link android.graphics.drawable.Drawable} on your
+ {@link android.widget.RemoteViews} object, because your text color may become unreadable.
+ </li>
+</ol>
+<p>
+ The {@link android.widget.RemoteViews} class also includes methods that you can use to easily
+ add a {@link android.widget.Chronometer} or {@link android.widget.ProgressBar}
+ to your notification's layout. For more information about creating custom layouts for your
+ notification, refer to the {@link android.widget.RemoteViews} reference documentation.
+</p>
+<p class="caution">
+ <strong>Caution:</strong> When you use a custom notification layout, take special care to
+ ensure that your custom layout works with different device orientations and resolutions. While
+ this advice applies to all View layouts, it's especially important for notifications because
+ the space in the notification drawer is very restricted. Don't make your custom layout too
+ complex, and be sure to test it in various configurations.
+</p>
+<!-- ------------------------------------------------------------------------------------------ -->
+<h4>Using style resources for custom notification text</h4>
+<p>
+ Always use style resources for the text of a custom notification. The background color of the
+ notification can vary across different devices and platform versions, and using style resources
+ helps you account for this. Starting in API level 9, the system defined a style for the
+ standard notification layout text. If you use the same style in applications that target API
+ level 9 or higher, you'll ensure that your text is visible against the display background.
+</p>
diff --git a/docs/html/images/ui/notifications/activity_indicator.png b/docs/html/images/ui/notifications/activity_indicator.png
new file mode 100644
index 0000000..e21fae2
--- /dev/null
+++ b/docs/html/images/ui/notifications/activity_indicator.png
Binary files differ
diff --git a/docs/html/images/ui/notifications/bigpicture_notification.png b/docs/html/images/ui/notifications/bigpicture_notification.png
new file mode 100644
index 0000000..ced6380
--- /dev/null
+++ b/docs/html/images/ui/notifications/bigpicture_notification.png
Binary files differ
diff --git a/docs/html/images/ui/notifications/bigpicture_notification_callouts.png b/docs/html/images/ui/notifications/bigpicture_notification_callouts.png
new file mode 100644
index 0000000..e2d313a
--- /dev/null
+++ b/docs/html/images/ui/notifications/bigpicture_notification_callouts.png
Binary files differ
diff --git a/docs/html/images/ui/notifications/bigtext_notification.png b/docs/html/images/ui/notifications/bigtext_notification.png
new file mode 100644
index 0000000..cd6e764
--- /dev/null
+++ b/docs/html/images/ui/notifications/bigtext_notification.png
Binary files differ
diff --git a/docs/html/images/ui/notifications/bigtext_notification_callouts.png b/docs/html/images/ui/notifications/bigtext_notification_callouts.png
new file mode 100644
index 0000000..4cfa403
--- /dev/null
+++ b/docs/html/images/ui/notifications/bigtext_notification_callouts.png
Binary files differ
diff --git a/docs/html/images/ui/notifications/custom_message.png b/docs/html/images/ui/notifications/custom_message.png
new file mode 100755
index 0000000..00b7632
--- /dev/null
+++ b/docs/html/images/ui/notifications/custom_message.png
Binary files differ
diff --git a/docs/html/images/ui/notifications/iconic_notification.png b/docs/html/images/ui/notifications/iconic_notification.png
new file mode 100644
index 0000000..4cabfdb
--- /dev/null
+++ b/docs/html/images/ui/notifications/iconic_notification.png
Binary files differ
diff --git a/docs/html/images/ui/notifications/inbox_notification.png b/docs/html/images/ui/notifications/inbox_notification.png
new file mode 100644
index 0000000..fb182d5
--- /dev/null
+++ b/docs/html/images/ui/notifications/inbox_notification.png
Binary files differ
diff --git a/docs/html/images/ui/notifications/inbox_notification_callouts.png b/docs/html/images/ui/notifications/inbox_notification_callouts.png
new file mode 100644
index 0000000..2ec818e
--- /dev/null
+++ b/docs/html/images/ui/notifications/inbox_notification_callouts.png
Binary files differ
diff --git a/docs/html/images/ui/notifications/normal_notification.png b/docs/html/images/ui/notifications/normal_notification.png
new file mode 100644
index 0000000..3cf0231
--- /dev/null
+++ b/docs/html/images/ui/notifications/normal_notification.png
Binary files differ
diff --git a/docs/html/images/ui/notifications/normal_notification_callouts.png b/docs/html/images/ui/notifications/normal_notification_callouts.png
new file mode 100644
index 0000000..db57daf
--- /dev/null
+++ b/docs/html/images/ui/notifications/normal_notification_callouts.png
Binary files differ
diff --git a/docs/html/images/ui/notifications/notifications_window.png b/docs/html/images/ui/notifications/notifications_window.png
new file mode 100755
index 0000000..0354ee9
--- /dev/null
+++ b/docs/html/images/ui/notifications/notifications_window.png
Binary files differ
diff --git a/docs/html/images/ui/notifications/progress_bar_summary.png b/docs/html/images/ui/notifications/progress_bar_summary.png
new file mode 100644
index 0000000..073e697d
--- /dev/null
+++ b/docs/html/images/ui/notifications/progress_bar_summary.png
Binary files differ
diff --git a/docs/html/images/ui/notifications/progress_indicator_1.png b/docs/html/images/ui/notifications/progress_indicator_1.png
new file mode 100644
index 0000000..f4c2365
--- /dev/null
+++ b/docs/html/images/ui/notifications/progress_indicator_1.png
Binary files differ
diff --git a/docs/html/images/ui/notifications/progress_indicator_2.png b/docs/html/images/ui/notifications/progress_indicator_2.png
new file mode 100644
index 0000000..975c90e
--- /dev/null
+++ b/docs/html/images/ui/notifications/progress_indicator_2.png
Binary files differ
diff --git a/docs/html/images/ui/notifications/status_bar.png b/docs/html/images/ui/notifications/status_bar.png
new file mode 100755
index 0000000..f0240a5
--- /dev/null
+++ b/docs/html/images/ui/notifications/status_bar.png
Binary files differ
diff --git a/docs/html/images/ui/notifications/updated_notification.png b/docs/html/images/ui/notifications/updated_notification.png
new file mode 100644
index 0000000..f69fa4b
--- /dev/null
+++ b/docs/html/images/ui/notifications/updated_notification.png
Binary files differ
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index 4604437..6238edb 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -967,7 +967,7 @@
* @hide
*/
static public int scaleFromDensity(int size, int sdensity, int tdensity) {
- if (sdensity == DENSITY_NONE || sdensity == tdensity) {
+ if (sdensity == DENSITY_NONE || tdensity == DENSITY_NONE || sdensity == tdensity) {
return size;
}
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 9b1a892..1460996 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -153,9 +153,9 @@
<skip />
<string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Usuario <xliff:g id="USER">%s</xliff:g>"</string>
<string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
- <string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Celular <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
+ <string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Móvil <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
<string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Batería <xliff:g id="STATE">%s</xliff:g>"</string>
- <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Modo avión <xliff:g id="STATE">%s</xliff:g>"</string>
+ <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Modo de avión <xliff:g id="STATE">%s</xliff:g>"</string>
<string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth <xliff:g id="STATE">%s</xliff:g>"</string>
<string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Alarma: <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"Datos de 2G-3G inhabilitados"</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 9a7e56df..9f0fbda 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -175,7 +175,7 @@
<string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"La pantalla está bloqueada en modo horizontal."</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"La pantalla está bloqueada en modo vertical."</string>
<string name="jelly_bean_dream_name" msgid="5992026543636816792">"BeanFlinger"</string>
- <string name="start_dreams" msgid="6170089063982549905">"Activar suspensión"</string>
+ <string name="start_dreams" msgid="6170089063982549905">"Suspender"</string>
<string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
<string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Modo avión"</string>
<string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Cargando (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 58c9dec..468375f 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -203,5 +203,5 @@
<string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Độ sáng"</string>
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"TỰ ĐỘNG"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"Thông báo xuất hiện tại đây"</string>
- <string name="status_bar_help_text" msgid="7874607155052076323">"Truy cập vào chúng bất kỳ lúc nào bằng cách trượt xuống."\n"Trượt lại xuống để có các điều khiển hệ thống."</string>
+ <string name="status_bar_help_text" msgid="7874607155052076323">"Truy cập vào chúng bất kỳ lúc nào bằng cách vuốt xuống."\n"Vuốt lại xuống để hiển thị các điều khiển hệ thống."</string>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 29b682d..d0323f0 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -204,6 +204,6 @@
<string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"無線螢幕分享"</string>
<string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"亮度"</string>
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"自動"</string>
- <string name="status_bar_help_title" msgid="1199237744086469217">"通知會顯示在這裡"</string>
+ <string name="status_bar_help_title" msgid="1199237744086469217">"系統會在這裡顯示通知"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"向下滑動即可隨時存取通知。"\n"再次向下滑動即可使用系統控制項。"</string>
</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/Somnambulator.java b/packages/SystemUI/src/com/android/systemui/Somnambulator.java
index 9356ff2..0dd6d92 100644
--- a/packages/SystemUI/src/com/android/systemui/Somnambulator.java
+++ b/packages/SystemUI/src/com/android/systemui/Somnambulator.java
@@ -1,4 +1,4 @@
-/*);
+/*
* Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -18,38 +18,23 @@
import android.app.Activity;
import android.content.Intent;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.os.UserHandle;
-import android.provider.Settings;
-import android.service.dreams.DreamService;
-import android.service.dreams.IDreamManager;
-import android.util.Slog;
+import android.service.dreams.Sandman;
+/**
+ * A simple activity that launches a dream.
+ * <p>
+ * Note: This Activity is special. If this class is moved to another package or
+ * renamed, be sure to update the component name in {@link Sandman}.
+ * </p>
+ */
public class Somnambulator extends Activity {
- public static final String TAG = "Somnambulator";
-
- public static final int DEFAULT_SCREENSAVER_ENABLED = 1;
- public static final int DEFAULT_SCREENSAVER_ACTIVATED_ON_DOCK = 1;
-
public Somnambulator() {
}
- private boolean isScreenSaverEnabled() {
- return Settings.Secure.getIntForUser(getContentResolver(),
- Settings.Secure.SCREENSAVER_ENABLED, DEFAULT_SCREENSAVER_ENABLED,
- UserHandle.USER_CURRENT) != 0;
- }
-
- private boolean isScreenSaverActivatedOnDock() {
- return Settings.Secure.getIntForUser(getContentResolver(),
- Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK,
- DEFAULT_SCREENSAVER_ACTIVATED_ON_DOCK, UserHandle.USER_CURRENT) != 0;
- }
-
@Override
public void onStart() {
super.onStart();
+
final Intent launchIntent = getIntent();
final String action = launchIntent.getAction();
if (Intent.ACTION_CREATE_SHORTCUT.equals(action)) {
@@ -64,23 +49,12 @@
setResult(RESULT_OK, resultIntent);
} else {
boolean docked = launchIntent.hasCategory(Intent.CATEGORY_DESK_DOCK);
-
- if (docked && !(isScreenSaverEnabled() && isScreenSaverActivatedOnDock())) {
- Slog.i(TAG, "Dreams currently disabled for docks.");
+ if (docked) {
+ Sandman.startDreamWhenDockedIfAppropriate(this);
} else {
- IDreamManager somnambulist = IDreamManager.Stub.asInterface(
- ServiceManager.checkService(DreamService.DREAM_SERVICE));
- if (somnambulist != null) {
- try {
- Slog.v(TAG, "Dreaming on " + (docked ? "dock insertion" : "user request"));
- somnambulist.dream();
- } catch (RemoteException e) {
- // fine, stay asleep then
- }
- }
+ Sandman.startDreamByUserRequest(this);
}
}
finish();
}
-
}
diff --git a/services/java/com/android/server/UiModeManagerService.java b/services/java/com/android/server/UiModeManagerService.java
index 2d4eb79..0e456f1 100644
--- a/services/java/com/android/server/UiModeManagerService.java
+++ b/services/java/com/android/server/UiModeManagerService.java
@@ -37,11 +37,9 @@
import android.os.PowerManager;
import android.os.RemoteException;
import android.os.ServiceManager;
-import android.os.SystemClock;
import android.os.UserHandle;
import android.provider.Settings;
-import android.service.dreams.DreamService;
-import android.service.dreams.IDreamManager;
+import android.service.dreams.Sandman;
import android.util.Slog;
import java.io.FileDescriptor;
@@ -59,9 +57,6 @@
private static final boolean ENABLE_LAUNCH_CAR_DOCK_APP = true;
private static final boolean ENABLE_LAUNCH_DESK_DOCK_APP = true;
- private static final int DEFAULT_SCREENSAVER_ENABLED = 1;
- private static final int DEFAULT_SCREENSAVER_ACTIVATED_ON_DOCK = 1;
-
private final Context mContext;
private final TwilightService mTwilightService;
private final Handler mHandler = new Handler();
@@ -496,18 +491,20 @@
// activity manager take care of both the start and config
// change.
Intent homeIntent = buildHomeIntent(category);
- try {
- int result = ActivityManagerNative.getDefault().startActivityWithConfig(
- null, homeIntent, null, null, null, 0, 0,
- mConfiguration, null, UserHandle.USER_CURRENT);
- if (result >= ActivityManager.START_SUCCESS) {
- dockAppStarted = true;
- } else if (result != ActivityManager.START_INTENT_NOT_RESOLVED) {
- Slog.e(TAG, "Could not start dock app: " + homeIntent
- + ", startActivityWithConfig result " + result);
+ if (Sandman.shouldStartDockApp(mContext, homeIntent)) {
+ try {
+ int result = ActivityManagerNative.getDefault().startActivityWithConfig(
+ null, homeIntent, null, null, null, 0, 0,
+ mConfiguration, null, UserHandle.USER_CURRENT);
+ if (result >= ActivityManager.START_SUCCESS) {
+ dockAppStarted = true;
+ } else if (result != ActivityManager.START_INTENT_NOT_RESOLVED) {
+ Slog.e(TAG, "Could not start dock app: " + homeIntent
+ + ", startActivityWithConfig result " + result);
+ }
+ } catch (RemoteException ex) {
+ Slog.e(TAG, "Could not start dock app: " + homeIntent, ex);
}
- } catch (RemoteException ex) {
- Slog.e(TAG, "Could not start dock app: " + homeIntent, ex);
}
}
@@ -515,41 +512,11 @@
sendConfigurationLocked();
// If we did not start a dock app, then start dreaming if supported.
- if (category != null && !dockAppStarted
- && isScreenSaverEnabledLocked() && isScreenSaverActivatedOnDockLocked()) {
- Slog.i(TAG, "Activating dream while docked.");
- try {
- IDreamManager dreamManagerService = IDreamManager.Stub.asInterface(
- ServiceManager.getService(DreamService.DREAM_SERVICE));
- if (dreamManagerService != null && !dreamManagerService.isDreaming()) {
- // Wake up.
- // The power manager will wake up the system when it starts receiving power
- // but there is a race between that happening and the UI mode manager
- // starting a dream. We want the system to already be awake
- // by the time this happens. Otherwise the dream may not start.
- mPowerManager.wakeUp(SystemClock.uptimeMillis());
-
- // Dream.
- dreamManagerService.dream();
- }
- } catch (RemoteException ex) {
- Slog.e(TAG, "Could not start dream when docked.", ex);
- }
+ if (category != null && !dockAppStarted) {
+ Sandman.startDreamWhenDockedIfAppropriate(mContext);
}
}
- private boolean isScreenSaverEnabledLocked() {
- return Settings.Secure.getIntForUser(mContext.getContentResolver(),
- Settings.Secure.SCREENSAVER_ENABLED, DEFAULT_SCREENSAVER_ENABLED,
- UserHandle.USER_CURRENT) != 0;
- }
-
- private boolean isScreenSaverActivatedOnDockLocked() {
- return Settings.Secure.getIntForUser(mContext.getContentResolver(),
- Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK,
- DEFAULT_SCREENSAVER_ACTIVATED_ON_DOCK, UserHandle.USER_CURRENT) != 0;
- }
-
private void adjustStatusBarCarModeLocked() {
if (mStatusBarManager == null) {
mStatusBarManager = (StatusBarManager)
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index b8d7286..f59e30d 100644
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -1835,7 +1835,8 @@
PackageSetting ps = mSettings.mPackages.get(packageName);
if (ps == null) return null;
// Note: isEnabledLP() does not apply here - always return info
- return PackageParser.generateApplicationInfo(p, flags, ps.readUserState(userId));
+ return PackageParser.generateApplicationInfo(
+ p, flags, ps.readUserState(userId), userId);
}
if ("android".equals(packageName)||"system".equals(packageName)) {
return mAndroidApplication;
diff --git a/tests/RenderScriptTests/ImageProcessing2/res/drawable-nodpi/img1600x1067.jpg b/tests/RenderScriptTests/ImageProcessing2/res/drawable-nodpi/img1600x1067.jpg
new file mode 100644
index 0000000..05d3ee2
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/res/drawable-nodpi/img1600x1067.jpg
Binary files differ
diff --git a/tests/RenderScriptTests/ImageProcessing2/res/drawable-nodpi/img1600x1067b.jpg b/tests/RenderScriptTests/ImageProcessing2/res/drawable-nodpi/img1600x1067b.jpg
new file mode 100644
index 0000000..aed0781
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/res/drawable-nodpi/img1600x1067b.jpg
Binary files differ
diff --git a/tests/RenderScriptTests/ImageProcessing2/res/layout/main.xml b/tests/RenderScriptTests/ImageProcessing2/res/layout/main.xml
index bd56d62..f0a2b92 100644
--- a/tests/RenderScriptTests/ImageProcessing2/res/layout/main.xml
+++ b/tests/RenderScriptTests/ImageProcessing2/res/layout/main.xml
@@ -54,6 +54,10 @@
android:id="@+id/filterselection"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
+ <Spinner
+ android:id="@+id/spinner1"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"/>
<TextView
android:id="@+id/slider1Text"
android:layout_width="match_parent"
@@ -124,6 +128,11 @@
android:layout_marginRight="10sp"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/benchmark_all"
+ android:onClick="benchmark_all"/>
</LinearLayout>
</ScrollView>
</LinearLayout>
diff --git a/tests/RenderScriptTests/ImageProcessing2/res/values/strings.xml b/tests/RenderScriptTests/ImageProcessing2/res/values/strings.xml
index cc5cc4d..a7dd165 100644
--- a/tests/RenderScriptTests/ImageProcessing2/res/values/strings.xml
+++ b/tests/RenderScriptTests/ImageProcessing2/res/values/strings.xml
@@ -29,5 +29,6 @@
<string name="gamma">Gamma</string>
<string name="saturation">Saturation</string>
<string name="benchmark">Benchmark</string>
+ <string name="benchmark_all">Benchmark All</string>
</resources>
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Blend.java b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Blend.java
new file mode 100644
index 0000000..ac02101
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Blend.java
@@ -0,0 +1,168 @@
+/*
+ * 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 java.lang.Short;
+
+import android.support.v8.renderscript.*;
+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;
+ 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/ImageProcessing2/src/com/android/rs/image/Blur25.java b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Blur25.java
index be87716..b518b02 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Blur25.java
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Blur25.java
@@ -24,37 +24,38 @@
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 ScriptC_vertical_blur mScriptVBlur;
- private ScriptC_horizontal_blur mScriptHBlur;
- private int mRadius = MAX_RADIUS;
+ private float mRadius = MAX_RADIUS;
private float mSaturation = 1.0f;
private Allocation mScratchPixelsAllocation1;
private Allocation mScratchPixelsAllocation2;
+ public Blur25(boolean useIntrinsic) {
+ mUseIntrinsic = useIntrinsic;
+ }
+
public boolean onBar1Setup(SeekBar b, TextView t) {
t.setText("Radius");
b.setProgress(100);
return true;
}
- public boolean onBar2Setup(SeekBar b, TextView t) {
- b.setProgress(50);
- t.setText("Saturation");
- return true;
- }
public void onBar1Changed(int progress) {
- float fRadius = progress / 100.0f;
- fRadius *= (float)(MAX_RADIUS);
- mRadius = (int)fRadius;
- mScript.set_radius(mRadius);
- }
- public void onBar2Changed(int progress) {
- mSaturation = (float)progress / 50.0f;
- mScriptVBlur.invoke_setSaturation(mSaturation);
+ mRadius = ((float)progress) / 100.0f * MAX_RADIUS;
+ if (mRadius <= 0.10f) {
+ mRadius = 0.10f;
+ }
+ if (mUseIntrinsic) {
+ mIntrinsic.setRadius(mRadius);
+ } else {
+ mScript.invoke_setRadius((int)mRadius);
+ }
}
@@ -62,40 +63,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 {
- mScriptVBlur = new ScriptC_vertical_blur(mRS, res, R.raw.vertical_blur);
- mScriptHBlur = new ScriptC_horizontal_blur(mRS, res, R.raw.horizontal_blur);
+ 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 = new ScriptC_threshold(mRS, res, R.raw.threshold);
- mScript.set_width(width);
- mScript.set_height(height);
- mScript.set_radius(mRadius);
+ mScript = new ScriptC_threshold(mRS, res, R.raw.threshold);
+ mScript.set_width(width);
+ mScript.set_height(height);
+ mScript.invoke_setRadius(MAX_RADIUS);
- mScriptVBlur.invoke_setSaturation(mSaturation);
-
- mScript.bind_InPixel(mInPixelsAllocation);
- mScript.bind_OutPixel(mOutPixelsAllocation);
- mScript.bind_ScratchPixel1(mScratchPixelsAllocation1);
- mScript.bind_ScratchPixel2(mScratchPixelsAllocation2);
-
- mScript.set_vBlurScript(mScriptVBlur);
- mScript.set_hBlurScript(mScriptHBlur);
+ mScript.set_InPixel(mInPixelsAllocation);
+ mScript.set_ScratchPixel1(mScratchPixelsAllocation1);
+ mScript.set_ScratchPixel2(mScratchPixelsAllocation2);
+ }
}
public void runTest() {
- mScript.invoke_filter();
+ if (mUseIntrinsic) {
+ mIntrinsic.forEach(mOutPixelsAllocation);
+ } else {
+ mScript.forEach_copyIn(mInPixelsAllocation, mScratchPixelsAllocation1);
+ mScript.forEach_horz(mScratchPixelsAllocation2);
+ mScript.forEach_vert(mOutPixelsAllocation);
+ }
}
public void setupBenchmark() {
- mScript.set_radius(MAX_RADIUS);
+ if (mUseIntrinsic) {
+ mIntrinsic.setRadius(MAX_RADIUS);
+ } else {
+ mScript.invoke_setRadius(MAX_RADIUS);
+ }
}
public void exitBenchmark() {
- mScript.set_radius(mRadius);
+ if (mUseIntrinsic) {
+ mIntrinsic.setRadius(mRadius);
+ } else {
+ mScript.invoke_setRadius((int)mRadius);
+ }
}
}
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/ColorMatrix.java b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/ColorMatrix.java
new file mode 100644
index 0000000..3b0f86a
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/ColorMatrix.java
@@ -0,0 +1,62 @@
+/*
+ * 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 ColorMatrix extends TestBase {
+ private ScriptC_colormatrix mScript;
+ private ScriptIntrinsicColorMatrix mIntrinsic;
+ private boolean mUseIntrinsic;
+ private boolean mUseGrey;
+
+ public ColorMatrix(boolean useIntrinsic, boolean useGrey) {
+ mUseIntrinsic = useIntrinsic;
+ mUseGrey = useGrey;
+ }
+
+ public void createTest(android.content.res.Resources res) {
+ Matrix4f m = new Matrix4f();
+ m.set(1, 0, 0.2f);
+ m.set(1, 1, 0.9f);
+ m.set(1, 2, 0.2f);
+
+ 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() {
+ if (mUseIntrinsic) {
+ mIntrinsic.forEach(mInPixelsAllocation, mOutPixelsAllocation);
+ } else {
+ mScript.forEach_root(mInPixelsAllocation, mOutPixelsAllocation);
+ }
+ }
+
+}
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Convolve3x3.java b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Convolve3x3.java
new file mode 100644
index 0000000..7635e13
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Convolve3x3.java
@@ -0,0 +1,66 @@
+/*
+ * 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 Convolve3x3 extends TestBase {
+ private ScriptC_convolve3x3 mScript;
+ private ScriptIntrinsicConvolve3x3 mIntrinsic;
+
+ private int mWidth;
+ private int mHeight;
+ private boolean mUseIntrinsic;
+
+ public Convolve3x3(boolean useIntrinsic) {
+ mUseIntrinsic = useIntrinsic;
+ }
+
+ public void createTest(android.content.res.Resources res) {
+ mWidth = mInPixelsAllocation.getType().getX();
+ mHeight = mInPixelsAllocation.getType().getY();
+
+ 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;
+
+ 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() {
+ if (mUseIntrinsic) {
+ mIntrinsic.forEach(mOutPixelsAllocation);
+ } else {
+ mScript.forEach_root(mOutPixelsAllocation);
+ }
+ }
+
+}
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Convolve5x5.java b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Convolve5x5.java
new file mode 100644
index 0000000..d2da3c4
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Convolve5x5.java
@@ -0,0 +1,80 @@
+/*
+ * 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 Convolve5x5 extends TestBase {
+ private ScriptC_convolve5x5 mScript;
+ private ScriptIntrinsicConvolve5x5 mIntrinsic;
+
+ private int mWidth;
+ private int mHeight;
+ private boolean mUseIntrinsic;
+
+ public Convolve5x5(boolean useIntrinsic) {
+ mUseIntrinsic = useIntrinsic;
+ }
+
+ public void createTest(android.content.res.Resources res) {
+ mWidth = mInPixelsAllocation.getType().getX();
+ mHeight = mInPixelsAllocation.getType().getY();
+
+ float f[] = new float[25];
+ //f[0] = 0.012f; f[1] = 0.025f; f[2] = 0.031f; f[3] = 0.025f; f[4] = 0.012f;
+ //f[5] = 0.025f; f[6] = 0.057f; f[7] = 0.075f; f[8] = 0.057f; f[9] = 0.025f;
+ //f[10]= 0.031f; f[11]= 0.075f; f[12]= 0.095f; f[13]= 0.075f; f[14]= 0.031f;
+ //f[15]= 0.025f; f[16]= 0.057f; f[17]= 0.075f; f[18]= 0.057f; f[19]= 0.025f;
+ //f[20]= 0.012f; f[21]= 0.025f; f[22]= 0.031f; f[23]= 0.025f; f[24]= 0.012f;
+
+ //f[0] = 1.f; f[1] = 2.f; f[2] = 0.f; f[3] = -2.f; f[4] = -1.f;
+ //f[5] = 4.f; f[6] = 8.f; f[7] = 0.f; f[8] = -8.f; f[9] = -4.f;
+ //f[10]= 6.f; f[11]=12.f; f[12]= 0.f; f[13]=-12.f; f[14]= -6.f;
+ //f[15]= 4.f; f[16]= 8.f; f[17]= 0.f; f[18]= -8.f; f[19]= -4.f;
+ //f[20]= 1.f; f[21]= 2.f; f[22]= 0.f; f[23]= -2.f; f[24]= -1.f;
+
+ f[0] = -1.f; f[1] = -3.f; f[2] = -4.f; f[3] = -3.f; f[4] = -1.f;
+ f[5] = -3.f; f[6] = 0.f; f[7] = 6.f; f[8] = 0.f; f[9] = -3.f;
+ f[10]= -4.f; f[11]= 6.f; f[12]= 20.f; f[13]= 6.f; f[14]= -4.f;
+ 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;
+
+ 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() {
+ if (mUseIntrinsic) {
+ mIntrinsic.forEach(mOutPixelsAllocation);
+ } else {
+ mScript.forEach_root(mOutPixelsAllocation);
+ }
+ }
+
+}
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Copy.java b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Copy.java
new file mode 100644
index 0000000..ef71907
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Copy.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.*;
+import android.util.Log;
+
+public class Copy extends TestBase {
+ private ScriptC_copy mScript;
+
+ public void createTest(android.content.res.Resources res) {
+ mScript = new ScriptC_copy(mRS, res, R.raw.copy);
+ }
+
+ public void runTest() {
+ mScript.forEach_root(mInPixelsAllocation, mOutPixelsAllocation);
+ }
+
+}
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/CrossProcess.java b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/CrossProcess.java
new file mode 100644
index 0000000..96787d7
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/CrossProcess.java
@@ -0,0 +1,60 @@
+/*
+ * 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 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/ImageProcessing2/src/com/android/rs/image/Fisheye.java b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Fisheye.java
index 995cf9d..97beb88 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Fisheye.java
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Fisheye.java
@@ -23,12 +23,16 @@
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 relaxed) {
+ public Fisheye(boolean approx, boolean relaxed) {
+ this.approx = approx;
this.relaxed = relaxed;
}
@@ -65,7 +69,18 @@
}
private void do_init() {
- if (relaxed)
+ 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,
@@ -78,7 +93,19 @@
}
public void createTest(android.content.res.Resources res) {
- if (relaxed) {
+ 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);
@@ -93,7 +120,12 @@
}
public void runTest() {
- if (relaxed)
+ 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/ImageProcessing2/src/com/android/rs/image/Grain.java b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Grain.java
index e00edd7..dfd3c32 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Grain.java
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Grain.java
@@ -40,19 +40,40 @@
mScript.set_gNoiseStrength(s);
}
+ private int findHighBit(int v) {
+ int bit = 0;
+ while (v > 1) {
+ bit++;
+ v >>= 1;
+ }
+ return bit;
+ }
+
+
public void createTest(android.content.res.Resources res) {
int width = mInPixelsAllocation.getType().getX();
int height = mInPixelsAllocation.getType().getY();
+ int noiseW = findHighBit(width);
+ int noiseH = findHighBit(height);
+ if (noiseW > 9) {
+ noiseW = 9;
+ }
+ if (noiseH > 9) {
+ noiseH = 9;
+ }
+ noiseW = 1 << noiseW;
+ noiseH = 1 << noiseH;
+
Type.Builder tb = new Type.Builder(mRS, Element.U8(mRS));
- tb.setX(width);
- tb.setY(height);
+ tb.setX(noiseW);
+ tb.setY(noiseH);
mNoise = Allocation.createTyped(mRS, tb.create());
mNoise2 = Allocation.createTyped(mRS, tb.create());
mScript = new ScriptC_grain(mRS, res, R.raw.grain);
- mScript.set_gWidth(width);
- mScript.set_gHeight(height);
+ mScript.set_gWMask(noiseW - 1);
+ mScript.set_gHMask(noiseH - 1);
mScript.set_gNoiseStrength(0.5f);
mScript.set_gBlendSource(mNoise);
mScript.set_gNoise(mNoise2);
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/GroupTest.java b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/GroupTest.java
index b9fbb59..a7ceebee 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/GroupTest.java
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/GroupTest.java
@@ -22,8 +22,8 @@
import android.util.Log;
public class GroupTest extends TestBase {
- private ScriptC_convolve3x3 mConvolve;
- private ScriptC_colormatrix mMatrix;
+ private ScriptIntrinsicConvolve3x3 mConvolve;
+ private ScriptIntrinsicColorMatrix mMatrix;
private Allocation mScratchPixelsAllocation1;
private ScriptGroup mGroup;
@@ -41,20 +41,20 @@
mWidth = mInPixelsAllocation.getType().getX();
mHeight = mInPixelsAllocation.getType().getY();
- mConvolve = new ScriptC_convolve3x3(mRS, res, R.raw.convolve3x3);
- mMatrix = new ScriptC_colormatrix(mRS, res, R.raw.colormatrix);
+ 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.set_gCoeffs(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.invoke_setMatrix(m);
+ mMatrix.setColorMatrix(m);
Type.Builder tb = new Type.Builder(mRS, Element.U8_4(mRS));
tb.setX(mWidth);
@@ -63,24 +63,23 @@
if (mUseNative) {
ScriptGroup.Builder b = new ScriptGroup.Builder(mRS);
- b.addConnection(connect, mConvolve, mMatrix, null);
+ 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.set_gIn(mInPixelsAllocation);
- mConvolve.set_gWidth(mWidth);
- mConvolve.set_gHeight(mHeight);
+ mConvolve.setInput(mInPixelsAllocation);
if (mUseNative) {
- mGroup.setOutput(mMatrix, mOutPixelsAllocation);
+ mGroup.setOutput(mMatrix.getKernelID(), mOutPixelsAllocation);
mGroup.execute();
} else {
- mConvolve.forEach_root(mScratchPixelsAllocation1);
- mMatrix.forEach_root(mScratchPixelsAllocation1, mOutPixelsAllocation);
+ mConvolve.forEach(mScratchPixelsAllocation1);
+ mMatrix.forEach(mScratchPixelsAllocation1, mOutPixelsAllocation);
}
}
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 9b36da14..227518f 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/ImageProcessingActivity2.java
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/ImageProcessingActivity2.java
@@ -34,13 +34,27 @@
import android.util.Log;
import java.lang.Math;
+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;
+import java.io.IOException;
+
public class ImageProcessingActivity2 extends Activity
implements SeekBar.OnSeekBarChangeListener {
private final String TAG = "Img";
+ private final String RESULT_FILE = "image_processing_result.csv";
+
Bitmap mBitmapIn;
+ Bitmap mBitmapIn2;
Bitmap mBitmapOut;
String mTestNames[];
+ private Spinner mSpinner;
private SeekBar mBar1;
private SeekBar mBar2;
private SeekBar mBar3;
@@ -64,6 +78,10 @@
private TestBase mTest;
+ public void updateDisplay() {
+ mTest.updateBitmap(mBitmapOut);
+ mDisplayView.invalidate();
+ }
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (fromUser) {
@@ -81,8 +99,7 @@
}
mTest.runTest();
- mTest.updateBitmap(mBitmapOut);
- mDisplayView.invalidate();
+ updateDisplay();
}
}
@@ -93,6 +110,9 @@
}
void setupBars() {
+ mSpinner.setVisibility(View.VISIBLE);
+ mTest.onSpinner1Setup(mSpinner);
+
mBar1.setVisibility(View.VISIBLE);
mText1.setVisibility(View.VISIBLE);
mTest.onBar1Setup(mBar1, mText1);
@@ -116,6 +136,9 @@
void changeTest(int testID) {
+ if (mTest != null) {
+ mTest.destroy();
+ }
switch(testID) {
case 0:
mTest = new LevelsV4(false, false);
@@ -130,58 +153,122 @@
mTest = new LevelsV4(true, true);
break;
case 4:
- mTest = new Blur25();
+ mTest = new Blur25(false);
break;
case 5:
- mTest = new Greyscale();
+ mTest = new Blur25(true);
break;
case 6:
- mTest = new Grain();
+ mTest = new Greyscale();
break;
case 7:
- mTest = new Fisheye(false);
+ mTest = new Grain();
break;
case 8:
- mTest = new Fisheye(true);
+ mTest = new Fisheye(false, false);
break;
case 9:
- mTest = new Vignette(false);
+ mTest = new Fisheye(false, true);
break;
case 10:
- mTest = new Vignette(true);
+ mTest = new Fisheye(true, false);
break;
case 11:
- mTest = new GroupTest(false);
+ mTest = new Fisheye(true, true);
break;
case 12:
+ mTest = new Vignette(false, false);
+ break;
+ case 13:
+ mTest = new Vignette(false, true);
+ break;
+ case 14:
+ mTest = new Vignette(true, false);
+ break;
+ case 15:
+ mTest = new Vignette(true, true);
+ break;
+ case 16:
+ mTest = new GroupTest(false);
+ break;
+ case 17:
mTest = new GroupTest(true);
break;
+ case 18:
+ mTest = new Convolve3x3(false);
+ break;
+ case 19:
+ mTest = new Convolve3x3(true);
+ break;
+ case 20:
+ mTest = new ColorMatrix(false, false);
+ break;
+ case 21:
+ mTest = new ColorMatrix(true, false);
+ break;
+ case 22:
+ mTest = new ColorMatrix(true, true);
+ break;
+ case 23:
+ mTest = new Copy();
+ break;
+ case 24:
+ mTest = new CrossProcess();
+ break;
+ case 25:
+ mTest = new Convolve5x5(false);
+ break;
+ case 26:
+ mTest = new Convolve5x5(true);
+ break;
+ case 27:
+ mTest = new Mandelbrot();
+ break;
+ case 28:
+ mTest = new Blend();
+ break;
}
- mTest.createBaseTest(this, mBitmapIn);
+ mTest.createBaseTest(this, mBitmapIn, mBitmapIn2);
setupBars();
mTest.runTest();
- mTest.updateBitmap(mBitmapOut);
- mDisplayView.invalidate();
+ updateDisplay();
mBenchmarkResult.setText("Result: not run");
}
void setupTests() {
- mTestNames = new String[13];
+ 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] = "Greyscale";
- mTestNames[6] = "Grain";
- mTestNames[7] = "Fisheye Full";
- mTestNames[8] = "Fisheye Relaxed";
- mTestNames[9] = "Vignette Full";
- mTestNames[10] = "Vignette Relaxed";
- mTestNames[11] = "Group Test (emulated)";
- mTestNames[12] = "Group Test (native)";
+ 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));
}
@@ -202,14 +289,17 @@
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
- mBitmapIn = loadBitmap(R.drawable.city);
- mBitmapOut = loadBitmap(R.drawable.city);
+ mBitmapIn = loadBitmap(R.drawable.img1600x1067);
+ mBitmapIn2 = loadBitmap(R.drawable.img1600x1067b);
+ mBitmapOut = loadBitmap(R.drawable.img1600x1067);
mSurfaceView = (SurfaceView) findViewById(R.id.surface);
mDisplayView = (ImageView) findViewById(R.id.display);
mDisplayView.setImageBitmap(mBitmapOut);
+ mSpinner = (Spinner) findViewById(R.id.spinner1);
+
mBar1 = (SeekBar) findViewById(R.id.slider1);
mBar2 = (SeekBar) findViewById(R.id.slider2);
mBar3 = (SeekBar) findViewById(R.id.slider3);
@@ -255,37 +345,69 @@
// button hook
public void benchmark(View v) {
- long t = getBenchmark();
+ float t = getBenchmark();
//long javaTime = javaFilter();
//mBenchmarkResult.setText("RS: " + t + " ms Java: " + javaTime + " ms");
mBenchmarkResult.setText("Result: " + t + " ms");
+ Log.v(TAG, "getBenchmark: Renderscript frame time core ms " + t);
+ }
+
+ public void benchmark_all(View v) {
+ // write result into a file
+ File externalStorage = Environment.getExternalStorageDirectory();
+ if (!externalStorage.canWrite()) {
+ Log.v(TAG, "sdcard is not writable");
+ return;
+ }
+ File resultFile = new File(externalStorage, RESULT_FILE);
+ //resultFile.setWritable(true, false);
+ 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);
+ float t = getBenchmark();
+ String s = new String("" + mTestNames[i] + ", " + t);
+ rsWriter.write(s + "\n");
+ Log.v(TAG, "Test " + s + "ms\n");
+ }
+ rsWriter.close();
+ } catch (IOException e) {
+ Log.v(TAG, "Unable to write result file " + e.getMessage());
+ }
+ changeTest(0);
}
// For benchmark test
- public long getBenchmark() {
+ public float getBenchmark() {
mDoingBenchmark = true;
mTest.setupBenchmark();
long result = 0;
- Log.v(TAG, "Warming");
- long t = java.lang.System.currentTimeMillis() + 2000;
+ //Log.v(TAG, "Warming");
+ long t = java.lang.System.currentTimeMillis() + 250;
do {
mTest.runTest();
mTest.finish();
} while (t > java.lang.System.currentTimeMillis());
- Log.v(TAG, "Benchmarking");
+ //Log.v(TAG, "Benchmarking");
+ int ct = 0;
t = java.lang.System.currentTimeMillis();
- mTest.runTest();
- mTest.finish();
+ do {
+ mTest.runTest();
+ mTest.finish();
+ ct++;
+ } while ((t+1000) > java.lang.System.currentTimeMillis());
t = java.lang.System.currentTimeMillis() - t;
+ float ft = (float)t;
+ ft /= ct;
- Log.v(TAG, "getBenchmark: Renderscript frame time core ms " + t);
mTest.exitBenchmark();
mDoingBenchmark = false;
- return t;
+ return ft;
}
}
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Mandelbrot.java b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Mandelbrot.java
new file mode 100644
index 0000000..556d797
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Mandelbrot.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.support.v8.renderscript.*;
+import android.util.Log;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+public class Mandelbrot extends TestBase {
+ private ScriptC_mandelbrot mScript;
+
+ public boolean onBar1Setup(SeekBar b, TextView t) {
+ t.setText("Iterations");
+ b.setProgress(0);
+ return true;
+ }
+
+ public void onBar1Changed(int progress) {
+ int iters = progress * 3 + 50;
+ mScript.set_gMaxIteration(iters);
+ }
+
+ public boolean onBar2Setup(SeekBar b, TextView t) {
+ t.setText("Lower Bound: X");
+ b.setProgress(0);
+ return true;
+ }
+
+ public void onBar2Changed(int progress) {
+ float scaleFactor = mScript.get_scaleFactor();
+ // allow viewport to be moved by 2x scale factor
+ float lowerBoundX = -2.f + ((progress / scaleFactor) / 50.f);
+ mScript.set_lowerBoundX(lowerBoundX);
+ }
+
+ public boolean onBar3Setup(SeekBar b, TextView t) {
+ t.setText("Lower Bound: Y");
+ b.setProgress(0);
+ return true;
+ }
+
+ public void onBar3Changed(int progress) {
+ float scaleFactor = mScript.get_scaleFactor();
+ // allow viewport to be moved by 2x scale factor
+ float lowerBoundY = -2.f + ((progress / scaleFactor) / 50.f);
+ mScript.set_lowerBoundY(lowerBoundY);
+ }
+
+ public boolean onBar4Setup(SeekBar b, TextView t) {
+ t.setText("Scale Factor");
+ b.setProgress(0);
+ return true;
+ }
+
+ public void onBar4Changed(int progress) {
+ float scaleFactor = 4.f - (3.96f * (progress / 100.f));
+ mScript.set_scaleFactor(scaleFactor);
+ }
+
+ public void createTest(android.content.res.Resources res) {
+ int width = mOutPixelsAllocation.getType().getX();
+ int height = mOutPixelsAllocation.getType().getY();
+
+ mScript = new ScriptC_mandelbrot(mRS, res, R.raw.mandelbrot);
+ mScript.set_gDimX(width);
+ mScript.set_gDimY(height);
+ mScript.set_gMaxIteration(50);
+ }
+
+ public void runTest() {
+ mScript.forEach_root(mOutPixelsAllocation);
+ mRS.finish();
+ }
+
+}
+
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 35170af..9df2eff 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/TestBase.java
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/TestBase.java
@@ -31,14 +31,18 @@
import android.view.View;
import android.util.Log;
import java.lang.Math;
+import android.widget.Spinner;
public class TestBase {
protected final String TAG = "Img";
protected RenderScript mRS;
protected Allocation mInPixelsAllocation;
+ protected Allocation mInPixelsAllocation2;
protected Allocation mOutPixelsAllocation;
+ protected ImageProcessingActivity2 act;
+
// Override to use UI elements
public void onBar1Changed(int progress) {
}
@@ -79,11 +83,20 @@
return false;
}
- public final void createBaseTest(ImageProcessingActivity2 act, Bitmap b) {
+ public boolean onSpinner1Setup(Spinner s) {
+ s.setVisibility(View.INVISIBLE);
+ return false;
+ }
+
+ public final void createBaseTest(ImageProcessingActivity2 ipact, Bitmap b, Bitmap b2) {
+ act = ipact;
mRS = RenderScript.create(act);
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);
@@ -103,6 +116,10 @@
mRS.finish();
}
+ public void destroy() {
+ mRS.destroy();
+ }
+
public void updateBitmap(Bitmap b) {
mOutPixelsAllocation.copyTo(b);
}
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 fc69eba..8618d5a 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Vignette.java
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/Vignette.java
@@ -23,6 +23,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;
@@ -30,7 +33,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;
}
@@ -87,7 +91,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,
@@ -100,21 +115,36 @@
}
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 {
+ else
mScript_full = new ScriptC_vignette_full(mRS, res,
R.raw.vignette_full);
- }
do_init();
}
public void runTest() {
- if (relaxed)
- mScript_relaxed.forEach_root(mInPixelsAllocation, mOutPixelsAllocation);
+ 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
- mScript_full.forEach_root(mInPixelsAllocation, mOutPixelsAllocation);
+ mScript_full.forEach_root(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
new file mode 100644
index 0000000..4d90725
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/blend.rs
@@ -0,0 +1,24 @@
+// 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.
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image2)
+
+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/ImageProcessing2/src/com/android/rs/image/convolve5x5.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/convolve5x5.rs
new file mode 100644
index 0000000..b110b88
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/convolve5x5.rs
@@ -0,0 +1,74 @@
+/*
+ * 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
+
+int32_t gWidth;
+int32_t gHeight;
+rs_allocation gIn;
+
+float gCoeffs[25];
+
+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(rsGetElementAt_uchar4(gIn, x0, y0)) * gCoeffs[0]
+ + convert_float4(rsGetElementAt_uchar4(gIn, x1, y0)) * gCoeffs[1]
+ + convert_float4(rsGetElementAt_uchar4(gIn, x2, y0)) * gCoeffs[2]
+ + convert_float4(rsGetElementAt_uchar4(gIn, x3, y0)) * gCoeffs[3]
+ + convert_float4(rsGetElementAt_uchar4(gIn, x4, y0)) * gCoeffs[4];
+
+ float4 p1 = convert_float4(rsGetElementAt_uchar4(gIn, x0, y1)) * gCoeffs[5]
+ + convert_float4(rsGetElementAt_uchar4(gIn, x1, y1)) * gCoeffs[6]
+ + convert_float4(rsGetElementAt_uchar4(gIn, x2, y1)) * gCoeffs[7]
+ + convert_float4(rsGetElementAt_uchar4(gIn, x3, y1)) * gCoeffs[8]
+ + convert_float4(rsGetElementAt_uchar4(gIn, x4, y1)) * gCoeffs[9];
+
+ float4 p2 = convert_float4(rsGetElementAt_uchar4(gIn, x0, y2)) * gCoeffs[10]
+ + convert_float4(rsGetElementAt_uchar4(gIn, x1, y2)) * gCoeffs[11]
+ + convert_float4(rsGetElementAt_uchar4(gIn, x2, y2)) * gCoeffs[12]
+ + convert_float4(rsGetElementAt_uchar4(gIn, x3, y2)) * gCoeffs[13]
+ + convert_float4(rsGetElementAt_uchar4(gIn, x4, y2)) * gCoeffs[14];
+
+ float4 p3 = convert_float4(rsGetElementAt_uchar4(gIn, x0, y3)) * gCoeffs[15]
+ + convert_float4(rsGetElementAt_uchar4(gIn, x1, y3)) * gCoeffs[16]
+ + convert_float4(rsGetElementAt_uchar4(gIn, x2, y3)) * gCoeffs[17]
+ + convert_float4(rsGetElementAt_uchar4(gIn, x3, y3)) * gCoeffs[18]
+ + convert_float4(rsGetElementAt_uchar4(gIn, x4, y3)) * gCoeffs[19];
+
+ float4 p4 = convert_float4(rsGetElementAt_uchar4(gIn, x0, y4)) * gCoeffs[20]
+ + convert_float4(rsGetElementAt_uchar4(gIn, x1, y4)) * gCoeffs[21]
+ + convert_float4(rsGetElementAt_uchar4(gIn, x2, y4)) * gCoeffs[22]
+ + convert_float4(rsGetElementAt_uchar4(gIn, x3, y4)) * gCoeffs[23]
+ + convert_float4(rsGetElementAt_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/copy.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/copy.rs
new file mode 100644
index 0000000..31e4241
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/copy.rs
@@ -0,0 +1,24 @@
+/*
+ * 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/ImageProcessing2/src/com/android/rs/image/fisheye.rsh b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye.rsh
index 4dcfc1d..3809912 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye.rsh
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye.rsh
@@ -17,46 +17,41 @@
rs_allocation in_alloc;
rs_sampler sampler;
-static float2 center, dimensions;
-static float2 scale;
-static float alpha;
-static float radius2;
-static float factor;
+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 focus_x, float focus_y, float k) {
- center.x = focus_x;
- center.y = focus_y;
- dimensions.x = (float)dim_x;
- dimensions.y = (float)dim_y;
-
+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.0 + 0.75;
- float bound2 = 0.25;
- if (dim_x > dim_y) {
- scale.x = 1.0;
- scale.y = dimensions.y / dimensions.x;
- bound2 *= (scale.y*scale.y + 1);
- } else {
- scale.x = dimensions.x / dimensions.y;
- scale.y = 1.0;
- bound2 *= (scale.x*scale.x + 1);
- }
+
+ 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.25 * (axis_scale.x*axis_scale.x + axis_scale.y*axis_scale.y);
const float bound = sqrt(bound2);
const float radius = 1.15 * bound;
radius2 = radius*radius;
- const float max_radian = 0.5f * M_PI - atan(alpha / bound * sqrt(radius2 - bound2));
+ 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) {
// Convert x and y to floating point coordinates with center as origin
- float2 coord;
- coord.x = (float)x / dimensions.x;
- coord.y = (float)y / dimensions.y;
- coord -= center;
- const float dist = length(scale * coord);
- const float radian = M_PI_2 - atan((alpha * sqrt(radius2 - dist * dist)) / dist);
- const float scalar = radian * factor / dist;
- const float2 new_coord = coord * scalar + center;
+ 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);
*out = 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
new file mode 100644
index 0000000..08b4126
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/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.0 + 0.75;
+
+ 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.25 * (axis_scale.x*axis_scale.x + axis_scale.y*axis_scale.y);
+ const float bound = sqrt(bound2);
+ const float radius = 1.15 * 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) {
+ // 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);
+ *out = 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
new file mode 100644
index 0000000..cce42f9
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_approx_full.rs
@@ -0,0 +1,21 @@
+/*
+ * 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)
+
+#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.rs
new file mode 100644
index 0000000..64d27ed
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/fisheye_approx_relaxed.rs
@@ -0,0 +1,22 @@
+/*
+ * 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
+
+#include "fisheye_approx.rsh"
+
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/grain.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/grain.rs
index 75f4021..44320a5 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/grain.rs
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/grain.rs
@@ -38,25 +38,25 @@
* 1 2 1
*/
-int32_t gWidth;
-int32_t gHeight;
+int32_t gWMask;
+int32_t gHMask;
rs_allocation gBlendSource;
void blend9(uchar *out, uint32_t x, uint32_t y) {
- uint32_t x1 = min(x+1, (uint32_t)gWidth);
- uint32_t x2 = max(x-1, (uint32_t)0);
- uint32_t y1 = min(y+1, (uint32_t)gHeight);
- uint32_t y2 = max(y-1, (uint32_t)0);
+ 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 * ((uchar *)rsGetElementAt(gBlendSource, x1, y1))[0];
- uint p01 = 114 * ((uchar *)rsGetElementAt(gBlendSource, x, y1))[0];
- uint p02 = 56 * ((uchar *)rsGetElementAt(gBlendSource, x2, y1))[0];
- uint p10 = 114 * ((uchar *)rsGetElementAt(gBlendSource, x1, y))[0];
- uint p11 = 230 * ((uchar *)rsGetElementAt(gBlendSource, x, y))[0];
- uint p12 = 114 * ((uchar *)rsGetElementAt(gBlendSource, x2, y))[0];
- uint p20 = 56 * ((uchar *)rsGetElementAt(gBlendSource, x1, y2))[0];
- uint p21 = 114 * ((uchar *)rsGetElementAt(gBlendSource, x, y2))[0];
- uint p22 = 56 * ((uchar *)rsGetElementAt(gBlendSource, x2, y2))[0];
+ uint p00 = 56 * rsGetElementAt_uchar(gBlendSource, x1, y1);
+ uint p01 = 114 * rsGetElementAt_uchar(gBlendSource, x, y1);
+ uint p02 = 56 * rsGetElementAt_uchar(gBlendSource, x2, y1);
+ uint p10 = 114 * rsGetElementAt_uchar(gBlendSource, x1, y);
+ uint p11 = 230 * rsGetElementAt_uchar(gBlendSource, x, y);
+ uint p12 = 114 * rsGetElementAt_uchar(gBlendSource, x2, y);
+ uint p20 = 56 * rsGetElementAt_uchar(gBlendSource, x1, y2);
+ uint p21 = 114 * rsGetElementAt_uchar(gBlendSource, x, y2);
+ uint p22 = 56 * rsGetElementAt_uchar(gBlendSource, x2, y2);
p00 += p01;
p02 += p10;
@@ -69,7 +69,8 @@
p20 += p22;
p20 += p02;
- *out = (uchar)(p20 >> 10);
+ p20 = min(p20 >> 10, (uint)255);
+ *out = (uchar)p20;
}
float gNoiseStrength;
@@ -77,7 +78,7 @@
rs_allocation gNoise;
void root(const uchar4 *in, uchar4 *out, uint32_t x, uint32_t y) {
float4 ip = convert_float4(*in);
- float pnoise = (float) ((uchar *)rsGetElementAt(gNoise, x, y))[0];
+ float pnoise = (float) rsGetElementAt_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;
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/horizontal_blur.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/horizontal_blur.rs
deleted file mode 100644
index ee83496..0000000
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/horizontal_blur.rs
+++ /dev/null
@@ -1,28 +0,0 @@
-#pragma version(1)
-#pragma rs_fp_relaxed
-
-#include "ip.rsh"
-
-void root(float4 *out, const void *usrData, uint32_t x, uint32_t y) {
- const FilterStruct *fs = (const FilterStruct *)usrData;
- float3 blurredPixel = 0;
- const float *gPtr = fs->gaussian;
- if ((x > fs->radius) && (x < (fs->width - fs->radius))) {
- for (int r = -fs->radius; r <= fs->radius; r ++) {
- const float4 *i = (const float4 *)rsGetElementAt(fs->ain, x + r, y);
- blurredPixel += i->xyz * gPtr[0];
- gPtr++;
- }
- } else {
- for (int r = -fs->radius; r <= fs->radius; r ++) {
- // Stepping left and right away from the pixel
- int validX = rsClamp((int)x + r, (int)0, (int)(fs->width - 1));
- const float4 *i = (const float4 *)rsGetElementAt(fs->ain, validX, y);
- blurredPixel += i->xyz * gPtr[0];
- gPtr++;
- }
- }
-
- out->xyz = blurredPixel;
-}
-
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/ip.rsh b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/ip.rsh
deleted file mode 100644
index 0cdf9e1..0000000
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/ip.rsh
+++ /dev/null
@@ -1,15 +0,0 @@
-#pragma rs java_package_name(com.android.rs.image2)
-
-#define MAX_RADIUS 25
-
-typedef struct FilterStruct_s {
- rs_allocation ain;
-
- float *gaussian; //[MAX_RADIUS * 2 + 1];
- int height;
- int width;
- int radius;
-
-} FilterStruct;
-
-
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/mandelbrot.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/mandelbrot.rs
new file mode 100644
index 0000000..55e5304
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/mandelbrot.rs
@@ -0,0 +1,56 @@
+// 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.
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image2)
+
+uint32_t gMaxIteration = 500;
+uint32_t gDimX = 1024;
+uint32_t gDimY = 1024;
+
+float lowerBoundX = -2.f;
+float lowerBoundY = -2.f;
+float scaleFactor = 4.f;
+
+void root(uchar4 *v_out, uint32_t x, uint32_t y) {
+ float2 p;
+ p.x = lowerBoundX + ((float)x / gDimX) * scaleFactor;
+ p.y = lowerBoundY + ((float)y / gDimY) * scaleFactor;
+
+ float2 t = 0;
+ float2 t2 = t * t;
+ int iter = 0;
+ while((t2.x + t2.y < 4.f) && (iter < gMaxIteration)) {
+ float xtemp = t2.x - t2.y + p.x;
+ t.y = 2 * t.x * t.y + p.y;
+ t.x = xtemp;
+ iter++;
+ t2 = t * t;
+ }
+
+ if(iter >= gMaxIteration) {
+ // write a non-transparent black pixel
+ *v_out = (uchar4){0, 0, 0, 0xff};
+ } else {
+ float mi3 = gMaxIteration / 3.;
+ if (iter <= (gMaxIteration / 3))
+ *v_out = (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};
+ else
+ *v_out = (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/threshold.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/threshold.rs
index 77cd5be..9ef4898 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/threshold.rs
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/threshold.rs
@@ -1,26 +1,23 @@
#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image2)
+#pragma rs_fp_relaxed
-#include "ip.rsh"
int height;
int width;
-int radius;
+static int radius;
-uchar4 * InPixel;
-uchar4 * OutPixel;
-float4 * ScratchPixel1;
-float4 * ScratchPixel2;
+rs_allocation InPixel;
+rs_allocation ScratchPixel1;
+rs_allocation ScratchPixel2;
-rs_script vBlurScript;
-rs_script hBlurScript;
-
-const int CMD_FINISHED = 1;
+const int MAX_RADIUS = 25;
// Store our coefficients here
static float gaussian[MAX_RADIUS * 2 + 1];
-
-static void computeGaussianWeights() {
+void setRadius(int rad) {
+ radius = rad;
// Compute gaussian weights for the blur
// e is the euler's number
float e = 2.718281828459045f;
@@ -45,8 +42,7 @@
float normalizeFactor = 0.0f;
float floatR = 0.0f;
- int r;
- for (r = -radius; r <= radius; r ++) {
+ for (int r = -radius; r <= radius; r ++) {
floatR = (float)r;
gaussian[r + radius] = coeff1 * pow(e, floatR * floatR * coeff2);
normalizeFactor += gaussian[r + radius];
@@ -54,40 +50,57 @@
//Now we need to normalize the weights because all our coefficients need to add up to one
normalizeFactor = 1.0f / normalizeFactor;
- for (r = -radius; r <= radius; r ++) {
+ for (int r = -radius; r <= radius; r ++) {
floatR = (float)r;
gaussian[r + radius] *= normalizeFactor;
}
}
-
-static void copyInput() {
- rs_allocation ain;
- ain = rsGetAllocation(InPixel);
- uint32_t dimx = rsAllocationGetDimX(ain);
- uint32_t dimy = rsAllocationGetDimY(ain);
- for (uint32_t y = 0; y < dimy; y++) {
- for (uint32_t x = 0; x < dimx; x++) {
- ScratchPixel1[x + y * dimx] = convert_float4(InPixel[x + y * dimx]);
- }
- }
+void copyIn(const uchar4 *in, float4 *out) {
+ *out = convert_float4(*in);
}
-void filter() {
- copyInput();
- computeGaussianWeights();
+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++;
+ }
+ }
- FilterStruct fs;
- fs.gaussian = gaussian;
- fs.width = width;
- fs.height = height;
- fs.radius = radius;
+ out->xyz = convert_uchar3(clamp(blurredPixel, 0.f, 255.f));
+ out->w = 0xff;
+}
- fs.ain = rsGetAllocation(ScratchPixel1);
- rsForEach(hBlurScript, fs.ain, rsGetAllocation(ScratchPixel2), &fs, sizeof(fs));
+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++;
+ }
+ }
- fs.ain = rsGetAllocation(ScratchPixel2);
- rsForEach(vBlurScript, fs.ain, rsGetAllocation(OutPixel), &fs, sizeof(fs));
- //rsSendToClientBlocking(CMD_FINISHED);
+ out->xyz = blurredPixel;
}
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vertical_blur.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vertical_blur.rs
deleted file mode 100644
index 60fd71b..0000000
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vertical_blur.rs
+++ /dev/null
@@ -1,59 +0,0 @@
-#pragma version(1)
-#pragma rs_fp_relaxed
-
-#include "ip.rsh"
-
-static float saturation;
-static rs_matrix3x3 colorMat;
-
-void setSaturation(float sat) {
- saturation = sat;
-
- // Saturation
- // Linear weights
- //float rWeight = 0.3086f;
- //float gWeight = 0.6094f;
- //float bWeight = 0.0820f;
-
- // Gamma 2.2 weights (we haven't converted our image to linear space yet for perf reasons)
- float rWeight = 0.299f;
- float gWeight = 0.587f;
- float bWeight = 0.114f;
-
- float oneMinusS = 1.0f - saturation;
- rsMatrixSet(&colorMat, 0, 0, oneMinusS * rWeight + saturation);
- rsMatrixSet(&colorMat, 0, 1, oneMinusS * rWeight);
- rsMatrixSet(&colorMat, 0, 2, oneMinusS * rWeight);
- rsMatrixSet(&colorMat, 1, 0, oneMinusS * gWeight);
- rsMatrixSet(&colorMat, 1, 1, oneMinusS * gWeight + saturation);
- rsMatrixSet(&colorMat, 1, 2, oneMinusS * gWeight);
- rsMatrixSet(&colorMat, 2, 0, oneMinusS * bWeight);
- rsMatrixSet(&colorMat, 2, 1, oneMinusS * bWeight);
- rsMatrixSet(&colorMat, 2, 2, oneMinusS * bWeight + saturation);
-}
-
-void root(uchar4 *out, const void *usrData, uint32_t x, uint32_t y) {
- const FilterStruct *fs = (const FilterStruct *)usrData;
- float3 blurredPixel = 0;
- const float *gPtr = fs->gaussian;
- if ((y > fs->radius) && (y < (fs->height - fs->radius))) {
- for (int r = -fs->radius; r <= fs->radius; r ++) {
- const float4 *i = (const float4 *)rsGetElementAt(fs->ain, x, y + r);
- blurredPixel += i->xyz * gPtr[0];
- gPtr++;
- }
- } else {
- for (int r = -fs->radius; r <= fs->radius; r ++) {
- int validH = rsClamp((int)y + r, (int)0, (int)(fs->height - 1));
- const float4 *i = (const float4 *)rsGetElementAt(fs->ain, x, validH);
- blurredPixel += i->xyz * gPtr[0];
- gPtr++;
- }
- }
-
- float3 temp = rsMatrixMultiply(&colorMat, blurredPixel);
- temp = clamp(temp, 0.f, 255.f);
- out->xyz = convert_uchar3(temp);
- out->w = 0xff;
-}
-
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
new file mode 100644
index 0000000..7f7bdcf
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette_approx.rsh
@@ -0,0 +1,60 @@
+/*
+ * 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.5 * 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;
+ 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) {
+ // 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;
+ // TODO: add half_exp once implemented
+ 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;
+ *out = 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
new file mode 100644
index 0000000..3612509
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette_approx_full.rs
@@ -0,0 +1,21 @@
+/*
+ * 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)
+
+#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.rs
new file mode 100644
index 0000000..b714e9b
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/vignette_approx_relaxed.rs
@@ -0,0 +1,22 @@
+/*
+ * 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
+
+#include "vignette_approx.rsh"
+