summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/current.txt2
-rw-r--r--core/java/android/app/ActionBar.java27
-rw-r--r--core/java/com/android/internal/app/ActionBarImpl.java28
-rw-r--r--core/java/com/android/internal/widget/ActionBarContainer.java40
-rw-r--r--core/java/com/android/internal/widget/ActionBarView.java38
-rw-r--r--core/jni/android/graphics/TextLayoutCache.cpp114
-rw-r--r--core/res/res/drawable-hdpi/btn_cab_done_default_holo.9.pngbin2247 -> 1115 bytes
-rw-r--r--core/res/res/drawable-hdpi/btn_cab_done_focused_holo.9.pngbin2660 -> 1540 bytes
-rw-r--r--core/res/res/drawable-hdpi/btn_cab_done_pressed_holo.9.pngbin1561 -> 1578 bytes
-rw-r--r--core/res/res/drawable-mdpi/btn_cab_done_default_holo.9.pngbin1347 -> 762 bytes
-rw-r--r--core/res/res/drawable-mdpi/btn_cab_done_focused_holo.9.pngbin1594 -> 1024 bytes
-rw-r--r--core/res/res/drawable-mdpi/btn_cab_done_pressed_holo.9.pngbin1008 -> 854 bytes
-rw-r--r--core/res/res/drawable/btn_cab_done.xml4
-rw-r--r--core/res/res/values-w480dp/bools.xml1
-rwxr-xr-xcore/res/res/values/attrs.xml4
-rw-r--r--core/res/res/values/bools.xml1
-rw-r--r--core/res/res/values/styles.xml1
-rw-r--r--drm/drmserver/DrmManager.cpp2
-rw-r--r--media/jni/Android.mk4
-rw-r--r--media/jni/android_mtp_MtpDatabase.cpp63
-rw-r--r--media/libstagefright/MPEG4Extractor.cpp5
-rw-r--r--media/mtp/MtpDataPacket.cpp10
-rw-r--r--media/mtp/MtpDataPacket.h1
-rw-r--r--media/mtp/MtpDatabase.h2
-rw-r--r--media/mtp/MtpServer.cpp21
-rw-r--r--media/mtp/MtpServer.h1
-rw-r--r--tests/BiDiTests/res/layout/biditest_main.xml1
-rw-r--r--tests/BiDiTests/res/values/strings.xml3
-rw-r--r--tests/BiDiTests/src/com/android/bidi/BiDiTestView.java10
29 files changed, 324 insertions, 59 deletions
diff --git a/api/current.txt b/api/current.txt
index 8ec773241e54..0c3a0c4a21e2 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -2102,6 +2102,7 @@ package android.app {
method public abstract void setCustomView(android.view.View);
method public abstract void setCustomView(android.view.View, android.app.ActionBar.LayoutParams);
method public abstract void setCustomView(int);
+ method public abstract void setDisplayDisableHomeEnabled(boolean);
method public abstract void setDisplayHomeAsUpEnabled(boolean);
method public abstract void setDisplayOptions(int);
method public abstract void setDisplayOptions(int, int);
@@ -2121,6 +2122,7 @@ package android.app {
method public abstract void setTitle(java.lang.CharSequence);
method public abstract void setTitle(int);
method public abstract void show();
+ field public static final int DISPLAY_DISABLE_HOME = 32; // 0x20
field public static final int DISPLAY_HOME_AS_UP = 4; // 0x4
field public static final int DISPLAY_SHOW_CUSTOM = 16; // 0x10
field public static final int DISPLAY_SHOW_HOME = 2; // 0x2
diff --git a/core/java/android/app/ActionBar.java b/core/java/android/app/ActionBar.java
index a9e84d7e9a31..cac06ec54eeb 100644
--- a/core/java/android/app/ActionBar.java
+++ b/core/java/android/app/ActionBar.java
@@ -107,6 +107,18 @@ public abstract class ActionBar {
public static final int DISPLAY_SHOW_CUSTOM = 0x10;
/**
+ * Disable the 'home' element. This may be combined with
+ * {@link #DISPLAY_SHOW_HOME} to create a non-focusable/non-clickable
+ * 'home' element. Useful for a level of your app's navigation hierarchy
+ * where clicking 'home' doesn't do anything.
+ *
+ * @see #setDisplayOptions(int)
+ * @see #setDisplayOptions(int, int)
+ * @see #setDisplayDisableHomeEnabled(boolean)
+ */
+ public static final int DISPLAY_DISABLE_HOME = 0x20;
+
+ /**
* Set the action bar into custom navigation mode, supplying a view
* for custom navigation.
*
@@ -393,6 +405,21 @@ public abstract class ActionBar {
public abstract void setDisplayShowCustomEnabled(boolean showCustom);
/**
+ * Set whether the 'home' affordance on the action bar should be disabled.
+ * If set, the 'home' element will not be focusable or clickable, useful if
+ * the user is at the top level of the app's navigation hierarchy.
+ *
+ * <p>To set several display options at once, see the setDisplayOptions methods.
+ *
+ * @param disableHome true to disable the 'home' element.
+ *
+ * @see #setDisplayOptions(int)
+ * @see #setDisplayOptions(int, int)
+ * @see #DISPLAY_DISABLE_HOME
+ */
+ public abstract void setDisplayDisableHomeEnabled(boolean disableHome);
+
+ /**
* Set the ActionBar's background.
*
* @param d Background drawable
diff --git a/core/java/com/android/internal/app/ActionBarImpl.java b/core/java/com/android/internal/app/ActionBarImpl.java
index 96520858fe95..dccfa6c537fb 100644
--- a/core/java/com/android/internal/app/ActionBarImpl.java
+++ b/core/java/com/android/internal/app/ActionBarImpl.java
@@ -42,8 +42,10 @@ import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
+import android.view.ViewGroup;
import android.view.Window;
import android.view.animation.DecelerateInterpolator;
+import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;
import android.widget.SpinnerAdapter;
@@ -71,6 +73,7 @@ public class ActionBarImpl extends ActionBar {
private ActionBarContextView mUpperContextView;
private LinearLayout mLowerContextView;
private View mContentView;
+ private ViewGroup mExternalTabView;
private ArrayList<TabImpl> mTabs = new ArrayList<TabImpl>();
@@ -172,6 +175,18 @@ public class ActionBarImpl extends ActionBar {
mActionView.setContextView(mUpperContextView);
mContextDisplayMode = mLowerContextView == null ?
CONTEXT_DISPLAY_NORMAL : CONTEXT_DISPLAY_SPLIT;
+
+ if (!mActionView.hasEmbeddedTabs()) {
+ HorizontalScrollView tabScroller = new HorizontalScrollView(mContext);
+ ViewGroup tabContainer = mActionView.createTabContainer();
+ tabScroller.setHorizontalFadingEdgeEnabled(true);
+ tabScroller.addView(tabContainer);
+ tabScroller.setVisibility(getNavigationMode() == NAVIGATION_MODE_TABS ?
+ View.VISIBLE : View.GONE);
+ mActionView.setExternalTabLayout(tabContainer);
+ mContainerView.setTabContainer(tabScroller);
+ mExternalTabView = tabScroller;
+ }
}
/**
@@ -239,6 +254,11 @@ public class ActionBarImpl extends ActionBar {
}
@Override
+ public void setDisplayDisableHomeEnabled(boolean disableHome) {
+ setDisplayOptions(disableHome ? DISPLAY_DISABLE_HOME : 0, DISPLAY_DISABLE_HOME);
+ }
+
+ @Override
public void setTitle(int resId) {
setTitle(mContext.getString(resId));
}
@@ -533,7 +553,7 @@ public class ActionBarImpl extends ActionBar {
final int count = mContainerView.getChildCount();
for (int i = 0; i < count; i++) {
final View child = mContainerView.getChildAt(i);
- if (i == viewIndex) {
+ if (i == viewIndex || child == mContainerView.getTabContainer()) {
continue;
}
@@ -840,11 +860,17 @@ public class ActionBarImpl extends ActionBar {
case NAVIGATION_MODE_TABS:
mSavedTabPosition = getSelectedNavigationIndex();
selectTab(null);
+ if (!mActionView.hasEmbeddedTabs()) {
+ mExternalTabView.setVisibility(View.GONE);
+ }
break;
}
mActionView.setNavigationMode(mode);
switch (mode) {
case NAVIGATION_MODE_TABS:
+ if (!mActionView.hasEmbeddedTabs()) {
+ mExternalTabView.setVisibility(View.VISIBLE);
+ }
if (mSavedTabPosition != INVALID_POSITION) {
setSelectedNavigationItem(mSavedTabPosition);
mSavedTabPosition = INVALID_POSITION;
diff --git a/core/java/com/android/internal/widget/ActionBarContainer.java b/core/java/com/android/internal/widget/ActionBarContainer.java
index c9b0ec9e838d..3deb036ea89a 100644
--- a/core/java/com/android/internal/widget/ActionBarContainer.java
+++ b/core/java/com/android/internal/widget/ActionBarContainer.java
@@ -20,6 +20,7 @@ import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.MotionEvent;
+import android.view.View;
import android.widget.FrameLayout;
/**
@@ -29,6 +30,7 @@ import android.widget.FrameLayout;
*/
public class ActionBarContainer extends FrameLayout {
private boolean mIsTransitioning;
+ private View mTabContainer;
public ActionBarContainer(Context context) {
this(context, null);
@@ -65,6 +67,44 @@ public class ActionBarContainer extends FrameLayout {
@Override
public boolean onTouchEvent(MotionEvent ev) {
super.onTouchEvent(ev);
+
+ // An action bar always eats touch events.
return true;
}
+
+ public void setTabContainer(View tabView) {
+ if (mTabContainer != null) {
+ removeView(mTabContainer);
+ }
+ mTabContainer = tabView;
+ addView(tabView);
+ }
+
+ public View getTabContainer() {
+ return mTabContainer;
+ }
+
+ @Override
+ public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ if (mTabContainer != null && mTabContainer.getVisibility() != GONE) {
+ final int mode = MeasureSpec.getMode(heightMeasureSpec);
+ if (mode == MeasureSpec.AT_MOST) {
+ final int measuredHeight = getMeasuredHeight();
+ final int maxHeight = MeasureSpec.getSize(heightMeasureSpec);
+ setMeasuredDimension(getMeasuredWidth(),
+ Math.min(measuredHeight + mTabContainer.getMeasuredHeight(), maxHeight));
+ }
+ }
+ }
+
+ @Override
+ public void onLayout(boolean changed, int l, int t, int r, int b) {
+ super.onLayout(changed, l, t, r, b);
+ if (mTabContainer != null && mTabContainer.getVisibility() != GONE) {
+ final int containerHeight = getMeasuredHeight();
+ mTabContainer.layout(l, containerHeight - mTabContainer.getMeasuredHeight(),
+ r, containerHeight);
+ }
+ }
}
diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java
index fa8eb5141674..a572e1168372 100644
--- a/core/java/com/android/internal/widget/ActionBarView.java
+++ b/core/java/com/android/internal/widget/ActionBarView.java
@@ -97,7 +97,7 @@ public class ActionBarView extends ViewGroup {
private Spinner mSpinner;
private LinearLayout mListNavLayout;
private HorizontalScrollView mTabScrollView;
- private LinearLayout mTabLayout;
+ private ViewGroup mTabLayout;
private View mCustomNavView;
private ProgressBar mProgressView;
private ProgressBar mIndeterminateProgressView;
@@ -112,6 +112,7 @@ public class ActionBarView extends ViewGroup {
private boolean mShowMenu;
private boolean mUserTitle;
+ private boolean mIncludeTabs;
private MenuBuilder mOptionsMenu;
private ActionMenuView mMenuView;
@@ -201,6 +202,8 @@ public class ActionBarView extends ViewGroup {
mProgressBarPadding = a.getDimensionPixelOffset(R.styleable.ActionBar_progressBarPadding, 0);
mItemPadding = a.getDimensionPixelOffset(R.styleable.ActionBar_itemPadding, 0);
+ mIncludeTabs = a.getBoolean(R.styleable.ActionBar_embeddedTabs, true);
+
setDisplayOptions(a.getInt(R.styleable.ActionBar_displayOptions, DISPLAY_DEFAULT));
final int customNavId = a.getResourceId(R.styleable.ActionBar_customNavigationLayout, 0);
@@ -242,6 +245,14 @@ public class ActionBarView extends ViewGroup {
addView(mIndeterminateProgressView);
}
+ public boolean hasEmbeddedTabs() {
+ return mIncludeTabs;
+ }
+
+ public void setExternalTabLayout(ViewGroup tabLayout) {
+ mTabLayout = tabLayout;
+ }
+
@Override
public ActionMode startActionModeForChild(View child, ActionMode.Callback callback) {
// No starting an action mode for an action bar child! (Where would it go?)
@@ -389,6 +400,12 @@ public class ActionBarView extends ViewGroup {
public void setDisplayOptions(int options) {
final int flagsChanged = options ^ mDisplayOptions;
mDisplayOptions = options;
+
+ if ((flagsChanged & ActionBar.DISPLAY_DISABLE_HOME) != 0) {
+ final boolean disableHome = (options & ActionBar.DISPLAY_DISABLE_HOME) != 0;
+ mHomeLayout.setEnabled(!disableHome);
+ }
+
if ((flagsChanged & DISPLAY_RELAYOUT_MASK) != 0) {
final int vis = (options & ActionBar.DISPLAY_SHOW_HOME) != 0 ? VISIBLE : GONE;
mHomeLayout.setVisibility(vis);
@@ -477,7 +494,7 @@ public class ActionBarView extends ViewGroup {
}
break;
case ActionBar.NAVIGATION_MODE_TABS:
- if (mTabLayout != null) {
+ if (mTabScrollView != null) {
removeView(mTabScrollView);
}
}
@@ -502,7 +519,9 @@ public class ActionBarView extends ViewGroup {
break;
case ActionBar.NAVIGATION_MODE_TABS:
ensureTabsExist();
- addView(mTabScrollView);
+ if (mTabScrollView != null) {
+ addView(mTabScrollView);
+ }
break;
}
mNavigationMode = mode;
@@ -511,15 +530,24 @@ public class ActionBarView extends ViewGroup {
}
private void ensureTabsExist() {
+ if (!mIncludeTabs) return;
+
if (mTabScrollView == null) {
mTabScrollView = new HorizontalScrollView(getContext());
mTabScrollView.setHorizontalFadingEdgeEnabled(true);
- mTabLayout = new LinearLayout(getContext(), null,
- com.android.internal.R.attr.actionBarTabBarStyle);
+ mTabLayout = createTabContainer();
mTabScrollView.addView(mTabLayout);
}
}
+ public ViewGroup createTabContainer() {
+ ViewGroup result = new LinearLayout(getContext(), null,
+ com.android.internal.R.attr.actionBarTabBarStyle);
+ result.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,
+ mContentHeight));
+ return result;
+ }
+
public void setDropdownAdapter(SpinnerAdapter adapter) {
mSpinnerAdapter = adapter;
if (mSpinner != null) {
diff --git a/core/jni/android/graphics/TextLayoutCache.cpp b/core/jni/android/graphics/TextLayoutCache.cpp
index df017f5d42c3..26aa7d9af7cc 100644
--- a/core/jni/android/graphics/TextLayoutCache.cpp
+++ b/core/jni/android/graphics/TextLayoutCache.cpp
@@ -399,6 +399,14 @@ struct GlyphRun {
int isRTL;
};
+void static reverseGlyphArray(jchar* glyphs, size_t count) {
+ for (size_t i = 0; i < count / 2; i++) {
+ jchar temp = glyphs[i];
+ glyphs[i] = glyphs[count - 1 - i];
+ glyphs[count - 1 - i] = temp;
+ }
+}
+
void TextLayoutCacheValue::computeValuesWithHarfbuzz(SkPaint* paint, const UChar* chars,
size_t start, size_t count, size_t contextCount, int dirFlags,
jfloat* outAdvances, jfloat* outTotalAdvance,
@@ -424,6 +432,10 @@ void TextLayoutCacheValue::computeValuesWithHarfbuzz(SkPaint* paint, const UChar
#endif
computeRunValuesWithHarfbuzz(paint, chars, start, count, contextCount, dirFlags,
outAdvances, outTotalAdvance, outGlyphs, outGlyphsCount);
+
+ if (forceRTL && *outGlyphsCount > 1) {
+ reverseGlyphArray(*outGlyphs, *outGlyphsCount);
+ }
} else {
UBiDi* bidi = ubidi_open();
if (bidi) {
@@ -438,71 +450,81 @@ void TextLayoutCacheValue::computeValuesWithHarfbuzz(SkPaint* paint, const UChar
#if DEBUG_GLYPHS
LOGD("computeValuesWithHarfbuzz -- dirFlags=%d run-count=%d paraDir=%d", dirFlags, rc, paraDir);
#endif
-
if (rc == 1 || !U_SUCCESS(status)) {
computeRunValuesWithHarfbuzz(paint, chars, start, count, contextCount,
dirFlags, outAdvances, outTotalAdvance, outGlyphs, outGlyphsCount);
- ubidi_close(bidi);
- return;
- }
- size_t runIndex = 0;
- Vector<GlyphRun> glyphRuns;
- for (size_t i = 0; i < rc; ++i) {
- int32_t startRun;
- int32_t lengthRun;
- UBiDiDirection runDir = ubidi_getVisualRun(bidi, i, &startRun, &lengthRun);
-
- int newFlags = (runDir == UBIDI_RTL) ? kDirection_RTL : kDirection_LTR;
- jfloat runTotalAdvance = 0;
+ if (dirFlags == 1 && *outGlyphsCount > 1) {
+ reverseGlyphArray(*outGlyphs, *outGlyphsCount);
+ }
+ } else {
+ Vector<GlyphRun> glyphRuns;
jchar* runGlyphs;
size_t runGlyphsCount = 0;
-
+ size_t runIndex = 0;
+ for (size_t i = 0; i < rc; ++i) {
+ int32_t startRun;
+ int32_t lengthRun;
+ UBiDiDirection runDir = ubidi_getVisualRun(bidi, i, &startRun, &lengthRun);
+
+ int newFlags = (runDir == UBIDI_RTL) ? kDirection_RTL : kDirection_LTR;
+ jfloat runTotalAdvance = 0;
#if DEBUG_GLYPHS
- LOGD("computeValuesWithHarfbuzz -- run-start=%d run-len=%d newFlags=%d",
- startRun, lengthRun, newFlags);
+ LOGD("computeValuesWithHarfbuzz -- run-start=%d run-len=%d newFlags=%d",
+ startRun, lengthRun, newFlags);
#endif
- computeRunValuesWithHarfbuzz(paint, chars, startRun,
- lengthRun, contextCount, newFlags,
- outAdvances + runIndex, &runTotalAdvance,
- &runGlyphs, &runGlyphsCount);
+ computeRunValuesWithHarfbuzz(paint, chars, startRun,
+ lengthRun, contextCount, newFlags,
+ outAdvances + runIndex, &runTotalAdvance,
+ &runGlyphs, &runGlyphsCount);
- runIndex += lengthRun;
-
- *outTotalAdvance += runTotalAdvance;
- *outGlyphsCount += runGlyphsCount;
+ runIndex += lengthRun;
+ *outTotalAdvance += runTotalAdvance;
+ *outGlyphsCount += runGlyphsCount;
#if DEBUG_GLYPHS
- LOGD("computeValuesWithHarfbuzz -- run=%d run-glyphs-count=%d",
- i, runGlyphsCount);
- for (size_t j = 0; j < runGlyphsCount; j++) {
- LOGD(" -- glyphs[%d]=%d", j, runGlyphs[j]);
- }
-#endif
- glyphRuns.push(GlyphRun(runGlyphs, runGlyphsCount, newFlags));
- }
-
-#if DEBUG_GLYPHS
- LOGD("computeValuesWithHarfbuzz -- total-glyphs-count=%d", *outGlyphsCount);
+ LOGD("computeValuesWithHarfbuzz -- run=%d run-glyphs-count=%d",
+ i, runGlyphsCount);
+ for (size_t j = 0; j < runGlyphsCount; j++) {
+ LOGD(" -- glyphs[%d]=%d", j, runGlyphs[j]);
+ }
#endif
- *outGlyphs = new jchar[*outGlyphsCount];
- jchar* glyphs = *outGlyphs;
- for (size_t i = 0; i < glyphRuns.size(); i++) {
- const GlyphRun& glyphRun = glyphRuns.itemAt(i);
- if (glyphRun.isRTL) {
- for (size_t n = 0; n < glyphRun.glyphsCount; n++) {
- glyphs[glyphRun.glyphsCount - n - 1] = glyphRun.glyphs[n];
+ glyphRuns.push(GlyphRun(runGlyphs, runGlyphsCount, newFlags));
+ }
+ *outGlyphs = new jchar[*outGlyphsCount];
+
+ jchar* glyphs = *outGlyphs;
+ for (size_t i = 0; i < glyphRuns.size(); i++) {
+ const GlyphRun& glyphRun = glyphRuns.itemAt(i);
+ if (glyphRun.isRTL) {
+ for (size_t n = 0; n < glyphRun.glyphsCount; n++) {
+ glyphs[glyphRun.glyphsCount - n - 1] = glyphRun.glyphs[n];
+ }
+ } else {
+ memcpy(glyphs, glyphRun.glyphs, glyphRun.glyphsCount * sizeof(jchar));
}
- } else {
- memcpy(glyphs, glyphRun.glyphs, glyphRun.glyphsCount * sizeof(jchar));
+ glyphs += glyphRun.glyphsCount;
+ delete[] glyphRun.glyphs;
}
- glyphs += glyphRun.glyphsCount;
- delete[] glyphRun.glyphs;
}
}
ubidi_close(bidi);
+ } else {
+ // Cannot run BiDi, just consider one Run
+#if DEBUG_GLYPHS
+ LOGD("computeValuesWithHarfbuzz -- cannot run BiDi, considering only one Run");
+#endif
+ computeRunValuesWithHarfbuzz(paint, chars, start, count, contextCount, dirFlags,
+ outAdvances, outTotalAdvance, outGlyphs, outGlyphsCount);
+
+ if (dirFlags == 1 && *outGlyphsCount > 1) {
+ reverseGlyphArray(*outGlyphs, *outGlyphsCount);
+ }
}
}
+#if DEBUG_GLYPHS
+ LOGD("computeValuesWithHarfbuzz -- total-glyphs-count=%d", *outGlyphsCount);
+#endif
}
void TextLayoutCacheValue::computeRunValuesWithHarfbuzz(SkPaint* paint, const UChar* chars,
diff --git a/core/res/res/drawable-hdpi/btn_cab_done_default_holo.9.png b/core/res/res/drawable-hdpi/btn_cab_done_default_holo.9.png
index c66716fab76e..f5e60541810b 100644
--- a/core/res/res/drawable-hdpi/btn_cab_done_default_holo.9.png
+++ b/core/res/res/drawable-hdpi/btn_cab_done_default_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_cab_done_focused_holo.9.png b/core/res/res/drawable-hdpi/btn_cab_done_focused_holo.9.png
index 0f1d9a08cbe5..1121070d5733 100644
--- a/core/res/res/drawable-hdpi/btn_cab_done_focused_holo.9.png
+++ b/core/res/res/drawable-hdpi/btn_cab_done_focused_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_cab_done_pressed_holo.9.png b/core/res/res/drawable-hdpi/btn_cab_done_pressed_holo.9.png
index 391227efcff8..1a072a905368 100644
--- a/core/res/res/drawable-hdpi/btn_cab_done_pressed_holo.9.png
+++ b/core/res/res/drawable-hdpi/btn_cab_done_pressed_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_cab_done_default_holo.9.png b/core/res/res/drawable-mdpi/btn_cab_done_default_holo.9.png
index 3a113ee2ea23..7af26cabea27 100644
--- a/core/res/res/drawable-mdpi/btn_cab_done_default_holo.9.png
+++ b/core/res/res/drawable-mdpi/btn_cab_done_default_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_cab_done_focused_holo.9.png b/core/res/res/drawable-mdpi/btn_cab_done_focused_holo.9.png
index 8496965b5f00..486c37a72c1f 100644
--- a/core/res/res/drawable-mdpi/btn_cab_done_focused_holo.9.png
+++ b/core/res/res/drawable-mdpi/btn_cab_done_focused_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_cab_done_pressed_holo.9.png b/core/res/res/drawable-mdpi/btn_cab_done_pressed_holo.9.png
index dc70c6a50350..3cfb4bd49764 100644
--- a/core/res/res/drawable-mdpi/btn_cab_done_pressed_holo.9.png
+++ b/core/res/res/drawable-mdpi/btn_cab_done_pressed_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable/btn_cab_done.xml b/core/res/res/drawable/btn_cab_done.xml
index 154837d1138c..e3cf461511c0 100644
--- a/core/res/res/drawable/btn_cab_done.xml
+++ b/core/res/res/drawable/btn_cab_done.xml
@@ -16,11 +16,11 @@
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_window_focused="false" android:state_enabled="true"
- android:drawable="@drawable/btn_cab_done_holo" />
+ android:drawable="@drawable/btn_cab_done_default_holo" />
<item android:state_pressed="true"
android:drawable="@drawable/btn_cab_done_pressed_holo" />
<item android:state_focused="true" android:state_enabled="true"
android:drawable="@drawable/btn_cab_done_focused_holo" />
<item android:state_enabled="true"
- android:drawable="@drawable/btn_cab_done_holo" />
+ android:drawable="@drawable/btn_cab_done_default_holo" />
</selector>
diff --git a/core/res/res/values-w480dp/bools.xml b/core/res/res/values-w480dp/bools.xml
index ea7eeb58c7d7..c202d90d403b 100644
--- a/core/res/res/values-w480dp/bools.xml
+++ b/core/res/res/values-w480dp/bools.xml
@@ -18,4 +18,5 @@
-->
<resources>
<bool name="allow_action_menu_item_text_with_icon">true</bool>
+ <bool name="action_bar_embed_tabs">true</bool>
</resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index e8767d80a82c..3a44e4f73a82 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -4850,6 +4850,7 @@
<flag name="homeAsUp" value="0x4" />
<flag name="showTitle" value="0x8" />
<flag name="showCustom" value="0x10" />
+ <flag name="disableHome" value="0x20" />
</attr>
<!-- Specifies title text used for navigationMode="normal" -->
<attr name="title" />
@@ -4882,6 +4883,9 @@
<!-- Specifies padding that should be applied to the left and right sides of
system-provided items in the bar. -->
<attr name="itemPadding" format="dimension" />
+ <!-- Specifies whether tabs should be embedded within the bar itself (true)
+ or displayed elsewhere (false). -->
+ <attr name="embeddedTabs" format="boolean" />
</declare-styleable>
<declare-styleable name="ActionMode">
diff --git a/core/res/res/values/bools.xml b/core/res/res/values/bools.xml
index c7dcb515cd09..6eb006f32f03 100644
--- a/core/res/res/values/bools.xml
+++ b/core/res/res/values/bools.xml
@@ -18,4 +18,5 @@
-->
<resources>
<bool name="allow_action_menu_item_text_with_icon">false</bool>
+ <bool name="action_bar_embed_tabs">false</bool>
</resources>
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 198ff8b47cbd..8ce35f8aeccc 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -1074,6 +1074,7 @@
<item name="android:progressBarStyle">@android:style/Widget.ProgressBar.Horizontal</item>
<item name="android:indeterminateProgressStyle">@android:style/Widget.ProgressBar.Small</item>
<item name="android:homeLayout">@android:layout/action_bar_home</item>
+ <item name="android:embeddedTabs">@android:bool/action_bar_embed_tabs</item>
</style>
<style name="Widget.ActionMode">
diff --git a/drm/drmserver/DrmManager.cpp b/drm/drmserver/DrmManager.cpp
index 2fee59c3cc1c..1809619d0262 100644
--- a/drm/drmserver/DrmManager.cpp
+++ b/drm/drmserver/DrmManager.cpp
@@ -101,6 +101,7 @@ status_t DrmManager::loadPlugIns(const String8& plugInDirPath) {
DrmSupportInfo* info = mPlugInManager.getPlugIn(plugInPath).getSupportInfo(0);
if (NULL != info) {
mSupportInfoToPlugInIdMap.add(*info, plugInPath);
+ delete info;
}
}
}
@@ -178,6 +179,7 @@ status_t DrmManager::installDrmEngine(int uniqueId, const String8& absolutePath)
DrmSupportInfo* info = rDrmEngine.getSupportInfo(0);
mSupportInfoToPlugInIdMap.add(*info, absolutePath);
+ delete info;
return DRM_NO_ERROR;
}
diff --git a/media/jni/Android.mk b/media/jni/Android.mk
index 4fd41472b308..77cedd5a365f 100644
--- a/media/jni/Android.mk
+++ b/media/jni/Android.mk
@@ -27,9 +27,11 @@ LOCAL_SHARED_LIBRARIES := \
libcamera_client \
libsqlite \
libmtp \
- libusbhost
+ libusbhost \
+ libexif
LOCAL_C_INCLUDES += \
+ external/jhead \
external/tremor/Tremor \
frameworks/base/core/jni \
frameworks/base/media/libmedia \
diff --git a/media/jni/android_mtp_MtpDatabase.cpp b/media/jni/android_mtp_MtpDatabase.cpp
index 585cd30ceed3..0f3c063bedae 100644
--- a/media/jni/android_mtp_MtpDatabase.cpp
+++ b/media/jni/android_mtp_MtpDatabase.cpp
@@ -35,6 +35,10 @@
#include "MtpUtils.h"
#include "mtp.h"
+extern "C" {
+#include "jhead.h"
+}
+
using namespace android;
// ----------------------------------------------------------------------------
@@ -141,6 +145,8 @@ public:
virtual MtpResponseCode getObjectInfo(MtpObjectHandle handle,
MtpObjectInfo& info);
+ virtual void* getThumbnail(MtpObjectHandle handle, size_t& outThumbSize);
+
virtual MtpResponseCode getObjectFilePath(MtpObjectHandle handle,
MtpString& outFilePath,
int64_t& outFileLength,
@@ -776,10 +782,67 @@ MtpResponseCode MyMtpDatabase::getObjectInfo(MtpObjectHandle handle,
info.mName = strdup((const char *)temp);
env->ReleaseCharArrayElements(mStringBuffer, str, 0);
+ // read EXIF data for thumbnail information
+ if (info.mFormat == MTP_FORMAT_EXIF_JPEG || info.mFormat == MTP_FORMAT_JFIF) {
+ MtpString path;
+ int64_t length;
+ MtpObjectFormat format;
+ if (getObjectFilePath(handle, path, length, format) == MTP_RESPONSE_OK) {
+ ResetJpgfile();
+ // Start with an empty image information structure.
+ memset(&ImageInfo, 0, sizeof(ImageInfo));
+ ImageInfo.FlashUsed = -1;
+ ImageInfo.MeteringMode = -1;
+ ImageInfo.Whitebalance = -1;
+ strncpy(ImageInfo.FileName, (const char *)path, PATH_MAX);
+ if (ReadJpegFile((const char*)path, READ_METADATA)) {
+ Section_t* section = FindSection(M_EXIF);
+ if (section) {
+ info.mThumbCompressedSize = ImageInfo.ThumbnailSize;
+ info.mThumbFormat = MTP_FORMAT_EXIF_JPEG;
+ info.mImagePixWidth = ImageInfo.Width;
+ info.mImagePixHeight = ImageInfo.Height;
+ }
+ }
+ DiscardData();
+ }
+ }
+
checkAndClearExceptionFromCallback(env, __FUNCTION__);
return MTP_RESPONSE_OK;
}
+void* MyMtpDatabase::getThumbnail(MtpObjectHandle handle, size_t& outThumbSize) {
+ MtpString path;
+ int64_t length;
+ MtpObjectFormat format;
+ void* result = NULL;
+ outThumbSize = 0;
+
+ if (getObjectFilePath(handle, path, length, format) == MTP_RESPONSE_OK
+ && (format == MTP_FORMAT_EXIF_JPEG || format == MTP_FORMAT_JFIF)) {
+ ResetJpgfile();
+ // Start with an empty image information structure.
+ memset(&ImageInfo, 0, sizeof(ImageInfo));
+ ImageInfo.FlashUsed = -1;
+ ImageInfo.MeteringMode = -1;
+ ImageInfo.Whitebalance = -1;
+ strncpy(ImageInfo.FileName, (const char *)path, PATH_MAX);
+ if (ReadJpegFile((const char*)path, READ_METADATA)) {
+ Section_t* section = FindSection(M_EXIF);
+ if (section) {
+ outThumbSize = ImageInfo.ThumbnailSize;
+ result = malloc(outThumbSize);
+ if (result)
+ memcpy(result, section->Data + ImageInfo.ThumbnailOffset + 8, outThumbSize);
+ }
+ DiscardData();
+ }
+ }
+
+ return result;
+}
+
MtpResponseCode MyMtpDatabase::getObjectFilePath(MtpObjectHandle handle,
MtpString& outFilePath,
int64_t& outFileLength,
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index 01d0a929b552..8787214f2525 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -2130,6 +2130,11 @@ static bool isCompatibleBrand(uint32_t fourcc) {
FOURCC('3', 'g', 'p', '4'),
FOURCC('m', 'p', '4', '1'),
FOURCC('m', 'p', '4', '2'),
+
+ // Won't promise that the following file types can be played.
+ // Just give these file types a chance.
+ FOURCC('q', 't', ' ', ' '), // Apple's QuickTime
+ FOURCC('M', 'S', 'N', 'V'), // Sony's PSP
};
for (size_t i = 0;
diff --git a/media/mtp/MtpDataPacket.cpp b/media/mtp/MtpDataPacket.cpp
index 0b0c80d11d8c..817eac055f72 100644
--- a/media/mtp/MtpDataPacket.cpp
+++ b/media/mtp/MtpDataPacket.cpp
@@ -388,6 +388,16 @@ int MtpDataPacket::writeDataHeader(int fd, uint32_t length) {
int ret = ::write(fd, mBuffer, MTP_CONTAINER_HEADER_SIZE);
return (ret < 0 ? ret : 0);
}
+
+int MtpDataPacket::writeData(int fd, void* data, uint32_t length) {
+ MtpPacket::putUInt32(MTP_CONTAINER_LENGTH_OFFSET, length + MTP_CONTAINER_HEADER_SIZE);
+ MtpPacket::putUInt16(MTP_CONTAINER_TYPE_OFFSET, MTP_CONTAINER_TYPE_DATA);
+ int ret = ::write(fd, mBuffer, MTP_CONTAINER_HEADER_SIZE);
+ if (ret == MTP_CONTAINER_HEADER_SIZE)
+ ret = ::write(fd, data, length);
+ return (ret < 0 ? ret : 0);
+}
+
#endif // MTP_DEVICE
#ifdef MTP_HOST
diff --git a/media/mtp/MtpDataPacket.h b/media/mtp/MtpDataPacket.h
index 577cea152f69..8a08948b43e8 100644
--- a/media/mtp/MtpDataPacket.h
+++ b/media/mtp/MtpDataPacket.h
@@ -100,6 +100,7 @@ public:
// write our data to the given file descriptor
int write(int fd);
int writeDataHeader(int fd, uint32_t length);
+ int writeData(int fd, void* data, uint32_t length);
#endif
#ifdef MTP_HOST
diff --git a/media/mtp/MtpDatabase.h b/media/mtp/MtpDatabase.h
index d7bde00a4dc7..4e6ac7a8a3d8 100644
--- a/media/mtp/MtpDatabase.h
+++ b/media/mtp/MtpDatabase.h
@@ -84,6 +84,8 @@ public:
virtual MtpResponseCode getObjectInfo(MtpObjectHandle handle,
MtpObjectInfo& info) = 0;
+ virtual void* getThumbnail(MtpObjectHandle handle, size_t& outThumbSize) = 0;
+
virtual MtpResponseCode getObjectFilePath(MtpObjectHandle handle,
MtpString& outFilePath,
int64_t& outFileLength,
diff --git a/media/mtp/MtpServer.cpp b/media/mtp/MtpServer.cpp
index b744b5b4c84a..4a8fd3e33d91 100644
--- a/media/mtp/MtpServer.cpp
+++ b/media/mtp/MtpServer.cpp
@@ -50,7 +50,7 @@ static const MtpOperationCode kSupportedOperationCodes[] = {
MTP_OPERATION_GET_OBJECT_HANDLES,
MTP_OPERATION_GET_OBJECT_INFO,
MTP_OPERATION_GET_OBJECT,
-// MTP_OPERATION_GET_THUMB,
+ MTP_OPERATION_GET_THUMB,
MTP_OPERATION_DELETE_OBJECT,
MTP_OPERATION_SEND_OBJECT_INFO,
MTP_OPERATION_SEND_OBJECT,
@@ -370,6 +370,9 @@ bool MtpServer::handleRequest() {
case MTP_OPERATION_GET_OBJECT:
response = doGetObject();
break;
+ case MTP_OPERATION_GET_THUMB:
+ response = doGetThumb();
+ break;
case MTP_OPERATION_GET_PARTIAL_OBJECT:
case MTP_OPERATION_GET_PARTIAL_OBJECT_64:
response = doGetPartialObject(operation);
@@ -736,6 +739,22 @@ MtpResponseCode MtpServer::doGetObject() {
return MTP_RESPONSE_OK;
}
+MtpResponseCode MtpServer::doGetThumb() {
+ MtpObjectHandle handle = mRequest.getParameter(1);
+ size_t thumbSize;
+ void* thumb = mDatabase->getThumbnail(handle, thumbSize);
+ if (thumb) {
+ // send data
+ mData.setOperationCode(mRequest.getOperationCode());
+ mData.setTransactionID(mRequest.getTransactionID());
+ mData.writeData(mFD, thumb, thumbSize);
+ free(thumb);
+ return MTP_RESPONSE_OK;
+ } else {
+ return MTP_RESPONSE_GENERAL_ERROR;
+ }
+}
+
MtpResponseCode MtpServer::doGetPartialObject(MtpOperationCode operation) {
if (!hasStorage())
return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
diff --git a/media/mtp/MtpServer.h b/media/mtp/MtpServer.h
index b06eb287ba58..859a18e63b66 100644
--- a/media/mtp/MtpServer.h
+++ b/media/mtp/MtpServer.h
@@ -133,6 +133,7 @@ private:
MtpResponseCode doGetObjectPropList();
MtpResponseCode doGetObjectInfo();
MtpResponseCode doGetObject();
+ MtpResponseCode doGetThumb();
MtpResponseCode doGetPartialObject(MtpOperationCode operation);
MtpResponseCode doSendObjectInfo();
MtpResponseCode doSendObject();
diff --git a/tests/BiDiTests/res/layout/biditest_main.xml b/tests/BiDiTests/res/layout/biditest_main.xml
index 087c9a34f4a5..044a35567c81 100644
--- a/tests/BiDiTests/res/layout/biditest_main.xml
+++ b/tests/BiDiTests/res/layout/biditest_main.xml
@@ -43,7 +43,6 @@
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:textSize="32dip"
- android:text="@string/edittext_text"
/>
</LinearLayout>
diff --git a/tests/BiDiTests/res/values/strings.xml b/tests/BiDiTests/res/values/strings.xml
index d20600e1307c..c272df18d42a 100644
--- a/tests/BiDiTests/res/values/strings.xml
+++ b/tests/BiDiTests/res/values/strings.xml
@@ -20,10 +20,11 @@
<string name="normal_long_text">mmmmmmmmmmmmmmmmmmmmmmmm</string>
<string name="normal_long_text_2">nnnnnnnnnnnnnnnnnnnnnnnn</string>
<string name="normal_long_text_3">Notify me when an open network is available</string>
- <string name="arabic_text">&#x0644;&#x0627; &#x0627;&#x0646;&#x0627; hello world</string>
+ <string name="arabic_text">&#x0644;&#x0627; &#x0627;&#x0646;&#x0627; hello Arabic</string>
<string name="chinese_text">利比亚局势或影响美俄关系发展</string>
<string name="italic_text">Italic String</string>
<string name="bold_text">Bold String - other text</string>
<string name="bold_italic_text">Bold Italic String</string>
<string name="mixed_text_1">he said in Arabic: &#x0644;&#x0627;. Wow this is cool</string>
+ <string name="hebrew_text">&#x05DD;&#x05DE;</string>
</resources> \ No newline at end of file
diff --git a/tests/BiDiTests/src/com/android/bidi/BiDiTestView.java b/tests/BiDiTests/src/com/android/bidi/BiDiTestView.java
index 76031a81d1ec..4f17e529eaae 100644
--- a/tests/BiDiTests/src/com/android/bidi/BiDiTestView.java
+++ b/tests/BiDiTests/src/com/android/bidi/BiDiTestView.java
@@ -50,6 +50,7 @@ public class BiDiTestView extends View {
private String ARABIC_TEXT;
private String CHINESE_TEXT;
private String MIXED_TEXT_1;
+ private String HEBREW_TEXT;
private Typeface typeface;
@@ -81,6 +82,7 @@ public class BiDiTestView extends View {
ARABIC_TEXT = context.getString(R.string.arabic_text);
CHINESE_TEXT = context.getString(R.string.chinese_text);
MIXED_TEXT_1 = context.getString(R.string.mixed_text_1);
+ HEBREW_TEXT = context.getString(R.string.hebrew_text);
typeface = paint.getTypeface();
paint.setAntiAlias(true);
@@ -95,7 +97,9 @@ public class BiDiTestView extends View {
public void onDraw(Canvas canvas) {
drawInsideRect(canvas, Color.BLACK);
- int deltaX = testString(canvas, NORMAL_TEXT, ORIGIN, ORIGIN,
+ int deltaX = 0;
+
+ deltaX = testString(canvas, NORMAL_TEXT, ORIGIN, ORIGIN,
paint, typeface, false, false, Paint.DIRECTION_LTR, currentTextSize);
deltaX += testString(canvas, ITALIC_TEXT, ORIGIN + deltaX, ORIGIN,
@@ -130,6 +134,10 @@ public class BiDiTestView extends View {
// Test Mixed (English and Arabic)
deltaX = testString(canvas, MIXED_TEXT_1, ORIGIN, ORIGIN + 12 * currentTextSize,
paint, typeface, false, false, Paint.DIRECTION_LTR, currentTextSize);
+
+ // Test Hebrew
+ deltaX = testString(canvas, HEBREW_TEXT, ORIGIN, ORIGIN + 14 * currentTextSize,
+ paint, typeface, false, false, Paint.DIRECTION_RTL, currentTextSize);
}
private int testString(Canvas canvas, String text, int x, int y, Paint paint, Typeface typeface,