summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmds/installd/commands.c23
-rw-r--r--cmds/installd/installd.h5
-rw-r--r--cmds/installd/tests/installd_utils_test.cpp56
-rw-r--r--cmds/installd/utils.c18
-rwxr-xr-xcore/java/android/server/BluetoothService.java34
-rw-r--r--core/java/android/text/TextLine.java24
-rw-r--r--core/java/android/text/method/Touch.java40
-rw-r--r--core/java/android/widget/TextView.java89
-rw-r--r--docs/html/guide/practices/ui_guidelines/widget_design.jd12
-rw-r--r--docs/html/guide/topics/appwidgets/index.jd4
-rw-r--r--libs/rs/rsScriptC.cpp20
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java10
-rw-r--r--services/java/com/android/server/DeviceStorageMonitorService.java1
13 files changed, 251 insertions, 85 deletions
diff --git a/cmds/installd/commands.c b/cmds/installd/commands.c
index 26b911356699..4ede33f73daf 100644
--- a/cmds/installd/commands.c
+++ b/cmds/installd/commands.c
@@ -184,6 +184,7 @@ int free_cache(int64_t free_size)
DIR *d;
struct dirent *de;
int64_t avail;
+ char datadir[PKG_PATH_MAX];
avail = disk_free();
if (avail < 0) return -1;
@@ -191,9 +192,14 @@ int free_cache(int64_t free_size)
LOGI("free_cache(%" PRId64 ") avail %" PRId64 "\n", free_size, avail);
if (avail >= free_size) return 0;
- d = opendir(android_data_dir.path);
+ if (create_persona_path(datadir, 0)) {
+ LOGE("couldn't get directory for persona 0");
+ return -1;
+ }
+
+ d = opendir(datadir);
if (d == NULL) {
- LOGE("cannot open %s: %s\n", android_data_dir.path, strerror(errno));
+ LOGE("cannot open %s: %s\n", datadir, strerror(errno));
return -1;
}
dfd = dirfd(d);
@@ -578,19 +584,6 @@ fail:
return -1;
}
-int create_move_path(char path[PKG_PATH_MAX],
- const char* pkgname,
- const char* leaf,
- uid_t persona)
-{
- if ((android_data_dir.len + strlen(pkgname) + strlen(leaf) + 1) >= PKG_PATH_MAX) {
- return -1;
- }
-
- sprintf(path, "%s%s%s/%s", android_data_dir.path, PRIMARY_USER_PREFIX, pkgname, leaf);
- return 0;
-}
-
void mkinnerdirs(char* path, int basepos, mode_t mode, int uid, int gid,
struct stat* statbuf)
{
diff --git a/cmds/installd/installd.h b/cmds/installd/installd.h
index c5872b8efa09..173cabfb77a7 100644
--- a/cmds/installd/installd.h
+++ b/cmds/installd/installd.h
@@ -105,6 +105,11 @@ int create_pkg_path(char path[PKG_PATH_MAX],
int create_persona_path(char path[PKG_PATH_MAX],
uid_t persona);
+int create_move_path(char path[PKG_PATH_MAX],
+ const char* pkgname,
+ const char* leaf,
+ uid_t persona);
+
int is_valid_package_name(const char* pkgname);
int create_cache_path(char path[PKG_PATH_MAX], const char *src);
diff --git a/cmds/installd/tests/installd_utils_test.cpp b/cmds/installd/tests/installd_utils_test.cpp
index 1128fceca0af..7cb9b37fe038 100644
--- a/cmds/installd/tests/installd_utils_test.cpp
+++ b/cmds/installd/tests/installd_utils_test.cpp
@@ -34,6 +34,16 @@ extern "C" {
#define TEST_SYSTEM_DIR1 "/system/app/"
#define TEST_SYSTEM_DIR2 "/vendor/app/"
+#define REALLY_LONG_APP_NAME "com.example." \
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa." \
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa." \
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+
+#define REALLY_LONG_LEAF_NAME "shared_prefs_shared_prefs_shared_prefs_shared_prefs_shared_prefs_" \
+ "shared_prefs_shared_prefs_shared_prefs_shared_prefs_shared_prefs_shared_prefs_" \
+ "shared_prefs_shared_prefs_shared_prefs_shared_prefs_shared_prefs_shared_prefs_" \
+ "shared_prefs_shared_prefs_shared_prefs_shared_prefs_shared_prefs_shared_prefs_"
+
namespace android {
class UtilsTest : public testing::Test {
@@ -210,7 +220,7 @@ TEST_F(UtilsTest, CheckSystemApp_BadPathEscapeFail) {
TEST_F(UtilsTest, GetPathFromString_NullPathFail) {
dir_rec_t test1;
- EXPECT_EQ(-1, get_path_from_string(&test1, NULL))
+ EXPECT_EQ(-1, get_path_from_string(&test1, (const char *) NULL))
<< "Should not allow NULL as a path.";
}
@@ -327,6 +337,50 @@ TEST_F(UtilsTest, CreatePkgPathInDir_ProtectedDir) {
<< "Package path should be in /data/app-private/";
}
+TEST_F(UtilsTest, CreatePersonaPath_Primary) {
+ char path[PKG_PATH_MAX];
+
+ EXPECT_EQ(0, create_persona_path(path, 0))
+ << "Should successfully build primary user path.";
+
+ EXPECT_STREQ("/data/data/", path)
+ << "Primary user should have correct path";
+}
+
+TEST_F(UtilsTest, CreatePersonaPath_Secondary) {
+ char path[PKG_PATH_MAX];
+
+ EXPECT_EQ(0, create_persona_path(path, 1))
+ << "Should successfully build primary user path.";
+
+ EXPECT_STREQ("/data/user/1/", path)
+ << "Primary user should have correct path";
+}
+
+TEST_F(UtilsTest, CreateMovePath_Primary) {
+ char path[PKG_PATH_MAX];
+
+ EXPECT_EQ(0, create_move_path(path, "com.android.test", "shared_prefs", 0))
+ << "Should be able to create move path for primary user";
+
+ EXPECT_STREQ("/data/data/com.android.test/shared_prefs", path)
+ << "Primary user package directory should be created correctly";
+}
+
+TEST_F(UtilsTest, CreateMovePath_Fail_AppTooLong) {
+ char path[PKG_PATH_MAX];
+
+ EXPECT_EQ(-1, create_move_path(path, REALLY_LONG_APP_NAME, "shared_prefs", 0))
+ << "Should fail to create move path for primary user";
+}
+
+TEST_F(UtilsTest, CreateMovePath_Fail_LeafTooLong) {
+ char path[PKG_PATH_MAX];
+
+ EXPECT_EQ(-1, create_move_path(path, "com.android.test", REALLY_LONG_LEAF_NAME, 0))
+ << "Should fail to create move path for primary user";
+}
+
TEST_F(UtilsTest, CopyAndAppend_Normal) {
//int copy_and_append(dir_rec_t* dst, dir_rec_t* src, char* suffix)
dir_rec_t dst;
diff --git a/cmds/installd/utils.c b/cmds/installd/utils.c
index 3099b8341f6e..a53a93ce1073 100644
--- a/cmds/installd/utils.c
+++ b/cmds/installd/utils.c
@@ -109,7 +109,7 @@ int create_persona_path(char path[PKG_PATH_MAX],
uid_len = 0;
} else {
persona_prefix = SECONDARY_USER_PREFIX;
- uid_len = snprintf(NULL, 0, "%d", persona);
+ uid_len = snprintf(NULL, 0, "%d/", persona);
}
char *dst = path;
@@ -126,7 +126,7 @@ int create_persona_path(char path[PKG_PATH_MAX],
LOGE("Error building user path");
return -1;
}
- int ret = snprintf(dst, dst_size, "%d", persona);
+ int ret = snprintf(dst, dst_size, "%d/", persona);
if (ret < 0 || (size_t) ret != uid_len) {
LOGE("Error appending persona id to path");
return -1;
@@ -135,6 +135,20 @@ int create_persona_path(char path[PKG_PATH_MAX],
return 0;
}
+int create_move_path(char path[PKG_PATH_MAX],
+ const char* pkgname,
+ const char* leaf,
+ uid_t persona)
+{
+ if ((android_data_dir.len + strlen(PRIMARY_USER_PREFIX) + strlen(pkgname) + strlen(leaf) + 1)
+ >= PKG_PATH_MAX) {
+ return -1;
+ }
+
+ sprintf(path, "%s%s%s/%s", android_data_dir.path, PRIMARY_USER_PREFIX, pkgname, leaf);
+ return 0;
+}
+
/**
* Checks whether the package name is valid. Returns -1 on error and
* 0 on success.
diff --git a/core/java/android/server/BluetoothService.java b/core/java/android/server/BluetoothService.java
index a7d8cace28e5..94fbbc8d33e2 100755
--- a/core/java/android/server/BluetoothService.java
+++ b/core/java/android/server/BluetoothService.java
@@ -145,7 +145,12 @@ public class BluetoothService extends IBluetooth.Stub {
private final ArrayList<String> mUuidIntentTracker;
private final HashMap<RemoteService, IBluetoothCallback> mUuidCallbackTracker;
- private final HashMap<Integer, Pair<Integer, IBinder>> mServiceRecordToPid;
+ private static class ServiceRecordClient {
+ int pid;
+ IBinder binder;
+ IBinder.DeathRecipient death;
+ }
+ private final HashMap<Integer, ServiceRecordClient> mServiceRecordToPid;
private final HashMap<String, BluetoothDeviceProfileState> mDeviceProfileState;
private final BluetoothProfileState mA2dpProfileState;
@@ -221,7 +226,7 @@ public class BluetoothService extends IBluetooth.Stub {
mDeviceOobData = new HashMap<String, Pair<byte[], byte[]>>();
mUuidIntentTracker = new ArrayList<String>();
mUuidCallbackTracker = new HashMap<RemoteService, IBluetoothCallback>();
- mServiceRecordToPid = new HashMap<Integer, Pair<Integer, IBinder>>();
+ mServiceRecordToPid = new HashMap<Integer, ServiceRecordClient>();
mDeviceProfileState = new HashMap<String, BluetoothDeviceProfileState>();
mA2dpProfileState = new BluetoothProfileState(mContext, BluetoothProfileState.A2DP);
mHfpProfileState = new BluetoothProfileState(mContext, BluetoothProfileState.HFP);
@@ -1528,11 +1533,17 @@ public class BluetoothService extends IBluetooth.Stub {
return -1;
}
- int pid = Binder.getCallingPid();
- mServiceRecordToPid.put(new Integer(handle), new Pair<Integer, IBinder>(pid, b));
+ ServiceRecordClient client = new ServiceRecordClient();
+ client.pid = Binder.getCallingPid();
+ client.binder = b;
+ client.death = new Reaper(handle, client.pid, RFCOMM_RECORD_REAPER);
+ mServiceRecordToPid.put(new Integer(handle), client);
try {
- b.linkToDeath(new Reaper(handle, pid, RFCOMM_RECORD_REAPER), 0);
- } catch (RemoteException e) {Log.e(TAG, "", e);}
+ b.linkToDeath(client.death, 0);
+ } catch (RemoteException e) {
+ Log.e(TAG, "", e);
+ client.death = null;
+ }
return handle;
}
@@ -1547,10 +1558,15 @@ public class BluetoothService extends IBluetooth.Stub {
}
private synchronized void checkAndRemoveRecord(int handle, int pid) {
- Pair<Integer, IBinder> pidPair = mServiceRecordToPid.get(handle);
- if (pidPair != null && pid == pidPair.first) {
+ ServiceRecordClient client = mServiceRecordToPid.get(handle);
+ if (client != null && pid == client.pid) {
if (DBG) Log.d(TAG, "Removing service record " +
Integer.toHexString(handle) + " for pid " + pid);
+
+ if (client.death != null) {
+ client.binder.unlinkToDeath(client.death, 0);
+ }
+
mServiceRecordToPid.remove(handle);
removeServiceRecordNative(handle);
}
@@ -1880,7 +1896,7 @@ public class BluetoothService extends IBluetooth.Stub {
private void dumpApplicationServiceRecords(PrintWriter pw) {
pw.println("\n--Application Service Records--");
for (Integer handle : mServiceRecordToPid.keySet()) {
- Integer pid = mServiceRecordToPid.get(handle).first;
+ Integer pid = mServiceRecordToPid.get(handle).pid;
pw.println("\tpid " + pid + " handle " + Integer.toHexString(handle));
}
}
diff --git a/core/java/android/text/TextLine.java b/core/java/android/text/TextLine.java
index 68fea1907b87..b73d90046303 100644
--- a/core/java/android/text/TextLine.java
+++ b/core/java/android/text/TextLine.java
@@ -119,6 +119,7 @@ class TextLine {
* @param hasTabs true if the line might contain tabs or emoji
* @param tabStops the tabStops. Can be null.
*/
+ @SuppressWarnings("null")
void set(TextPaint paint, CharSequence text, int start, int limit, int dir,
Directions directions, boolean hasTabs, TabStops tabStops) {
mPaint = paint;
@@ -134,11 +135,12 @@ class TextLine {
mSpanned = null;
boolean hasReplacement = false;
+ SpanSet<ReplacementSpan> replacementSpans = null;
if (text instanceof Spanned) {
mSpanned = (Spanned) text;
- ReplacementSpan[] spans = mSpanned.getSpans(start, limit, ReplacementSpan.class);
- spans = TextUtils.removeEmptySpans(spans, mSpanned, ReplacementSpan.class);
- hasReplacement = spans.length > 0;
+ replacementSpans = new SpanSet<ReplacementSpan>(mSpanned, start, limit,
+ ReplacementSpan.class);
+ hasReplacement = replacementSpans.numberOfSpans > 0;
}
mCharsValid = hasReplacement || hasTabs || directions != Layout.DIRS_ALL_LEFT_TO_RIGHT;
@@ -156,10 +158,9 @@ class TextLine {
// zero-width characters.
char[] chars = mChars;
for (int i = start, inext; i < limit; i = inext) {
- inext = mSpanned.nextSpanTransition(i, limit, ReplacementSpan.class);
- ReplacementSpan[] spans = mSpanned.getSpans(i, inext, ReplacementSpan.class);
- spans = TextUtils.removeEmptySpans(spans, mSpanned, ReplacementSpan.class);
- if (spans.length > 0) {
+ // replacementSpans cannot be null if hasReplacement is true
+ inext = replacementSpans.getNextTransition(i, limit);
+ if (replacementSpans.hasSpansIntersecting(i, inext)) {
// transition into a span
chars[i - start] = '\ufffc';
for (int j = i - start + 1, e = inext - start; j < e; ++j) {
@@ -908,6 +909,15 @@ class TextLine {
numberOfSpans = count;
}
+ public boolean hasSpansIntersecting(int start, int end) {
+ for (int i = 0; i < numberOfSpans; i++) {
+ // equal test is valid since both intervals are not empty by construction
+ if (spanStarts[i] >= end || spanEnds[i] <= start) continue;
+ return true;
+ }
+ return false;
+ }
+
int getNextTransition(int start, int limit) {
for (int i = 0; i < numberOfSpans; i++) {
final int spanStart = spanStarts[i];
diff --git a/core/java/android/text/method/Touch.java b/core/java/android/text/method/Touch.java
index 106a80190b36..3dfd44d90e4d 100644
--- a/core/java/android/text/method/Touch.java
+++ b/core/java/android/text/method/Touch.java
@@ -35,22 +35,30 @@ public class Touch {
* Y position.
*/
public static void scrollTo(TextView widget, Layout layout, int x, int y) {
- final int verticalPadding = widget.getTotalPaddingTop() + widget.getTotalPaddingBottom();
- final int top = layout.getLineForVertical(y);
- final int bottom = layout.getLineForVertical(y + widget.getHeight() - verticalPadding);
+ final int horizontalPadding = widget.getTotalPaddingLeft() + widget.getTotalPaddingRight();
+ final int availableWidth = widget.getWidth() - horizontalPadding;
- int left = Integer.MAX_VALUE;
- int right = 0;
+ final int top = layout.getLineForVertical(y);
Alignment a = layout.getParagraphAlignment(top);
boolean ltr = layout.getParagraphDirection(top) > 0;
- for (int i = top; i <= bottom; i++) {
- left = (int) Math.min(left, layout.getLineLeft(i));
- right = (int) Math.max(right, layout.getLineRight(i));
+ int left, right;
+ if (widget.getHorizontallyScrolling()) {
+ final int verticalPadding = widget.getTotalPaddingTop() + widget.getTotalPaddingBottom();
+ final int bottom = layout.getLineForVertical(y + widget.getHeight() - verticalPadding);
+
+ left = Integer.MAX_VALUE;
+ right = 0;
+
+ for (int i = top; i <= bottom; i++) {
+ left = (int) Math.min(left, layout.getLineLeft(i));
+ right = (int) Math.max(right, layout.getLineRight(i));
+ }
+ } else {
+ left = 0;
+ right = availableWidth;
}
- final int hoizontalPadding = widget.getTotalPaddingLeft() + widget.getTotalPaddingRight();
- final int availableWidth = widget.getWidth() - hoizontalPadding;
final int actualWidth = right - left;
if (actualWidth < availableWidth) {
@@ -166,16 +174,24 @@ public class Touch {
return false;
}
+ /**
+ * @param widget The text view.
+ * @param buffer The text buffer.
+ */
public static int getInitialScrollX(TextView widget, Spannable buffer) {
DragState[] ds = buffer.getSpans(0, buffer.length(), DragState.class);
return ds.length > 0 ? ds[0].mScrollX : -1;
}
-
+
+ /**
+ * @param widget The text view.
+ * @param buffer The text buffer.
+ */
public static int getInitialScrollY(TextView widget, Spannable buffer) {
DragState[] ds = buffer.getSpans(0, buffer.length(), DragState.class);
return ds.length > 0 ? ds[0].mScrollY : -1;
}
-
+
private static class DragState implements NoCopySpan {
public float mX;
public float mY;
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index cbd08082d781..bd03fb908838 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -2581,6 +2581,17 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
/**
+ * Returns whether the text is allowed to be wider than the View is.
+ * If false, the text will be wrapped to the width of the View.
+ *
+ * @attr ref android.R.styleable#TextView_scrollHorizontally
+ * @hide
+ */
+ public boolean getHorizontallyScrolling() {
+ return mHorizontallyScrolling;
+ }
+
+ /**
* Makes the TextView at least this many lines tall.
*
* Setting this value overrides any other (minimum) height setting. A single line TextView will
@@ -9367,40 +9378,57 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
mPositionY = mTempCoords[1];
}
- public boolean isVisible(int positionX, int positionY) {
- final TextView textView = TextView.this;
+ public void onScrollChanged() {
+ mScrollHasChanged = true;
+ }
+ }
- if (mTempRect == null) mTempRect = new Rect();
- final Rect clip = mTempRect;
- clip.left = getCompoundPaddingLeft();
- clip.top = getExtendedPaddingTop();
- clip.right = textView.getWidth() - getCompoundPaddingRight();
- clip.bottom = textView.getHeight() - getExtendedPaddingBottom();
-
- final ViewParent parent = textView.getParent();
- if (parent == null || !parent.getChildVisibleRect(textView, clip, null)) {
- return false;
- }
+ private boolean isPositionVisible(int positionX, int positionY) {
+ synchronized (sTmpPosition) {
+ final float[] position = sTmpPosition;
+ position[0] = positionX;
+ position[1] = positionY;
+ View view = this;
- int posX = mPositionX + positionX;
- int posY = mPositionY + positionY;
+ while (view != null) {
+ if (view != this) {
+ // Local scroll is already taken into account in positionX/Y
+ position[0] -= view.getScrollX();
+ position[1] -= view.getScrollY();
+ }
- // Offset by 1 to take into account 0.5 and int rounding around getPrimaryHorizontal.
- return posX >= clip.left - 1 && posX <= clip.right + 1 &&
- posY >= clip.top && posY <= clip.bottom;
- }
+ if (position[0] < 0 || position[1] < 0 ||
+ position[0] > view.getWidth() || position[1] > view.getHeight()) {
+ return false;
+ }
- public boolean isOffsetVisible(int offset) {
- final int line = mLayout.getLineForOffset(offset);
- final int lineBottom = mLayout.getLineBottom(line);
- final int primaryHorizontal = (int) mLayout.getPrimaryHorizontal(offset);
- return isVisible(primaryHorizontal + viewportToContentHorizontalOffset(),
- lineBottom + viewportToContentVerticalOffset());
- }
+ if (!view.getMatrix().isIdentity()) {
+ view.getMatrix().mapPoints(position);
+ }
- public void onScrollChanged() {
- mScrollHasChanged = true;
+ position[0] += view.getLeft();
+ position[1] += view.getTop();
+
+ final ViewParent parent = view.getParent();
+ if (parent instanceof View) {
+ view = (View) parent;
+ } else {
+ // We've reached the ViewRoot, stop iterating
+ view = null;
+ }
+ }
}
+
+ // We've been able to walk up the view hierarchy and the position was never clipped
+ return true;
+ }
+
+ private boolean isOffsetVisible(int offset) {
+ final int line = mLayout.getLineForOffset(offset);
+ final int lineBottom = mLayout.getLineBottom(line);
+ final int primaryHorizontal = (int) mLayout.getPrimaryHorizontal(offset);
+ return isPositionVisible(primaryHorizontal + viewportToContentHorizontalOffset(),
+ lineBottom + viewportToContentVerticalOffset());
}
@Override
@@ -9501,7 +9529,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
public void updatePosition(int parentPositionX, int parentPositionY,
boolean parentPositionChanged, boolean parentScrolled) {
// Either parentPositionChanged or parentScrolled is true, check if still visible
- if (isShowing() && getPositionListener().isOffsetVisible(getTextOffset())) {
+ if (isShowing() && isOffsetVisible(getTextOffset())) {
if (parentScrolled) computeLocalPosition();
updatePosition(parentPositionX, parentPositionY);
} else {
@@ -10525,7 +10553,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
return false;
}
- return getPositionListener().isVisible(mPositionX + mHotspotX, mPositionY);
+ return TextView.this.isPositionVisible(mPositionX + mHotspotX, mPositionY);
}
public abstract int getCurrentCursorOffset();
@@ -11507,6 +11535,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
private Path mHighlightPath;
private boolean mHighlightPathBogus = true;
private static final RectF sTempRect = new RectF();
+ private static final float[] sTmpPosition = new float[2];
// XXX should be much larger
private static final int VERY_WIDE = 1024*1024;
diff --git a/docs/html/guide/practices/ui_guidelines/widget_design.jd b/docs/html/guide/practices/ui_guidelines/widget_design.jd
index de20e007f393..f63f3c4a8a76 100644
--- a/docs/html/guide/practices/ui_guidelines/widget_design.jd
+++ b/docs/html/guide/practices/ui_guidelines/widget_design.jd
@@ -250,13 +250,15 @@ android.widget.FrameLayout}. Just as your activity layouts must adapt to differe
sizes, widget layouts must adapt to different Home screen grid cell sizes.</p>
<p>Below is an example layout that a music widget showing text information and two buttons can use.
-It builds upon the previous discussion of adding margins depending on OS version.</p>
+It builds upon the previous discussion of adding margins depending on OS version. Note that the
+most robust and resilient way to add margins to the widget is to wrap the widget frame and contents
+in a padded {@link android.widget.FrameLayout}.</p>
<pre>
&lt;FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:layout_margin="@dimen/widget_margin"&gt;
+ android:padding="@dimen/widget_margin"&gt;
&lt;LinearLayout
android:layout_width="match_parent"
@@ -295,16 +297,16 @@ use flexible layouts attributes like so:</p>
<p>When a user adds the widget to their home screen, on an example Android 4.0 device where each
-grid cell is 80dp &times; 100dp in size and 16dp of margins are automatically applied on all sizes,
+grid cell is 80dp &times; 100dp in size and 8dp of margins are automatically applied on all sizes,
the widget will be stretched, like so:</p>
<img src="{@docRoot}images/widget_design/music_example_stretched.png"
- alt="Music widget sitting on an example 80dp x 100dp grid with 16dp of automatic margins
+ alt="Music widget sitting on an example 80dp x 100dp grid with 8dp of automatic margins
added by the system" id="music_example_stretched">
<p class="img-caption"><strong>Figure 7.</strong> Music widget sitting on an example 80dp x 100dp
-grid with 16dp of automatic margins added by the system.</p>
+grid with 8dp of automatic margins added by the system.</p>
<h2 id="templates">Using the App Widget Templates Pack</h2>
diff --git a/docs/html/guide/topics/appwidgets/index.jd b/docs/html/guide/topics/appwidgets/index.jd
index 61337b782a75..2cb23c1cdbba 100644
--- a/docs/html/guide/topics/appwidgets/index.jd
+++ b/docs/html/guide/topics/appwidgets/index.jd
@@ -346,7 +346,7 @@ following layout classes:</p>
&lt;FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
- <strong>android:layout_margin="@dimen/widget_margin"&gt;</strong>
+ <strong>android:padding="@dimen/widget_margin"&gt;</strong>
&lt;LinearLayout
android:layout_width="match_parent"
@@ -363,7 +363,7 @@ following layout classes:</p>
<li>Create two dimensions resources, one in <code>res/values/</code> to provide the pre-Android 4.0 custom margins, and one in <code>res/values-v14/</code> to provide no extra padding for Android 4.0 widgets:
<p><strong>res/values/dimens.xml</strong>:<br>
- <pre>&lt;dimen name="widget_margin"&gt;15dp&lt;/dimen&gt;</pre></p>
+ <pre>&lt;dimen name="widget_margin"&gt;8dp&lt;/dimen&gt;</pre></p>
<p><strong>res/values-v14/dimens.xml</strong>:<br>
<pre>&lt;dimen name="widget_margin"&gt;0dp&lt;/dimen&gt;</pre></p>
diff --git a/libs/rs/rsScriptC.cpp b/libs/rs/rsScriptC.cpp
index 2e7f2134fbaa..cd7b3a72ffef 100644
--- a/libs/rs/rsScriptC.cpp
+++ b/libs/rs/rsScriptC.cpp
@@ -21,6 +21,7 @@
#ifndef ANDROID_RS_SERIALIZE
#include <bcinfo/BitcodeTranslator.h>
+#include <bcinfo/BitcodeWrapper.h>
#endif
using namespace android;
@@ -196,7 +197,24 @@ bool ScriptC::runCompiler(Context *rsc,
//LOGE("runCompiler %p %p %p %p %p %i", rsc, this, resName, cacheDir, bitcode, bitcodeLen);
#ifndef ANDROID_RS_SERIALIZE
- uint32_t sdkVersion = rsc->getTargetSdkVersion();
+ uint32_t sdkVersion = 0;
+ bcinfo::BitcodeWrapper bcWrapper((const char *)bitcode, bitcodeLen);
+ if (!bcWrapper.unwrap()) {
+ LOGE("Bitcode is not in proper container format (raw or wrapper)");
+ return false;
+ }
+
+ rsAssert(bcWrapper.getHeaderVersion() == 0);
+ if (bcWrapper.getBCFileType() == bcinfo::BC_WRAPPER) {
+ sdkVersion = bcWrapper.getTargetAPI();
+ }
+
+ if (sdkVersion == 0) {
+ // This signals that we didn't have a wrapper containing information
+ // about the bitcode.
+ sdkVersion = rsc->getTargetSdkVersion();
+ }
+
if (BT) {
delete BT;
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index 2dcd80d74d1b..2232995c5c64 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -34,6 +34,7 @@ import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.PixelFormat;
import android.graphics.PointF;
+import android.hardware.CameraSound;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Environment;
@@ -49,6 +50,7 @@ import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.animation.Interpolator;
import android.widget.ImageView;
+
import com.android.systemui.R;
import java.io.File;
@@ -254,6 +256,8 @@ class GlobalScreenshot {
private float mBgPadding;
private float mBgPaddingScale;
+ private CameraSound mCameraSound;
+
/**
* @param context everything needs a context :(
@@ -303,6 +307,9 @@ class GlobalScreenshot {
// Scale has to account for both sides of the bg
mBgPadding = (float) r.getDimensionPixelSize(R.dimen.global_screenshot_bg_padding);
mBgPaddingScale = mBgPadding / mDisplayMetrics.widthPixels;
+
+ // Setup the Camera shutter sound
+ mCameraSound = new CameraSound();
}
/**
@@ -413,6 +420,9 @@ class GlobalScreenshot {
mScreenshotLayout.post(new Runnable() {
@Override
public void run() {
+ // Play the shutter sound to notify that we've taken a screenshot
+ mCameraSound.playSound(CameraSound.SHUTTER_CLICK);
+
mScreenshotView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
mScreenshotView.buildLayer();
mScreenshotAnimation.start();
diff --git a/services/java/com/android/server/DeviceStorageMonitorService.java b/services/java/com/android/server/DeviceStorageMonitorService.java
index d34087f959d0..16eeb7babb35 100644
--- a/services/java/com/android/server/DeviceStorageMonitorService.java
+++ b/services/java/com/android/server/DeviceStorageMonitorService.java
@@ -163,7 +163,6 @@ public class DeviceStorageMonitorService extends Binder {
} catch (IllegalArgumentException e) {
// ignore; report -1
}
- mCacheFileStats.restat(CACHE_PATH);
EventLog.writeEvent(EventLogTags.FREE_STORAGE_LEFT,
mFreeMem, mFreeSystem, mFreeCache);
}