Merge "Import translations. DO NOT MERGE" 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/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 37d84b3..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
@@ -710,18 +725,7 @@
"javascript:(function() { %s.onResult(%d, %s); })();";
// Time in milliseconds to wait for a result before failing.
- // Based on recorded times, we have found that in a complex real-world
- // web app (such as the desktop version of Gmail), there can be spikes
- // of ~2600ms in the worst case. These are temporary spikes and are not
- // repeatable; GMail eventually settles down to around ~60ms. The
- // longest duration that is consistently repeatable is ~300ms when
- // loading extremely large plain text documents in WebView.
- // If this timeout hits, the navigation is considered to have "failed",
- // meaning there is no content. Since the longer spikes are one-off
- // events triggered by the page loading and itself running a large
- // amount of JS, subsequent runs would succeed, so the worst impact
- // is that the first run will look like it had not loaded yet.
- private static final long RESULT_TIMEOUT = 1500;
+ private static final long RESULT_TIMEOUT = 5000;
private final AtomicInteger mResultIdCounter = new AtomicInteger();
private final Object mResultLock = new Object();
@@ -787,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 */
}
}
@@ -816,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/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/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/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"
+