Merge "Add support for WV plugin"
diff --git a/api/current.xml b/api/current.xml
index 8d8e96f..7360913 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -1255,6 +1255,17 @@
visibility="public"
>
</field>
+<field name="WRITE_MEDIA_STORAGE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""android.permission.WRITE_MEDIA_STORAGE""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="WRITE_SECURE_SETTINGS"
type="java.lang.String"
transient="false"
@@ -1894,7 +1905,7 @@
type="int"
transient="false"
volatile="false"
- value="16843549"
+ value="16843550"
static="true"
final="true"
deprecated="not deprecated"
@@ -1905,7 +1916,7 @@
type="int"
transient="false"
volatile="false"
- value="16843548"
+ value="16843549"
static="true"
final="true"
deprecated="not deprecated"
@@ -1916,7 +1927,7 @@
type="int"
transient="false"
volatile="false"
- value="16843550"
+ value="16843551"
static="true"
final="true"
deprecated="not deprecated"
@@ -4717,6 +4728,17 @@
visibility="public"
>
</field>
+<field name="homeAsUpIndicator"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843548"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="horizontalDivider"
type="int"
transient="false"
@@ -9282,6 +9304,28 @@
visibility="public"
>
</field>
+<field name="textEditNoPasteWindowLayout"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843553"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="textEditPasteWindowLayout"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843552"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="textFilterEnabled"
type="int"
transient="false"
@@ -19427,6 +19471,17 @@
visibility="public"
>
</method>
+<method name="getNavigationItemCount"
+ return="int"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="getNavigationMode"
return="int"
abstract="true"
@@ -19438,6 +19493,17 @@
visibility="public"
>
</method>
+<method name="getSelectedNavigationIndex"
+ return="int"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="getSelectedNavigationItem"
return="int"
abstract="true"
@@ -19445,7 +19511,7 @@
synchronized="false"
static="false"
final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
visibility="public"
>
</method>
@@ -19471,6 +19537,19 @@
visibility="public"
>
</method>
+<method name="getTabAt"
+ return="android.app.ActionBar.Tab"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="index" type="int">
+</parameter>
+</method>
<method name="getTitle"
return="java.lang.CharSequence"
abstract="true"
@@ -19515,6 +19594,17 @@
visibility="public"
>
</method>
+<method name="removeAllTabs"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="removeTab"
return="void"
abstract="true"
@@ -19574,12 +19664,40 @@
synchronized="false"
static="false"
final="false"
+ deprecated="deprecated"
+ visibility="public"
+>
+<parameter name="view" type="android.view.View">
+</parameter>
+</method>
+<method name="setCustomView"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
deprecated="not deprecated"
visibility="public"
>
<parameter name="view" type="android.view.View">
</parameter>
</method>
+<method name="setCustomView"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="view" type="android.view.View">
+</parameter>
+<parameter name="layoutParams" type="android.app.ActionBar.LayoutParams">
+</parameter>
+</method>
<method name="setDisplayOptions"
return="void"
abstract="true"
@@ -19615,7 +19733,7 @@
synchronized="false"
static="false"
final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
visibility="public"
>
<parameter name="adapter" type="android.widget.SpinnerAdapter">
@@ -19630,7 +19748,7 @@
synchronized="false"
static="false"
final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
visibility="public"
>
<parameter name="adapter" type="android.widget.SpinnerAdapter">
@@ -19640,6 +19758,34 @@
<parameter name="defaultSelectedPosition" type="int">
</parameter>
</method>
+<method name="setListNavigationCallbacks"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="adapter" type="android.widget.SpinnerAdapter">
+</parameter>
+<parameter name="callback" type="android.app.ActionBar.NavigationCallback">
+</parameter>
+</method>
+<method name="setNavigationMode"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="mode" type="int">
+</parameter>
+</method>
<method name="setSelectedNavigationItem"
return="void"
abstract="true"
@@ -19660,7 +19806,7 @@
synchronized="false"
static="false"
final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
visibility="public"
>
</method>
@@ -19697,7 +19843,7 @@
synchronized="false"
static="false"
final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
visibility="public"
>
</method>
@@ -19742,6 +19888,39 @@
type="int"
transient="false"
volatile="false"
+ value="4096"
+ static="true"
+ final="true"
+ deprecated="deprecated"
+ visibility="public"
+>
+</field>
+<field name="DISPLAY_HOME_AS_UP"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="DISPLAY_SHOW_CUSTOM"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="DISPLAY_SHOW_HOME"
+ type="int"
+ transient="false"
+ volatile="false"
value="2"
static="true"
final="true"
@@ -19749,6 +19928,17 @@
visibility="public"
>
</field>
+<field name="DISPLAY_SHOW_TITLE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="8"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="DISPLAY_USE_LOGO"
type="int"
transient="false"
@@ -19760,18 +19950,18 @@
visibility="public"
>
</field>
-<field name="NAVIGATION_MODE_CUSTOM"
+<field name="NAVIGATION_MODE_DROPDOWN_LIST"
type="int"
transient="false"
volatile="false"
- value="3"
+ value="1"
static="true"
final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
visibility="public"
>
</field>
-<field name="NAVIGATION_MODE_DROPDOWN_LIST"
+<field name="NAVIGATION_MODE_LIST"
type="int"
transient="false"
volatile="false"
@@ -19805,6 +19995,93 @@
>
</field>
</class>
+<class name="ActionBar.LayoutParams"
+ extends="android.view.ViewGroup.MarginLayoutParams"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="ActionBar.LayoutParams"
+ type="android.app.ActionBar.LayoutParams"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="c" type="android.content.Context">
+</parameter>
+<parameter name="attrs" type="android.util.AttributeSet">
+</parameter>
+</constructor>
+<constructor name="ActionBar.LayoutParams"
+ type="android.app.ActionBar.LayoutParams"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="width" type="int">
+</parameter>
+<parameter name="height" type="int">
+</parameter>
+</constructor>
+<constructor name="ActionBar.LayoutParams"
+ type="android.app.ActionBar.LayoutParams"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="width" type="int">
+</parameter>
+<parameter name="height" type="int">
+</parameter>
+<parameter name="gravity" type="int">
+</parameter>
+</constructor>
+<constructor name="ActionBar.LayoutParams"
+ type="android.app.ActionBar.LayoutParams"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="gravity" type="int">
+</parameter>
+</constructor>
+<constructor name="ActionBar.LayoutParams"
+ type="android.app.ActionBar.LayoutParams"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="source" type="android.app.ActionBar.LayoutParams">
+</parameter>
+</constructor>
+<constructor name="ActionBar.LayoutParams"
+ type="android.app.ActionBar.LayoutParams"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="source" type="android.view.ViewGroup.LayoutParams">
+</parameter>
+</constructor>
+<field name="gravity"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
<interface name="ActionBar.NavigationCallback"
abstract="true"
static="true"
@@ -19911,7 +20188,7 @@
>
</method>
<method name="setCustomView"
- return="void"
+ return="android.app.ActionBar.Tab"
abstract="true"
native="false"
synchronized="false"
@@ -19924,7 +20201,7 @@
</parameter>
</method>
<method name="setIcon"
- return="void"
+ return="android.app.ActionBar.Tab"
abstract="true"
native="false"
synchronized="false"
@@ -19937,7 +20214,7 @@
</parameter>
</method>
<method name="setTabListener"
- return="void"
+ return="android.app.ActionBar.Tab"
abstract="true"
native="false"
synchronized="false"
@@ -19950,7 +20227,7 @@
</parameter>
</method>
<method name="setTag"
- return="void"
+ return="android.app.ActionBar.Tab"
abstract="true"
native="false"
synchronized="false"
@@ -19963,7 +20240,7 @@
</parameter>
</method>
<method name="setText"
- return="void"
+ return="android.app.ActionBar.Tab"
abstract="true"
native="false"
synchronized="false"
@@ -245105,7 +245382,7 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="arg0" type="T">
+<parameter name="t" type="T">
</parameter>
</method>
</interface>
diff --git a/core/java/android/app/ActionBar.java b/core/java/android/app/ActionBar.java
index 7df9295..66038d8 100644
--- a/core/java/android/app/ActionBar.java
+++ b/core/java/android/app/ActionBar.java
@@ -16,8 +16,16 @@
package android.app;
+import android.app.ActionBar.Tab;
+import android.content.Context;
+import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.view.Gravity;
import android.view.View;
+import android.view.ViewDebug;
+import android.view.ViewGroup;
+import android.view.ViewGroup.MarginLayoutParams;
import android.view.Window;
import android.widget.SpinnerAdapter;
@@ -37,9 +45,16 @@
public static final int NAVIGATION_MODE_STANDARD = 0;
/**
- * Dropdown list navigation mode. Instead of static title text this mode
- * presents a dropdown menu for navigation within the activity.
+ * List navigation mode. Instead of static title text this mode
+ * presents a list menu for navigation within the activity.
+ * e.g. this might be presented to the user as a dropdown list.
*/
+ public static final int NAVIGATION_MODE_LIST = 1;
+
+ /**
+ * @deprecated use NAVIGATION_MODE_LIST
+ */
+ @Deprecated
public static final int NAVIGATION_MODE_DROPDOWN_LIST = 1;
/**
@@ -47,24 +62,77 @@
* presents a series of tabs for navigation within the activity.
*/
public static final int NAVIGATION_MODE_TABS = 2;
-
- /**
- * Custom navigation mode. This navigation mode is set implicitly whenever
- * a custom navigation view is set. See {@link #setCustomNavigationMode(View)}.
- */
- public static final int NAVIGATION_MODE_CUSTOM = 3;
/**
* Use logo instead of icon if available. This flag will cause appropriate
* navigation modes to use a wider logo in place of the standard icon.
+ *
+ * @see #setDisplayOptions(int)
+ * @see #setDisplayOptions(int, int)
*/
public static final int DISPLAY_USE_LOGO = 0x1;
/**
- * Hide 'home' elements in this action bar, leaving more space for other
+ * Show 'home' elements in this action bar, leaving more space for other
* navigation elements. This includes logo and icon.
+ *
+ * @see #setDisplayOptions(int)
+ * @see #setDisplayOptions(int, int)
*/
- public static final int DISPLAY_HIDE_HOME = 0x2;
+ public static final int DISPLAY_SHOW_HOME = 0x2;
+
+ /**
+ * @deprecated Display flags are now positive for consistency - 'show' instead of 'hide'.
+ * Use DISPLAY_SHOW_HOME.
+ */
+ @Deprecated
+ public static final int DISPLAY_HIDE_HOME = 0x1000;
+
+ /**
+ * Display the 'home' element such that it appears as an 'up' affordance.
+ * e.g. show an arrow to the left indicating the action that will be taken.
+ *
+ * Set this flag if selecting the 'home' button in the action bar to return
+ * up by a single level in your UI rather than back to the top level or front page.
+ *
+ * @see #setDisplayOptions(int)
+ * @see #setDisplayOptions(int, int)
+ */
+ public static final int DISPLAY_HOME_AS_UP = 0x4;
+
+ /**
+ * Show the activity title and subtitle, if present.
+ *
+ * @see #setTitle(CharSequence)
+ * @see #setTitle(int)
+ * @see #setSubtitle(CharSequence)
+ * @see #setSubtitle(int)
+ * @see #setDisplayOptions(int)
+ * @see #setDisplayOptions(int, int)
+ */
+ public static final int DISPLAY_SHOW_TITLE = 0x8;
+
+ /**
+ * Show the custom view if one has been set.
+ * @see #setCustomView(View)
+ * @see #setDisplayOptions(int)
+ * @see #setDisplayOptions(int, int)
+ */
+ public static final int DISPLAY_SHOW_CUSTOM = 0x10;
+
+ /**
+ * Set the action bar into custom navigation mode, supplying a view
+ * for custom navigation.
+ *
+ * Custom navigation views appear between the application icon and
+ * any action buttons and may use any space available there. Common
+ * use cases for custom navigation views might include an auto-suggesting
+ * address bar for a browser or other navigation mechanisms that do not
+ * translate well to provided navigation modes.
+ *
+ * @param view Custom navigation view to place in the ActionBar.
+ */
+ public abstract void setCustomView(View view);
/**
* Set the action bar into custom navigation mode, supplying a view
@@ -77,7 +145,15 @@
* translate well to provided navigation modes.
*
* @param view Custom navigation view to place in the ActionBar.
+ * @param layoutParams How this custom view should layout in the bar.
*/
+ public abstract void setCustomView(View view, LayoutParams layoutParams);
+
+ /**
+ * @param view
+ * @deprecated Use {@link #setCustomView(View)} and {@link #setDisplayOptions(int)} instead.
+ */
+ @Deprecated
public abstract void setCustomNavigationMode(View view);
/**
@@ -89,11 +165,31 @@
* within the dropdown navigation menu.
* @param callback A NavigationCallback that will receive events when the user
* selects a navigation item.
+ * @deprecated See setListNavigationCallbacks.
*/
+ @Deprecated
public abstract void setDropdownNavigationMode(SpinnerAdapter adapter,
NavigationCallback callback);
/**
+ * Set the adapter and navigation callback for list navigation mode.
+ *
+ * The supplied adapter will provide views for the expanded list as well as
+ * the currently selected item. (These may be displayed differently.)
+ *
+ * The supplied NavigationCallback will alert the application when the user
+ * changes the current list selection.
+ *
+ * @param adapter An adapter that will provide views both to display
+ * the current navigation selection and populate views
+ * within the dropdown navigation menu.
+ * @param callback A NavigationCallback that will receive events when the user
+ * selects a navigation item.
+ */
+ public abstract void setListNavigationCallbacks(SpinnerAdapter adapter,
+ NavigationCallback callback);
+
+ /**
* Set the action bar into dropdown navigation mode and supply an adapter that will
* provide views for navigation choices.
*
@@ -104,23 +200,41 @@
* selects a navigation item.
* @param defaultSelectedPosition Position within the provided adapter that should be
* selected from the outset.
+ * @deprecated See setListNavigationCallbacks and setSelectedNavigationItem.
*/
+ @Deprecated
public abstract void setDropdownNavigationMode(SpinnerAdapter adapter,
NavigationCallback callback, int defaultSelectedPosition);
/**
- * Set the selected navigation item in dropdown or tabbed navigation modes.
+ * Set the selected navigation item in list or tabbed navigation modes.
*
* @param position Position of the item to select.
*/
public abstract void setSelectedNavigationItem(int position);
/**
- * Get the position of the selected navigation item in dropdown or tabbed navigation modes.
+ * Get the position of the selected navigation item in list or tabbed navigation modes.
+ *
+ * @return Position of the selected item.
+ * @deprecated Use {@link #getSelectedNavigationIndex()} instead.
+ */
+ @Deprecated
+ public abstract int getSelectedNavigationItem();
+
+ /**
+ * Get the position of the selected navigation item in list or tabbed navigation modes.
*
* @return Position of the selected item.
*/
- public abstract int getSelectedNavigationItem();
+ public abstract int getSelectedNavigationIndex();
+
+ /**
+ * Get the number of navigation items present in the current navigation mode.
+ *
+ * @return Number of navigation items.
+ */
+ public abstract int getNavigationItemCount();
/**
* Set the action bar into standard navigation mode, using the currently set title
@@ -128,7 +242,9 @@
*
* Standard navigation mode is default. The title is automatically set to the name of
* your Activity on startup if an action bar is present.
+ * @deprecated See setNavigationMode
*/
+ @Deprecated
public abstract void setStandardNavigationMode();
/**
@@ -181,10 +297,10 @@
* Set selected display options. Only the options specified by mask will be changed.
* To change all display option bits at once, see {@link #setDisplayOptions(int)}.
*
- * <p>Example: setDisplayOptions(0, DISPLAY_HIDE_HOME) will disable the
- * {@link #DISPLAY_HIDE_HOME} option.
- * setDisplayOptions(DISPLAY_HIDE_HOME, DISPLAY_HIDE_HOME | DISPLAY_USE_LOGO)
- * will enable {@link #DISPLAY_HIDE_HOME} and disable {@link #DISPLAY_USE_LOGO}.
+ * <p>Example: setDisplayOptions(0, DISPLAY_SHOW_HOME) will disable the
+ * {@link #DISPLAY_SHOW_HOME} option.
+ * setDisplayOptions(DISPLAY_SHOW_HOME, DISPLAY_HIDE_HOME | DISPLAY_USE_LOGO)
+ * will enable {@link #DISPLAY_SHOW_HOME} and disable {@link #DISPLAY_USE_LOGO}.
*
* @param options A combination of the bits defined by the DISPLAY_ constants
* defined in ActionBar.
@@ -226,9 +342,8 @@
* Returns the current navigation mode. The result will be one of:
* <ul>
* <li>{@link #NAVIGATION_MODE_STANDARD}</li>
- * <li>{@link #NAVIGATION_MODE_DROPDOWN_LIST}</li>
+ * <li>{@link #NAVIGATION_MODE_LIST}</li>
* <li>{@link #NAVIGATION_MODE_TABS}</li>
- * <li>{@link #NAVIGATION_MODE_CUSTOM}</li>
* </ul>
*
* @return The current navigation mode.
@@ -241,7 +356,17 @@
* @see #setCustomNavigationMode(View)
*/
public abstract int getNavigationMode();
-
+
+ /**
+ * Set the current navigation mode.
+ *
+ * @param mode The new mode to set.
+ * @see #NAVIGATION_MODE_STANDARD
+ * @see #NAVIGATION_MODE_LIST
+ * @see #NAVIGATION_MODE_TABS
+ */
+ public abstract void setNavigationMode(int mode);
+
/**
* @return The current set of display options.
*/
@@ -254,6 +379,8 @@
* @see #insertTab(Tab, int)
* @see #removeTab(Tab)
* @see #removeTabAt(int)
+ *
+ * @deprecated See {@link #setNavigationMode(int)}
*/
public abstract void setTabNavigationMode();
@@ -285,22 +412,31 @@
public abstract void addTab(Tab tab, int position);
/**
- * Remove a tab from the action bar.
+ * Remove a tab from the action bar. If the removed tab was selected it will be deselected
+ * and another tab will be selected if present.
*
* @param tab The tab to remove
*/
public abstract void removeTab(Tab tab);
/**
- * Remove a tab from the action bar.
+ * Remove a tab from the action bar. If the removed tab was selected it will be deselected
+ * and another tab will be selected if present.
*
* @param position Position of the tab to remove
*/
public abstract void removeTabAt(int position);
/**
+ * Remove all tabs from the action bar and deselect the current tab.
+ */
+ public abstract void removeAllTabs();
+
+ /**
* Select the specified tab. If it is not a child of this action bar it will be added.
*
+ * <p>Note: If you want to select by index, use {@link #setSelectedNavigationItem(int)}.</p>
+ *
* @param tab Tab to select
*/
public abstract void selectTab(Tab tab);
@@ -314,6 +450,14 @@
public abstract Tab getSelectedTab();
/**
+ * Returns the tab at the specified index.
+ *
+ * @param index Index value in the range 0-get
+ * @return
+ */
+ public abstract Tab getTabAt(int index);
+
+ /**
* Retrieve the current height of the ActionBar.
*
* @return The ActionBar's height
@@ -395,24 +539,27 @@
* Set the icon displayed on this tab.
*
* @param icon The drawable to use as an icon
+ * @return The current instance for call chaining
*/
- public abstract void setIcon(Drawable icon);
+ public abstract Tab setIcon(Drawable icon);
/**
* Set the text displayed on this tab. Text may be truncated if there is not
* room to display the entire string.
*
* @param text The text to display
+ * @return The current instance for call chaining
*/
- public abstract void setText(CharSequence text);
+ public abstract Tab setText(CharSequence text);
/**
* Set a custom view to be used for this tab. This overrides values set by
* {@link #setText(CharSequence)} and {@link #setIcon(Drawable)}.
*
* @param view Custom view to be used as a tab.
+ * @return The current instance for call chaining
*/
- public abstract void setCustomView(View view);
+ public abstract Tab setCustomView(View view);
/**
* Retrieve a previously set custom view for this tab.
@@ -425,8 +572,9 @@
* Give this Tab an arbitrary object to hold for later use.
*
* @param obj Object to store
+ * @return The current instance for call chaining
*/
- public abstract void setTag(Object obj);
+ public abstract Tab setTag(Object obj);
/**
* @return This Tab's tag object.
@@ -438,8 +586,9 @@
* All tabs must have a TabListener set before being added to the ActionBar.
*
* @param listener Listener to handle tab selection events
+ * @return The current instance for call chaining
*/
- public abstract void setTabListener(TabListener listener);
+ public abstract Tab setTabListener(TabListener listener);
/**
* Select this tab. Only valid if the tab has been added to the action bar.
@@ -481,4 +630,65 @@
*/
public void onTabReselected(Tab tab, FragmentTransaction ft);
}
+
+ /**
+ * Per-child layout information associated with action bar custom views.
+ *
+ * @attr ref android.R.styleable#ActionBar_LayoutParams_layout_gravity
+ */
+ public static class LayoutParams extends MarginLayoutParams {
+ /**
+ * Gravity for the view associated with these LayoutParams.
+ *
+ * @see android.view.Gravity
+ */
+ @ViewDebug.ExportedProperty(category = "layout", mapping = {
+ @ViewDebug.IntToString(from = -1, to = "NONE"),
+ @ViewDebug.IntToString(from = Gravity.NO_GRAVITY, to = "NONE"),
+ @ViewDebug.IntToString(from = Gravity.TOP, to = "TOP"),
+ @ViewDebug.IntToString(from = Gravity.BOTTOM, to = "BOTTOM"),
+ @ViewDebug.IntToString(from = Gravity.LEFT, to = "LEFT"),
+ @ViewDebug.IntToString(from = Gravity.RIGHT, to = "RIGHT"),
+ @ViewDebug.IntToString(from = Gravity.CENTER_VERTICAL, to = "CENTER_VERTICAL"),
+ @ViewDebug.IntToString(from = Gravity.FILL_VERTICAL, to = "FILL_VERTICAL"),
+ @ViewDebug.IntToString(from = Gravity.CENTER_HORIZONTAL, to = "CENTER_HORIZONTAL"),
+ @ViewDebug.IntToString(from = Gravity.FILL_HORIZONTAL, to = "FILL_HORIZONTAL"),
+ @ViewDebug.IntToString(from = Gravity.CENTER, to = "CENTER"),
+ @ViewDebug.IntToString(from = Gravity.FILL, to = "FILL")
+ })
+ public int gravity = -1;
+
+ public LayoutParams(Context c, AttributeSet attrs) {
+ super(c, attrs);
+
+ TypedArray a = c.obtainStyledAttributes(attrs,
+ com.android.internal.R.styleable.ActionBar_LayoutParams);
+ gravity = a.getInt(
+ com.android.internal.R.styleable.ActionBar_LayoutParams_layout_gravity, -1);
+ }
+
+ public LayoutParams(int width, int height) {
+ super(width, height);
+ this.gravity = Gravity.CENTER_VERTICAL | Gravity.LEFT;
+ }
+
+ public LayoutParams(int width, int height, int gravity) {
+ super(width, height);
+ this.gravity = gravity;
+ }
+
+ public LayoutParams(int gravity) {
+ this(WRAP_CONTENT, MATCH_PARENT, gravity);
+ }
+
+ public LayoutParams(LayoutParams source) {
+ super(source);
+
+ this.gravity = source.gravity;
+ }
+
+ public LayoutParams(ViewGroup.LayoutParams source) {
+ super(source);
+ }
+ }
}
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 7315f01..47efddb 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -1781,6 +1781,17 @@
performNewIntents(data.token, data.intents);
}
+ private static final ThreadLocal<Intent> sCurrentBroadcastIntent = new ThreadLocal<Intent>();
+
+ /**
+ * Return the Intent that's currently being handled by a
+ * BroadcastReceiver on this thread, or null if none.
+ * @hide
+ */
+ public static Intent getIntentBeingBroadcast() {
+ return sCurrentBroadcastIntent.get();
+ }
+
private final void handleReceiver(ReceiverData data) {
// If we are getting ready to gc after going to the background, well
// we are back active so skip it.
@@ -1820,6 +1831,7 @@
+ ", dir=" + packageInfo.getAppDir());
ContextImpl context = (ContextImpl)app.getBaseContext();
+ sCurrentBroadcastIntent.set(data.intent);
receiver.setPendingResult(data);
receiver.onReceive(context.getReceiverRestrictedContext(),
data.intent);
@@ -1832,6 +1844,8 @@
"Unable to start receiver " + component
+ ": " + e.toString(), e);
}
+ } finally {
+ sCurrentBroadcastIntent.set(null);
}
if (receiver.getPendingResult() != null) {
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index a29acf1..5ce4cd6 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -265,7 +265,11 @@
public Resources.Theme getTheme() {
if (mTheme == null) {
if (mThemeResource == 0) {
- mThemeResource = com.android.internal.R.style.Theme;
+ final Context outerContext = getOuterContext();
+ mThemeResource = (outerContext.getApplicationInfo().targetSdkVersion
+ >= Build.VERSION_CODES.HONEYCOMB)
+ ? com.android.internal.R.style.Theme_Holo
+ : com.android.internal.R.style.Theme;
}
mTheme = mResources.newTheme();
mTheme.applyStyle(mThemeResource, true);
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index c66b2de..556fb10 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -738,6 +738,27 @@
}
/**
+ * Get the current connection state of the local Bluetooth adapter.
+ * This can be used to check whether the local Bluetooth adapter is connected
+ * to any profile of any other remote Bluetooth Device.
+ *
+ * <p> Use this function along with {@link #ACTION_CONNECTION_STATE_CHANGED}
+ * intent to get the connection state of the adapter.
+ *
+ * @return One of {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTED},
+ * {@link #STATE_CONNECTING} or {@link #STATE_DISCONNECTED}
+ *
+ * @hide
+ */
+ public int getConnectionState() {
+ if (getState() != STATE_ON) return BluetoothAdapter.STATE_DISCONNECTED;
+ try {
+ return mService.getAdapterConnectionState();
+ } catch (RemoteException e) {Log.e(TAG, "getConnectionState:", e);}
+ return BluetoothAdapter.STATE_DISCONNECTED;
+ }
+
+ /**
* Picks RFCOMM channels until none are left.
* Avoids reserved channels.
*/
@@ -879,6 +900,7 @@
return socket;
}
+
/**
* Construct an unencrypted, unauthenticated, RFCOMM server socket.
* Call #accept to retrieve connections to this socket.
diff --git a/core/java/android/bluetooth/IBluetooth.aidl b/core/java/android/bluetooth/IBluetooth.aidl
index 1eb269d..aefb3f2 100644
--- a/core/java/android/bluetooth/IBluetooth.aidl
+++ b/core/java/android/bluetooth/IBluetooth.aidl
@@ -47,6 +47,8 @@
boolean isDiscovering();
byte[] readOutOfBandData();
+ int getAdapterConnectionState();
+
boolean createBond(in String address);
boolean createBondOutOfBand(in String address, in byte[] hash, in byte[] randomizer);
boolean cancelBondProcess(in String address);
diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java
index 73d9458..e279f64 100644
--- a/core/java/android/content/res/AssetManager.java
+++ b/core/java/android/content/res/AssetManager.java
@@ -149,7 +149,7 @@
/*package*/ final CharSequence getResourceText(int ident) {
synchronized (this) {
TypedValue tmpValue = mValue;
- int block = loadResourceValue(ident, tmpValue, true);
+ int block = loadResourceValue(ident, (short) 0, tmpValue, true);
if (block >= 0) {
if (tmpValue.type == TypedValue.TYPE_STRING) {
return mStringBlocks[block].get(tmpValue.data);
@@ -190,10 +190,11 @@
/*package*/ final boolean getResourceValue(int ident,
+ int density,
TypedValue outValue,
boolean resolveRefs)
{
- int block = loadResourceValue(ident, outValue, resolveRefs);
+ int block = loadResourceValue(ident, (short) density, outValue, resolveRefs);
if (block >= 0) {
if (outValue.type != TypedValue.TYPE_STRING) {
return true;
@@ -681,8 +682,8 @@
/** Returns true if the resource was found, filling in mRetStringBlock and
* mRetData. */
- private native final int loadResourceValue(int ident, TypedValue outValue,
- boolean resolve);
+ private native final int loadResourceValue(int ident, short density, TypedValue outValue,
+ boolean resolve);
/** Returns true if the resource was found, filling in mRetStringBlock and
* mRetData. */
private native final int loadResourceBagValue(int ident, int bagEntryId, TypedValue outValue,
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index 9b23c1e..e6fd039 100755
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -628,6 +628,50 @@
}
/**
+ * Return a drawable object associated with a particular resource ID for the
+ * given screen density in DPI. This will set the drawable's density to be
+ * the device's density multiplied by the ratio of actual drawable density
+ * to requested density. This allows the drawable to be scaled up to the
+ * correct size if needed. Various types of objects will be returned
+ * depending on the underlying resource -- for example, a solid color, PNG
+ * image, scalable image, etc. The Drawable API hides these implementation
+ * details.
+ *
+ * @param id The desired resource identifier, as generated by the aapt tool.
+ * This integer encodes the package, type, and resource entry.
+ * The value 0 is an invalid identifier.
+ * @param density the desired screen density indicated by the resource as
+ * found in {@link DisplayMetrics}.
+ * @throws NotFoundException Throws NotFoundException if the given ID does
+ * not exist.
+ * @return Drawable An object that can be used to draw this resource.
+ * @hide
+ */
+ public Drawable getDrawableForDensity(int id, int density) throws NotFoundException {
+ synchronized (mTmpValue) {
+ TypedValue value = mTmpValue;
+ getValueForDensity(id, density, value, true);
+
+ /*
+ * Pretend the requested density is actually the display density. If
+ * the drawable returned is not the requested density, then force it
+ * to be scaled later by dividing its density by the ratio of
+ * requested density to actual device density. Drawables that have
+ * undefined density or no density don't need to be handled here.
+ */
+ if (value.density > 0 && value.density != TypedValue.DENSITY_NONE) {
+ if (value.density == density) {
+ value.density = DisplayMetrics.DENSITY_DEVICE;
+ } else {
+ value.density = (value.density * DisplayMetrics.DENSITY_DEVICE) / density;
+ }
+ }
+
+ return loadDrawable(value, id);
+ }
+ }
+
+ /**
* Return a movie object associated with the particular resource ID.
* @param id The desired resource identifier, as generated by the aapt
* tool. This integer encodes the package, type, and resource
@@ -930,7 +974,7 @@
*/
public void getValue(int id, TypedValue outValue, boolean resolveRefs)
throws NotFoundException {
- boolean found = mAssets.getResourceValue(id, outValue, resolveRefs);
+ boolean found = mAssets.getResourceValue(id, 0, outValue, resolveRefs);
if (found) {
return;
}
@@ -939,6 +983,29 @@
}
/**
+ * Get the raw value associated with a resource with associated density.
+ *
+ * @param id resource identifier
+ * @param density density in DPI
+ * @param resolveRefs If true, a resource that is a reference to another
+ * resource will be followed so that you receive the actual final
+ * resource data. If false, the TypedValue will be filled in with
+ * the reference itself.
+ * @throws NotFoundException Throws NotFoundException if the given ID does
+ * not exist.
+ * @see #getValue(String, TypedValue, boolean)
+ * @hide
+ */
+ public void getValueForDensity(int id, int density, TypedValue outValue, boolean resolveRefs)
+ throws NotFoundException {
+ boolean found = mAssets.getResourceValue(id, density, outValue, resolveRefs);
+ if (found) {
+ return;
+ }
+ throw new NotFoundException("Resource ID #0x" + Integer.toHexString(id));
+ }
+
+ /**
* Return the raw data associated with a particular resource ID.
* See getIdentifier() for information on how names are mapped to resource
* IDs, and getString(int) for information on how string resources are
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index 6089013..c0743cfe 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -1296,7 +1296,7 @@
mInShowWindow = false;
}
}
-
+
void showWindowInner(boolean showInput) {
boolean doShowInput = false;
boolean wasVisible = mWindowVisible;
@@ -1311,7 +1311,7 @@
} else {
showInput = true;
}
-
+
if (DEBUG) Log.v(TAG, "showWindow: updating UI");
initialize();
updateFullscreenMode();
@@ -1343,14 +1343,15 @@
if (doShowInput) {
startExtractingText(false);
}
-
+
if (!wasVisible) {
if (DEBUG) Log.v(TAG, "showWindow: showing!");
+ mImm.setIMEButtonVisible(mToken, true);
onWindowShown();
mWindow.show();
}
}
-
+
public void hideWindow() {
if (mInputViewStarted) {
if (DEBUG) Log.v(TAG, "CALL: onFinishInputView");
@@ -1364,11 +1365,12 @@
if (mWindowVisible) {
mWindow.hide();
mWindowVisible = false;
+ mImm.setIMEButtonVisible(mToken, false);
onWindowHidden();
mWindowWasVisible = false;
}
}
-
+
/**
* Called when the input method window has been shown to the user, after
* previously not being visible. This is done after all of the UI setup
diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java
index 5a6369c..34d3b85 100644
--- a/core/java/android/os/StrictMode.java
+++ b/core/java/android/os/StrictMode.java
@@ -17,7 +17,9 @@
import android.animation.ValueAnimator;
import android.app.ActivityManagerNative;
+import android.app.ActivityThread;
import android.app.ApplicationErrorReport;
+import android.content.Intent;
import android.util.Log;
import android.util.Printer;
@@ -1205,6 +1207,12 @@
public long violationUptimeMillis;
/**
+ * The action of the Intent being broadcast to somebody's onReceive
+ * on this thread right now, or null.
+ */
+ public String broadcastIntentAction;
+
+ /**
* Create an uninitialized instance of ViolationInfo
*/
public ViolationInfo() {
@@ -1220,6 +1228,10 @@
violationUptimeMillis = SystemClock.uptimeMillis();
this.policy = policy;
this.numAnimationsRunning = ValueAnimator.getCurrentAnimationsCount();
+ Intent broadcastIntent = ActivityThread.getIntentBeingBroadcast();
+ if (broadcastIntent != null) {
+ broadcastIntentAction = broadcastIntent.getAction();
+ }
}
/**
@@ -1247,6 +1259,7 @@
violationNumThisLoop = in.readInt();
numAnimationsRunning = in.readInt();
violationUptimeMillis = in.readLong();
+ broadcastIntentAction = in.readString();
}
/**
@@ -1259,6 +1272,7 @@
dest.writeInt(violationNumThisLoop);
dest.writeInt(numAnimationsRunning);
dest.writeLong(violationUptimeMillis);
+ dest.writeString(broadcastIntentAction);
}
@@ -1278,6 +1292,9 @@
pw.println(prefix + "numAnimationsRunning: " + numAnimationsRunning);
}
pw.println(prefix + "violationUptimeMillis: " + violationUptimeMillis);
+ if (broadcastIntentAction != null) {
+ pw.println(prefix + "broadcastIntentAction: " + broadcastIntentAction);
+ }
}
}
diff --git a/core/java/android/server/BluetoothService.java b/core/java/android/server/BluetoothService.java
index 65047c0..7289012 100644
--- a/core/java/android/server/BluetoothService.java
+++ b/core/java/android/server/BluetoothService.java
@@ -167,6 +167,8 @@
private static String mDockAddress;
private String mDockPin;
+ private int mAdapterConnectionState = BluetoothAdapter.STATE_DISCONNECTED;
+
private static class RemoteService {
public String address;
public ParcelUuid uuid;
@@ -415,6 +417,7 @@
mProfilesConnected = 0;
mProfilesConnecting = 0;
mProfilesDisconnecting = 0;
+ mAdapterConnectionState = BluetoothAdapter.STATE_DISCONNECTED;
if (saveSetting) {
persistBluetoothOnSetting(false);
@@ -2737,11 +2740,18 @@
}
}
+ public int getAdapterConnectionState() {
+ return mAdapterConnectionState;
+ }
+
public synchronized void sendConnectionStateChange(BluetoothDevice device, int state,
int prevState) {
if (updateCountersAndCheckForConnectionStateChange(device, state, prevState)) {
- state = getAdapterConnectionState(state);
- prevState = getAdapterConnectionState(prevState);
+ state = translateToAdapterConnectionState(state);
+ prevState = translateToAdapterConnectionState(prevState);
+
+ mAdapterConnectionState = state;
+
Intent intent = new Intent(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED);
intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
intent.putExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE, state);
@@ -2751,7 +2761,7 @@
}
}
- private int getAdapterConnectionState(int state) {
+ private int translateToAdapterConnectionState(int state) {
switch (state) {
case BluetoothProfile.STATE_CONNECTING:
return BluetoothAdapter.STATE_CONNECTING;
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 7cb6291..033ee7c 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -519,6 +519,15 @@
}
/** @hide */
+ public void setIMEButtonVisible(IBinder imeToken, boolean visible) {
+ try {
+ mService.setIMEButtonVisible(imeToken, visible);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /** @hide */
public void setFullscreenMode(boolean fullScreen) {
mFullscreenMode = fullScreen;
}
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
index 3d69249..4d582ef 100644
--- a/core/java/android/webkit/WebSettings.java
+++ b/core/java/android/webkit/WebSettings.java
@@ -1483,6 +1483,10 @@
return mAcceptLanguage;
}
+ /* package */ boolean isNarrowColumnLayout() {
+ return getLayoutAlgorithm() == LayoutAlgorithm.NARROW_COLUMNS;
+ }
+
/**
* Tell the WebView whether it needs to set a node to have focus when
* {@link WebView#requestFocus(int, android.graphics.Rect)} is called.
diff --git a/core/java/android/webkit/ZoomManager.java b/core/java/android/webkit/ZoomManager.java
index 86dfd1f..dd812d4 100644
--- a/core/java/android/webkit/ZoomManager.java
+++ b/core/java/android/webkit/ZoomManager.java
@@ -348,7 +348,8 @@
mZoomCenterY = mWebView.getViewHeight() * .5f;
mAnchorX = mWebView.viewToContentX((int) mZoomCenterX + mWebView.getScrollX());
mAnchorY = mWebView.viewToContentY((int) mZoomCenterY + mWebView.getScrollY());
- return startZoomAnimation(mActualScale * zoomMultiplier, true);
+ return startZoomAnimation(mActualScale * zoomMultiplier,
+ !mWebView.getSettings().getUseFixedViewport());
}
/**
@@ -460,7 +461,7 @@
mInZoomOverview = !exceedsMinScaleIncrement(scale, getZoomOverviewScale());
}
- if (reflowText) {
+ if (reflowText && !mWebView.getSettings().getUseFixedViewport()) {
mTextWrapScale = scale;
}
@@ -519,7 +520,7 @@
*
* (2) HTML/OTHER: If the taps occur outside a plugin then the following
* heuristic is used.
- * A. If the current scale is not the same as the text wrap scale and the
+ * A. If the current text wrap scale differs from newly calculated and the
* layout algorithm specifies the use of NARROW_COLUMNS, then fit to
* column by reflowing the text.
* B. If the page is not in overview mode then change to overview mode.
@@ -553,8 +554,15 @@
return;
}
- if (settings.getLayoutAlgorithm() == WebSettings.LayoutAlgorithm.NARROW_COLUMNS
- && willScaleTriggerZoom(mTextWrapScale)) {
+ final float newTextWrapScale;
+ if (settings.getUseFixedViewport()) {
+ newTextWrapScale = Math.max(mActualScale, getReadingLevelScale());
+ } else {
+ newTextWrapScale = mActualScale;
+ }
+ if (settings.isNarrowColumnLayout()
+ && exceedsMinScaleIncrement(mTextWrapScale, newTextWrapScale)) {
+ mTextWrapScale = newTextWrapScale;
refreshZoomScale(true);
} else if (!mInZoomOverview) {
zoomToOverview();
@@ -584,7 +592,8 @@
if (scrollY < mWebView.getTitleHeight()) {
mWebView.updateScrollCoordinates(mWebView.getScrollX(), 0);
}
- startZoomAnimation(getZoomOverviewScale(), true);
+ startZoomAnimation(getZoomOverviewScale(),
+ !mWebView.getSettings().getUseFixedViewport());
}
private void zoomToReadingLevel() {
@@ -603,7 +612,8 @@
mZoomCenterX = 0;
}
}
- startZoomAnimation(readingScale, true);
+ startZoomAnimation(readingScale,
+ !mWebView.getSettings().getUseFixedViewport());
}
public void updateMultiTouchSupport(Context context) {
@@ -683,11 +693,12 @@
mAnchorX = mWebView.viewToContentX((int) mZoomCenterX + mWebView.getScrollX());
mAnchorY = mWebView.viewToContentY((int) mZoomCenterY + mWebView.getScrollY());
// don't reflow when zoom in; when zoom out, do reflow if the
- // new scale is almost minimum scale;
+ // new scale is almost minimum scale.
boolean reflowNow = !canZoomOut() || (mActualScale <= 0.8 * mTextWrapScale);
// force zoom after mPreviewZoomOnly is set to false so that the
// new view size will be passed to the WebKit
- refreshZoomScale(reflowNow);
+ refreshZoomScale(reflowNow &&
+ !mWebView.getSettings().getUseFixedViewport());
// call invalidate() to draw without zoom filter
mWebView.invalidate();
}
@@ -730,7 +741,8 @@
// cause its child View to reposition itself through ViewManager's
// scaleAll(), we need to post a Runnable to ensure requestLayout().
// Additionally, only update the text wrap scale if the width changed.
- mWebView.post(new PostScale(w != ow));
+ mWebView.post(new PostScale(w != ow &&
+ !mWebView.getSettings().getUseFixedViewport()));
}
private class PostScale implements Runnable {
@@ -808,7 +820,8 @@
if (!mWebView.drawHistory() && (mInitialZoomOverview || (mInZoomOverview
&& Math.abs((viewWidth * mInvActualScale) - mZoomOverviewWidth) > 1))) {
mInitialZoomOverview = false;
- setZoomScale(zoomOverviewScale, !willScaleTriggerZoom(mTextWrapScale));
+ setZoomScale(zoomOverviewScale, !willScaleTriggerZoom(mTextWrapScale) &&
+ !mWebView.getSettings().getUseFixedViewport());
}
}
@@ -855,6 +868,11 @@
scale = Math.max(viewState.mTextWrapScale, scale);
mInitialZoomOverview = !exceedsMinScaleIncrement(scale, getZoomOverviewScale());
}
+ if (settings.isNarrowColumnLayout() && settings.getUseFixedViewport()) {
+ // When first layout, reflow using the reading level scale to avoid
+ // reflow when double tapped.
+ mTextWrapScale = getReadingLevelScale();
+ }
reflowText = exceedsMinScaleIncrement(mTextWrapScale, scale);
}
setZoomScale(scale, reflowText);
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 257dbf0..ef15f6f 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -300,6 +300,8 @@
int mTextSelectHandleLeftRes;
int mTextSelectHandleRightRes;
int mTextSelectHandleRes;
+ int mTextEditPasteWindowLayout;
+ int mTextEditNoPasteWindowLayout;
Drawable mSelectHandleLeft;
Drawable mSelectHandleRight;
@@ -737,7 +739,15 @@
case com.android.internal.R.styleable.TextView_textSelectHandle:
mTextSelectHandleRes = a.getResourceId(attr, 0);
break;
-
+
+ case com.android.internal.R.styleable.TextView_textEditPasteWindowLayout:
+ mTextEditPasteWindowLayout = a.getResourceId(attr, 0);
+ break;
+
+ case com.android.internal.R.styleable.TextView_textEditNoPasteWindowLayout:
+ mTextEditNoPasteWindowLayout = a.getResourceId(attr, 0);
+ break;
+
case com.android.internal.R.styleable.TextView_textLineHeight:
int lineHeight = a.getDimensionPixelSize(attr, 0);
if (lineHeight != 0) {
@@ -7736,6 +7746,34 @@
}
}
+ /**
+ * Paste clipboard content between min and max positions.
+ *
+ * @param clipboard getSystemService(Context.CLIPBOARD_SERVICE)
+ */
+ private void paste(ClipboardManager clipboard, int min, int max) {
+ ClipData clip = clipboard.getPrimaryClip();
+ if (clip != null) {
+ boolean didfirst = false;
+ for (int i=0; i<clip.getItemCount(); i++) {
+ CharSequence paste = clip.getItem(i).coerceToText(getContext());
+ if (paste != null) {
+ if (!didfirst) {
+ long minMax = prepareSpacesAroundPaste(min, max, paste);
+ min = extractRangeStartFromLong(minMax);
+ max = extractRangeEndFromLong(minMax);
+ Selection.setSelection((Spannable) mText, max);
+ ((Editable) mText).replace(min, max, paste);
+ } else {
+ ((Editable) mText).insert(getSelectionEnd(), "\n");
+ ((Editable) mText).insert(getSelectionEnd(), paste);
+ }
+ }
+ }
+ stopSelectionActionMode();
+ }
+ }
+
private class SelectionActionModeCallback implements ActionMode.Callback {
@Override
@@ -7766,7 +7804,6 @@
}
menu.add(0, ID_SELECT_ALL, 0, com.android.internal.R.string.selectAll).
- setIcon(com.android.internal.R.drawable.ic_menu_select_all).
setAlphabeticShortcut('a').
setShowAsAction(
MenuItem.SHOW_AS_ACTION_ALWAYS | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
@@ -7844,26 +7881,7 @@
switch (item.getItemId()) {
case ID_PASTE:
- ClipData clip = clipboard.getPrimaryClip();
- if (clip != null) {
- boolean didfirst = false;
- for (int i=0; i<clip.getItemCount(); i++) {
- CharSequence paste = clip.getItem(i).coerceToText(getContext());
- if (paste != null) {
- if (!didfirst) {
- long minMax = prepareSpacesAroundPaste(min, max, paste);
- min = extractRangeStartFromLong(minMax);
- max = extractRangeEndFromLong(minMax);
- Selection.setSelection((Spannable) mText, max);
- ((Editable) mText).replace(min, max, paste);
- } else {
- ((Editable) mText).insert(getSelectionEnd(), "\n");
- ((Editable) mText).insert(getSelectionEnd(), paste);
- }
- }
- }
- stopSelectionActionMode();
- }
+ paste(clipboard, min, max);
return true;
case ID_CUT:
@@ -7931,6 +7949,100 @@
public boolean onTouchEvent(MotionEvent event);
}
+ private class PastePopupMenu implements OnClickListener {
+ private PopupWindow mContainer;
+ private int mPositionX;
+ private int mPositionY;
+ private View mPasteView, mNoPasteView;
+
+ public PastePopupMenu() {
+ mContainer = new PopupWindow(TextView.this.mContext, null,
+ com.android.internal.R.attr.textSelectHandleWindowStyle);
+ mContainer.setSplitTouchEnabled(true);
+ mContainer.setClippingEnabled(false);
+ mContainer.setWindowLayoutType(WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL);
+
+ mContainer.setWidth(ViewGroup.LayoutParams.WRAP_CONTENT);
+ mContainer.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
+ }
+
+ private void updateContent() {
+ View view = canPaste() ? mPasteView : mNoPasteView;
+
+ if (view == null) {
+ final int layout = canPaste() ? mTextEditPasteWindowLayout :
+ mTextEditNoPasteWindowLayout;
+ LayoutInflater inflater = (LayoutInflater)TextView.this.mContext.
+ getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ if (inflater != null) {
+ view = inflater.inflate(layout, null);
+ }
+
+ if (view == null) {
+ throw new IllegalArgumentException("Unable to inflate TextEdit paste window");
+ }
+
+ final int size = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
+ view.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT));
+ view.measure(size, size);
+
+ view.setOnClickListener(this);
+
+ if (canPaste()) mPasteView = view;
+ else mNoPasteView = view;
+ }
+
+ mContainer.setContentView(view);
+ }
+
+ public void show() {
+ updateContent();
+ final int[] coords = mTempCoords;
+ TextView.this.getLocationInWindow(coords);
+ positionAtCursor();
+ coords[0] += mPositionX;
+ coords[1] += mPositionY;
+ mContainer.showAtLocation(TextView.this, Gravity.NO_GRAVITY, coords[0], coords[1]);
+ }
+
+ public void hide() {
+ mContainer.dismiss();
+ }
+
+ public boolean isShowing() {
+ return mContainer.isShowing();
+ }
+
+ @Override
+ public void onClick(View v) {
+ ClipboardManager clipboard =
+ (ClipboardManager) getContext().getSystemService(Context.CLIPBOARD_SERVICE);
+ paste(clipboard, getSelectionStart(), getSelectionEnd());
+ }
+
+ void positionAtCursor() {
+ final int offset = TextView.this.getSelectionStart();
+ View contentView = mContainer.getContentView();
+ final int width = contentView.getMeasuredWidth();
+ final int height = contentView.getMeasuredHeight();
+ final int line = mLayout.getLineForOffset(offset);
+ final int lineTop = mLayout.getLineTop(line);
+
+ final Rect bounds = sCursorControllerTempRect;
+ bounds.left = (int) (mLayout.getPrimaryHorizontal(offset) - width / 2.0f);
+ bounds.top = lineTop - height;
+
+ bounds.right = bounds.left + width;
+ bounds.bottom = bounds.top + height;
+
+ convertFromViewportToContentCoordinates(bounds);
+
+ mPositionX = bounds.left;
+ mPositionY = bounds.top;
+ }
+ }
+
private class HandleView extends View {
private boolean mPositionOnTop = false;
private Drawable mDrawable;
@@ -7947,6 +8059,9 @@
private float mTouchOffsetY;
private int mLastParentX;
private int mLastParentY;
+ private int mContainerPositionX, mContainerPositionY;
+ private long mTouchTimer;
+ private PastePopupMenu mPastePopupWindow;
public static final int LEFT = 0;
public static final int CENTER = 1;
@@ -7998,6 +8113,7 @@
mDrawable = mSelectHandleCenter;
handleWidth = mDrawable.getIntrinsicWidth();
mHotspotX = handleWidth / 2;
+ mPastePopupWindow = new PastePopupMenu();
break;
}
}
@@ -8011,7 +8127,7 @@
}
@Override
- public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(mDrawable.getIntrinsicWidth(),
mDrawable.getIntrinsicHeight());
}
@@ -8024,14 +8140,22 @@
mContainer.setContentView(this);
final int[] coords = mTempCoords;
TextView.this.getLocationInWindow(coords);
- coords[0] += mPositionX;
- coords[1] += mPositionY;
- mContainer.showAtLocation(TextView.this, 0, coords[0], coords[1]);
+ mContainerPositionX = coords[0] + mPositionX;
+ mContainerPositionY = coords[1] + mPositionY;
+ mContainer.showAtLocation(TextView.this, 0, mContainerPositionX, mContainerPositionY);
+
+ // Hide paste view when handle is moved.
+ if (mPastePopupWindow != null) {
+ mPastePopupWindow.hide();
+ }
}
public void hide() {
mIsDragging = false;
mContainer.dismiss();
+ if (mPastePopupWindow != null) {
+ mPastePopupWindow.hide();
+ }
}
public boolean isShowing() {
@@ -8086,8 +8210,22 @@
if (mContainer.isShowing()){
coords = mTempCoords;
TextView.this.getLocationInWindow(coords);
- mContainer.update(coords[0] + mPositionX, coords[1] + mPositionY,
- mRight - mLeft, mBottom - mTop);
+ final int containerPositionX = coords[0] + mPositionX;
+ final int containerPositionY = coords[1] + mPositionY;
+
+ if (containerPositionX != mContainerPositionX ||
+ containerPositionY != mContainerPositionY) {
+ mContainerPositionX = containerPositionX;
+ mContainerPositionY = containerPositionY;
+
+ mContainer.update(mContainerPositionX, mContainerPositionY,
+ mRight - mLeft, mBottom - mTop);
+
+ // Hide paste popup window as soon as a scroll occurs.
+ if (mPastePopupWindow != null) {
+ mPastePopupWindow.hide();
+ }
+ }
} else {
show();
}
@@ -8103,6 +8241,10 @@
mLastParentX = coords[0];
mLastParentY = coords[1];
}
+ // Hide paste popup window as soon as the handle is dragged.
+ if (mPastePopupWindow != null) {
+ mPastePopupWindow.hide();
+ }
}
} else {
hide();
@@ -8110,7 +8252,7 @@
}
@Override
- public void onDraw(Canvas c) {
+ protected void onDraw(Canvas c) {
mDrawable.setBounds(0, 0, mRight - mLeft, mBottom - mTop);
if (mPositionOnTop) {
c.save();
@@ -8135,6 +8277,15 @@
mLastParentX = coords[0];
mLastParentY = coords[1];
mIsDragging = true;
+ if (mPastePopupWindow != null) {
+ mTouchTimer = SystemClock.uptimeMillis();
+ if (mPastePopupWindow.isShowing()) {
+ // Tapping on the handle again dismisses the displayed paste view,
+ mPastePopupWindow.hide();
+ // and makes sure the action up does not display the paste view.
+ mTouchTimer = 0;
+ }
+ }
break;
}
case MotionEvent.ACTION_MOVE: {
@@ -8148,6 +8299,24 @@
break;
}
case MotionEvent.ACTION_UP:
+ if (mPastePopupWindow != null) {
+ long delay = SystemClock.uptimeMillis() - mTouchTimer;
+ if (delay < ViewConfiguration.getTapTimeout()) {
+ final float touchOffsetX = ev.getRawX() - mPositionX;
+ final float touchOffsetY = ev.getRawY() - mPositionY;
+ final float dx = touchOffsetX - mTouchToWindowOffsetX;
+ final float dy = touchOffsetY - mTouchToWindowOffsetY;
+ final float distanceSquared = dx * dx + dy * dy;
+ final ViewConfiguration viewConfiguration = ViewConfiguration.get(getContext());
+ final int doubleTapSlop = viewConfiguration.getScaledDoubleTapSlop();
+ final int slopSquared = doubleTapSlop * doubleTapSlop;
+ if (distanceSquared < slopSquared) {
+ mPastePopupWindow.show();
+ }
+ }
+ }
+ mIsDragging = false;
+ break;
case MotionEvent.ACTION_CANCEL:
mIsDragging = false;
}
diff --git a/core/java/android/widget/VideoView.java b/core/java/android/widget/VideoView.java
index 531d9fe..3d9cde4 100644
--- a/core/java/android/widget/VideoView.java
+++ b/core/java/android/widget/VideoView.java
@@ -62,9 +62,6 @@
private static final int STATE_PLAYING = 3;
private static final int STATE_PAUSED = 4;
private static final int STATE_PLAYBACK_COMPLETED = 5;
- private static final int STATE_SUSPEND = 6;
- private static final int STATE_RESUME = 7;
- private static final int STATE_SUSPEND_UNSUPPORTED = 8;
// mCurrentState is a VideoView object's current state.
// mTargetState is the state that a method caller intends to reach.
@@ -90,7 +87,6 @@
private boolean mCanPause;
private boolean mCanSeekBack;
private boolean mCanSeekForward;
- private int mStateWhenSuspended; //state before calling suspend()
public VideoView(Context context) {
super(context);
@@ -470,14 +466,7 @@
public void surfaceCreated(SurfaceHolder holder)
{
mSurfaceHolder = holder;
- //resume() was called before surfaceCreated()
- if (mMediaPlayer != null && mCurrentState == STATE_SUSPEND
- && mTargetState == STATE_RESUME) {
- mMediaPlayer.setDisplay(mSurfaceHolder);
- resume();
- } else {
- openVideo();
- }
+ openVideo();
}
public void surfaceDestroyed(SurfaceHolder holder)
@@ -485,9 +474,7 @@
// after we return from this we can't use the surface any more
mSurfaceHolder = null;
if (mMediaController != null) mMediaController.hide();
- if (mCurrentState != STATE_SUSPEND) {
- release(true);
- }
+ release(true);
}
};
@@ -581,39 +568,14 @@
}
public void suspend() {
- if (isInPlaybackState()) {
- if (mMediaPlayer.suspend()) {
- mStateWhenSuspended = mCurrentState;
- mCurrentState = STATE_SUSPEND;
- mTargetState = STATE_SUSPEND;
- } else {
- release(false);
- mCurrentState = STATE_SUSPEND_UNSUPPORTED;
- Log.w(TAG, "Unable to suspend video. Release MediaPlayer.");
- }
- }
+ release(false);
}
public void resume() {
- if (mSurfaceHolder == null && mCurrentState == STATE_SUSPEND){
- mTargetState = STATE_RESUME;
- return;
- }
- if (mMediaPlayer != null && mCurrentState == STATE_SUSPEND) {
- if (mMediaPlayer.resume()) {
- mCurrentState = mStateWhenSuspended;
- mTargetState = mStateWhenSuspended;
- } else {
- Log.w(TAG, "Unable to resume video");
- }
- return;
- }
- if (mCurrentState == STATE_SUSPEND_UNSUPPORTED) {
- openVideo();
- }
+ openVideo();
}
- // cache duration as mDuration for faster access
+ // cache duration as mDuration for faster access
public int getDuration() {
if (isInPlaybackState()) {
if (mDuration > 0) {
diff --git a/core/java/com/android/internal/app/ActionBarImpl.java b/core/java/com/android/internal/app/ActionBarImpl.java
index 3015363..f4a041c 100644
--- a/core/java/com/android/internal/app/ActionBarImpl.java
+++ b/core/java/com/android/internal/app/ActionBarImpl.java
@@ -52,9 +52,6 @@
public class ActionBarImpl extends ActionBar {
private static final int NORMAL_VIEW = 0;
private static final int CONTEXT_VIEW = 1;
-
- private static final int TAB_SWITCH_SHOW_HIDE = 0;
- private static final int TAB_SWITCH_ADD_REMOVE = 1;
private Context mContext;
private Activity mActivity;
@@ -67,9 +64,7 @@
private ArrayList<TabImpl> mTabs = new ArrayList<TabImpl>();
- private int mTabContainerViewId = android.R.id.content;
private TabImpl mSelectedTab;
- private int mTabSwitchMode = TAB_SWITCH_ADD_REMOVE;
private ActionMode mActionMode;
@@ -133,7 +128,9 @@
public void setCustomNavigationMode(View view) {
cleanupTabs();
- mActionView.setCustomNavigationView(view);
+ setCustomView(view);
+ setDisplayOptions(DISPLAY_SHOW_CUSTOM, DISPLAY_SHOW_CUSTOM | DISPLAY_SHOW_TITLE);
+ mActionView.setNavigationMode(NAVIGATION_MODE_STANDARD);
mActionView.setCallback(null);
}
@@ -144,16 +141,17 @@
public void setDropdownNavigationMode(SpinnerAdapter adapter, NavigationCallback callback,
int defaultSelectedPosition) {
cleanupTabs();
- mActionView.setNavigationMode(NAVIGATION_MODE_DROPDOWN_LIST);
- mActionView.setDropdownAdapter(adapter);
+ setDisplayOptions(0, DISPLAY_SHOW_CUSTOM | DISPLAY_SHOW_TITLE);
+ mActionView.setNavigationMode(NAVIGATION_MODE_LIST);
+ setListNavigationCallbacks(adapter, callback);
if (defaultSelectedPosition >= 0) {
mActionView.setDropdownSelectedPosition(defaultSelectedPosition);
}
- mActionView.setCallback(callback);
}
public void setStandardNavigationMode() {
cleanupTabs();
+ setDisplayOptions(DISPLAY_SHOW_TITLE, DISPLAY_SHOW_TITLE | DISPLAY_SHOW_CUSTOM);
mActionView.setNavigationMode(NAVIGATION_MODE_STANDARD);
mActionView.setCallback(null);
}
@@ -163,24 +161,21 @@
case NAVIGATION_MODE_TABS:
selectTab(mTabs.get(position));
break;
- case NAVIGATION_MODE_DROPDOWN_LIST:
+ case NAVIGATION_MODE_LIST:
mActionView.setDropdownSelectedPosition(position);
break;
default:
throw new IllegalStateException(
- "setSelectedNavigationItem not valid for current navigation mode");
+ "setSelectedNavigationIndex not valid for current navigation mode");
}
}
public int getSelectedNavigationItem() {
- switch (mActionView.getNavigationMode()) {
- case NAVIGATION_MODE_TABS:
- return mSelectedTab.getPosition();
- case NAVIGATION_MODE_DROPDOWN_LIST:
- return mActionView.getDropdownSelectedPosition();
- default:
- return -1;
- }
+ return getSelectedNavigationIndex();
+ }
+
+ public void removeAllTabs() {
+ cleanupTabs();
}
private void cleanupTabs() {
@@ -321,6 +316,7 @@
throw new IllegalStateException(
"Tab navigation mode cannot be used outside of an Activity");
}
+ setDisplayOptions(0, DISPLAY_SHOW_TITLE | DISPLAY_SHOW_CUSTOM);
mActionView.setNavigationMode(NAVIGATION_MODE_TABS);
}
@@ -510,8 +506,9 @@
}
@Override
- public void setTag(Object tag) {
+ public Tab setTag(Object tag) {
mTag = tag;
+ return this;
}
public ActionBar.TabListener getCallback() {
@@ -519,8 +516,9 @@
}
@Override
- public void setTabListener(ActionBar.TabListener callback) {
+ public Tab setTabListener(ActionBar.TabListener callback) {
mCallback = callback;
+ return this;
}
@Override
@@ -529,8 +527,9 @@
}
@Override
- public void setCustomView(View view) {
+ public Tab setCustomView(View view) {
mCustomView = view;
+ return this;
}
@Override
@@ -553,13 +552,15 @@
}
@Override
- public void setIcon(Drawable icon) {
+ public Tab setIcon(Drawable icon) {
mIcon = icon;
+ return this;
}
@Override
- public void setText(CharSequence text) {
+ public Tab setText(CharSequence text) {
mText = text;
+ return this;
}
@Override
@@ -567,4 +568,56 @@
selectTab(this);
}
}
+
+ @Override
+ public void setCustomView(View view) {
+ mActionView.setCustomNavigationView(view);
+ }
+
+ @Override
+ public void setCustomView(View view, LayoutParams layoutParams) {
+ view.setLayoutParams(layoutParams);
+ mActionView.setCustomNavigationView(view);
+ }
+
+ @Override
+ public void setListNavigationCallbacks(SpinnerAdapter adapter, NavigationCallback callback) {
+ mActionView.setDropdownAdapter(adapter);
+ mActionView.setCallback(callback);
+ }
+
+ @Override
+ public int getSelectedNavigationIndex() {
+ switch (mActionView.getNavigationMode()) {
+ case NAVIGATION_MODE_TABS:
+ return mSelectedTab.getPosition();
+ case NAVIGATION_MODE_LIST:
+ return mActionView.getDropdownSelectedPosition();
+ default:
+ return -1;
+ }
+ }
+
+ @Override
+ public int getNavigationItemCount() {
+ switch (mActionView.getNavigationMode()) {
+ case NAVIGATION_MODE_TABS:
+ return mTabs.size();
+ case NAVIGATION_MODE_LIST:
+ SpinnerAdapter adapter = mActionView.getDropdownAdapter();
+ return adapter != null ? adapter.getCount() : 0;
+ default:
+ return 0;
+ }
+ }
+
+ @Override
+ public void setNavigationMode(int mode) {
+ mActionView.setNavigationMode(mode);
+ }
+
+ @Override
+ public Tab getTabAt(int index) {
+ return mTabs.get(index);
+ }
}
diff --git a/core/java/com/android/internal/app/LocalePicker.java b/core/java/com/android/internal/app/LocalePicker.java
index c8e3935..6f6b40b 100644
--- a/core/java/com/android/internal/app/LocalePicker.java
+++ b/core/java/com/android/internal/app/LocalePicker.java
@@ -18,11 +18,11 @@
import com.android.internal.R;
-import android.app.Activity;
import android.app.ActivityManagerNative;
import android.app.IActivityManager;
import android.app.ListFragment;
import android.app.backup.BackupManager;
+import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Bundle;
@@ -45,61 +45,65 @@
public void onLocaleSelected(Locale locale);
}
- Loc[] mLocales;
- String[] mSpecialLocaleCodes;
- String[] mSpecialLocaleNames;
-
- private Locale mNewLocale;
-
LocaleSelectionListener mListener; // default to null
- private static class Loc implements Comparable<Loc> {
- static Collator sCollator = Collator.getInstance();
+ public static class LocaleInfo implements Comparable<LocaleInfo> {
+ static final Collator sCollator = Collator.getInstance();
String label;
Locale locale;
- public Loc(String label, Locale locale) {
+ public LocaleInfo(String label, Locale locale) {
this.label = label;
this.locale = locale;
}
+ public String getLabel() {
+ return label;
+ }
+
+ public Locale getLocale() {
+ return locale;
+ }
+
@Override
public String toString() {
return this.label;
}
@Override
- public int compareTo(Loc another) {
+ public int compareTo(LocaleInfo another) {
return sCollator.compare(this.label, another.label);
}
}
- private void setUpLocaleList() {
- final Activity activity = getActivity();
- final Resources resources = activity.getResources();
- mSpecialLocaleCodes = resources.getStringArray(R.array.special_locale_codes);
- mSpecialLocaleNames = resources.getStringArray(R.array.special_locale_names);
-
- final String[] locales = activity.getAssets().getLocales();
+ /**
+ * Constructs an Adapter object containing Locale information. Content is sorted by
+ * {@link LocaleInfo#label}.
+ */
+ public static ArrayAdapter<LocaleInfo> constructAdapter(Context context) {
+ final Resources resources = context.getResources();
+ final String[] locales = context.getAssets().getLocales();
+ final String[] specialLocaleCodes = resources.getStringArray(R.array.special_locale_codes);
+ final String[] specialLocaleNames = resources.getStringArray(R.array.special_locale_names);
Arrays.sort(locales);
final int origSize = locales.length;
- Loc[] preprocess = new Loc[origSize];
+ final LocaleInfo[] preprocess = new LocaleInfo[origSize];
int finalSize = 0;
for (int i = 0 ; i < origSize; i++ ) {
- String s = locales[i];
- int len = s.length();
+ final String s = locales[i];
+ final int len = s.length();
if (len == 5) {
String language = s.substring(0, 2);
String country = s.substring(3, 5);
- Locale l = new Locale(language, country);
+ final Locale l = new Locale(language, country);
if (finalSize == 0) {
if (DEBUG) {
Log.v(TAG, "adding initial "+ toTitleCase(l.getDisplayLanguage(l)));
}
preprocess[finalSize++] =
- new Loc(toTitleCase(l.getDisplayLanguage(l)), l);
+ new LocaleInfo(toTitleCase(l.getDisplayLanguage(l)), l);
} else {
// check previous entry:
// same lang and a country -> upgrade to full name and
@@ -110,15 +114,20 @@
if (DEBUG) {
Log.v(TAG, "backing up and fixing "+
preprocess[finalSize-1].label+" to "+
- getDisplayName(preprocess[finalSize-1].locale));
+ getDisplayName(preprocess[finalSize-1].locale,
+ specialLocaleCodes, specialLocaleNames));
}
preprocess[finalSize-1].label = toTitleCase(
- getDisplayName(preprocess[finalSize-1].locale));
+ getDisplayName(preprocess[finalSize-1].locale,
+ specialLocaleCodes, specialLocaleNames));
if (DEBUG) {
- Log.v(TAG, " and adding "+ toTitleCase(getDisplayName(l)));
+ Log.v(TAG, " and adding "+ toTitleCase(
+ getDisplayName(l, specialLocaleCodes, specialLocaleNames)));
}
preprocess[finalSize++] =
- new Loc(toTitleCase(getDisplayName(l)), l);
+ new LocaleInfo(toTitleCase(
+ getDisplayName(
+ l, specialLocaleCodes, specialLocaleNames)), l);
} else {
String displayName;
if (s.equals("zz_ZZ")) {
@@ -129,31 +138,20 @@
if (DEBUG) {
Log.v(TAG, "adding "+displayName);
}
- preprocess[finalSize++] = new Loc(displayName, l);
+ preprocess[finalSize++] = new LocaleInfo(displayName, l);
}
}
}
}
- mLocales = new Loc[finalSize];
- for (int i = 0; i < finalSize ; i++) {
- mLocales[i] = preprocess[i];
+
+ final LocaleInfo[] localeInfos = new LocaleInfo[finalSize];
+ for (int i = 0; i < finalSize; i++) {
+ localeInfos[i] = preprocess[i];
}
- Arrays.sort(mLocales);
+ Arrays.sort(localeInfos);
final int layoutId = R.layout.locale_picker_item;
final int fieldId = R.id.locale;
- final ArrayAdapter<Loc> adapter =
- new ArrayAdapter<Loc>(activity, layoutId, fieldId, mLocales);
- setListAdapter(adapter);
- }
-
- @Override
- public void onActivityCreated(final Bundle savedInstanceState) {
- super.onActivityCreated(savedInstanceState);
- setUpLocaleList();
- }
-
- public void setLocaleSelectionListener(LocaleSelectionListener listener) {
- mListener = listener;
+ return new ArrayAdapter<LocaleInfo>(context, layoutId, fieldId, localeInfos);
}
private static String toTitleCase(String s) {
@@ -164,12 +162,13 @@
return Character.toUpperCase(s.charAt(0)) + s.substring(1);
}
- private String getDisplayName(Locale l) {
+ private static String getDisplayName(
+ Locale l, String[] specialLocaleCodes, String[] specialLocaleNames) {
String code = l.toString();
- for (int i = 0; i < mSpecialLocaleCodes.length; i++) {
- if (mSpecialLocaleCodes[i].equals(code)) {
- return mSpecialLocaleNames[i];
+ for (int i = 0; i < specialLocaleCodes.length; i++) {
+ if (specialLocaleCodes[i].equals(code)) {
+ return specialLocaleNames[i];
}
}
@@ -177,6 +176,17 @@
}
@Override
+ public void onActivityCreated(final Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+ final ArrayAdapter<LocaleInfo> adapter = constructAdapter(getActivity());
+ setListAdapter(adapter);
+ }
+
+ public void setLocaleSelectionListener(LocaleSelectionListener listener) {
+ mListener = listener;
+ }
+
+ @Override
public void onResume() {
super.onResume();
getListView().requestFocus();
@@ -191,7 +201,8 @@
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
if (mListener != null) {
- mListener.onLocaleSelected(mLocales[position].locale);
+ final Locale locale = ((LocaleInfo)getListAdapter().getItem(position)).locale;
+ mListener.onLocaleSelected(locale);
}
}
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index 34a5b11..f87ca3e 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -32,5 +32,6 @@
void animateCollapse();
void setLightsOn(boolean on);
void setMenuKeyVisible(boolean visible);
+ void setIMEButtonVisible(boolean visible);
}
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index 90f4d48..d5ae1f0 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -32,6 +32,7 @@
void removeIcon(String slot);
void setActiveWindowIsFullscreen(boolean fullscreen);
void setMenuKeyVisible(boolean visible);
+ void setIMEButtonVisible(boolean visible);
// ---- Methods below are for use by the status bar policy services ----
// You need the STATUS_BAR_SERVICE permission
diff --git a/core/java/com/android/internal/view/IInputMethodManager.aidl b/core/java/com/android/internal/view/IInputMethodManager.aidl
index 49ae2bc7..ca1cd59 100644
--- a/core/java/com/android/internal/view/IInputMethodManager.aidl
+++ b/core/java/com/android/internal/view/IInputMethodManager.aidl
@@ -55,6 +55,7 @@
void hideMySoftInput(in IBinder token, int flags);
void showMySoftInput(in IBinder token, int flags);
void updateStatusIcon(in IBinder token, String packageName, int iconId);
+ void setIMEButtonVisible(in IBinder token, boolean visible);
InputMethodSubtype getCurrentInputMethodSubtype();
boolean setInputMethodEnabled(String id, boolean enabled);
diff --git a/core/java/com/android/internal/view/menu/ActionMenuView.java b/core/java/com/android/internal/view/menu/ActionMenuView.java
index 2888074..621defe 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuView.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuView.java
@@ -24,10 +24,10 @@
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
+import android.view.ViewParent;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
-import android.widget.LinearLayout.LayoutParams;
import java.util.ArrayList;
@@ -169,6 +169,10 @@
final MenuItemImpl itemData = itemsToShow.get(i);
final View actionView = itemData.getActionView();
if (actionView != null) {
+ final ViewParent parent = actionView.getParent();
+ if (parent instanceof ViewGroup) {
+ ((ViewGroup) parent).removeView(actionView);
+ }
addView(actionView, makeActionViewLayoutParams());
} else {
needsDivider = addItemView(i == 0 || !needsDivider,
diff --git a/core/java/com/android/internal/widget/ActionBarContextView.java b/core/java/com/android/internal/widget/ActionBarContextView.java
index 38f76d3..e93c414 100644
--- a/core/java/com/android/internal/widget/ActionBarContextView.java
+++ b/core/java/com/android/internal/widget/ActionBarContextView.java
@@ -26,9 +26,6 @@
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.Button;
-import android.widget.ButtonGroup;
-import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.TextView;
diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java
index 4c3bba1..be96e48 100644
--- a/core/java/com/android/internal/widget/ActionBarView.java
+++ b/core/java/com/android/internal/widget/ActionBarView.java
@@ -26,20 +26,21 @@
import android.app.Activity;
import android.content.Context;
import android.content.pm.ApplicationInfo;
+import android.content.pm.ComponentInfo;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.TypedArray;
-import android.graphics.PorterDuff;
-import android.graphics.PorterDuffColorFilter;
import android.graphics.drawable.Drawable;
import android.text.TextUtils.TruncateAt;
import android.util.AttributeSet;
-import android.util.DisplayMetrics;
+import android.util.Log;
import android.view.ActionMode;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.View;
import android.view.ViewGroup;
+import android.view.ViewParent;
import android.widget.AdapterView;
import android.widget.HorizontalScrollView;
import android.widget.ImageView;
@@ -63,19 +64,27 @@
* Display options that require re-layout as opposed to a simple invalidate
*/
private static final int DISPLAY_RELAYOUT_MASK =
- ActionBar.DISPLAY_HIDE_HOME |
- ActionBar.DISPLAY_USE_LOGO;
+ ActionBar.DISPLAY_SHOW_HOME |
+ ActionBar.DISPLAY_USE_LOGO |
+ ActionBar.DISPLAY_HOME_AS_UP |
+ ActionBar.DISPLAY_SHOW_CUSTOM |
+ ActionBar.DISPLAY_SHOW_TITLE;
+
+ private static final int DEFAULT_CUSTOM_GRAVITY = Gravity.LEFT | Gravity.CENTER_VERTICAL;
private final int mContentHeight;
private int mNavigationMode;
- private int mDisplayOptions;
+ private int mDisplayOptions = ActionBar.DISPLAY_SHOW_HOME | ActionBar.DISPLAY_HOME_AS_UP;
private CharSequence mTitle;
private CharSequence mSubtitle;
private Drawable mIcon;
private Drawable mLogo;
private Drawable mDivider;
+ private Drawable mHomeAsUpIndicator;
+ private LinearLayout mHomeLayout;
+ private ImageView mHomeAsUpView;
private ImageView mIconView;
private ImageView mLogoView;
private LinearLayout mTitleLayout;
@@ -98,7 +107,8 @@
private ActionBarContextView mContextView;
private ActionMenuItem mLogoNavItem;
-
+
+ private SpinnerAdapter mSpinnerAdapter;
private NavigationCallback mCallback;
private final AdapterView.OnItemSelectedListener mNavItemSelectedListener =
@@ -122,30 +132,56 @@
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ActionBar);
- final int colorFilter = a.getColor(R.styleable.ActionBar_colorFilter, 0);
-
- if (colorFilter != 0) {
- final Drawable d = getBackground();
- d.setDither(true);
- d.setColorFilter(new PorterDuffColorFilter(colorFilter, PorterDuff.Mode.OVERLAY));
- }
-
- ApplicationInfo info = context.getApplicationInfo();
+ ApplicationInfo appInfo = context.getApplicationInfo();
PackageManager pm = context.getPackageManager();
mNavigationMode = a.getInt(R.styleable.ActionBar_navigationMode,
ActionBar.NAVIGATION_MODE_STANDARD);
mTitle = a.getText(R.styleable.ActionBar_title);
mSubtitle = a.getText(R.styleable.ActionBar_subtitle);
- mDisplayOptions = a.getInt(R.styleable.ActionBar_displayOptions, DISPLAY_DEFAULT);
mLogo = a.getDrawable(R.styleable.ActionBar_logo);
if (mLogo == null) {
- mLogo = info.loadLogo(pm);
+ if (context instanceof Activity) {
+ try {
+ mLogo = pm.getActivityLogo(((Activity) context).getComponentName());
+ } catch (NameNotFoundException e) {
+ Log.e(TAG, "Activity component name not found!", e);
+ }
+ }
+ if (mLogo == null) {
+ mLogo = appInfo.loadLogo(pm);
+ }
}
+
mIcon = a.getDrawable(R.styleable.ActionBar_icon);
if (mIcon == null) {
- mIcon = info.loadIcon(pm);
+ if (context instanceof Activity) {
+ try {
+ mIcon = pm.getActivityIcon(((Activity) context).getComponentName());
+ } catch (NameNotFoundException e) {
+ Log.e(TAG, "Activity component name not found!", e);
+ }
+ }
+ if (mIcon == null) {
+ mIcon = appInfo.loadIcon(pm);
+ }
}
+
+ mHomeLayout = new LinearLayout(context, null,
+ com.android.internal.R.attr.actionButtonStyle);
+ mHomeLayout.setClickable(true);
+ mHomeLayout.setFocusable(true);
+ mHomeLayout.setOnClickListener(mHomeClickListener);
+ mHomeLayout.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
+ LayoutParams.MATCH_PARENT));
+
+ mHomeAsUpIndicator = a.getDrawable(R.styleable.ActionBar_homeAsUpIndicator);
+
+ mHomeAsUpView = new ImageView(context);
+ mHomeAsUpView.setImageDrawable(mHomeAsUpIndicator);
+ mHomeAsUpView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
+ LayoutParams.MATCH_PARENT));
+ mHomeLayout.addView(mHomeAsUpView);
Drawable background = a.getDrawable(R.styleable.ActionBar_background);
if (background != null) {
@@ -155,11 +191,14 @@
mTitleStyleRes = a.getResourceId(R.styleable.ActionBar_titleTextStyle, 0);
mSubtitleStyleRes = a.getResourceId(R.styleable.ActionBar_subtitleTextStyle, 0);
+ setDisplayOptions(a.getInt(R.styleable.ActionBar_displayOptions, DISPLAY_DEFAULT));
+
final int customNavId = a.getResourceId(R.styleable.ActionBar_customNavigationLayout, 0);
if (customNavId != 0) {
LayoutInflater inflater = LayoutInflater.from(context);
mCustomNavView = (View) inflater.inflate(customNavId, null);
- mNavigationMode = ActionBar.NAVIGATION_MODE_CUSTOM;
+ mNavigationMode = ActionBar.NAVIGATION_MODE_STANDARD;
+ setDisplayOptions(mDisplayOptions | ActionBar.DISPLAY_SHOW_CUSTOM);
}
mContentHeight = a.getLayoutDimension(R.styleable.ActionBar_height, 0);
@@ -241,9 +280,13 @@
}
public void setCustomNavigationView(View view) {
+ final boolean showCustom = (mDisplayOptions & ActionBar.DISPLAY_SHOW_CUSTOM) != 0;
+ if (mCustomNavView != null && showCustom) {
+ removeView(mCustomNavView);
+ }
mCustomNavView = view;
- if (view != null) {
- setNavigationMode(ActionBar.NAVIGATION_MODE_CUSTOM);
+ if (mCustomNavView != null && showCustom) {
+ addView(mCustomNavView);
}
}
@@ -296,15 +339,43 @@
}
public void setDisplayOptions(int options) {
+ // TODO Remove this once DISPLAY_HIDE_HOME is removed
+ if ((options & ActionBar.DISPLAY_HIDE_HOME) != 0) {
+ options &= ~(ActionBar.DISPLAY_HIDE_HOME | ActionBar.DISPLAY_SHOW_HOME);
+ }
+ // End TODO
+
final int flagsChanged = options ^ mDisplayOptions;
mDisplayOptions = options;
if ((flagsChanged & DISPLAY_RELAYOUT_MASK) != 0) {
- final int vis = (options & ActionBar.DISPLAY_HIDE_HOME) != 0 ? GONE : VISIBLE;
- if (mLogoView != null) {
- mLogoView.setVisibility(vis);
+ final int vis = (options & ActionBar.DISPLAY_SHOW_HOME) != 0 ? VISIBLE : GONE;
+ mHomeLayout.setVisibility(vis);
+
+ if ((flagsChanged & ActionBar.DISPLAY_HOME_AS_UP) != 0) {
+ mHomeAsUpView.setVisibility((options & ActionBar.DISPLAY_HOME_AS_UP) != 0
+ ? VISIBLE : GONE);
}
- if (mIconView != null) {
- mIconView.setVisibility(vis);
+
+ if (mLogoView != null && (flagsChanged & ActionBar.DISPLAY_USE_LOGO) != 0) {
+ final boolean logoVis = (options & ActionBar.DISPLAY_USE_LOGO) != 0;
+ mLogoView.setVisibility(logoVis ? VISIBLE : GONE);
+ mIconView.setVisibility(logoVis ? GONE : VISIBLE);
+ }
+
+ if ((flagsChanged & ActionBar.DISPLAY_SHOW_TITLE) != 0) {
+ if ((options & ActionBar.DISPLAY_SHOW_TITLE) != 0) {
+ initTitle();
+ } else {
+ removeView(mTitleLayout);
+ }
+ }
+
+ if ((flagsChanged & ActionBar.DISPLAY_SHOW_CUSTOM) != 0 && mCustomNavView != null) {
+ if ((options & ActionBar.DISPLAY_SHOW_CUSTOM) != 0) {
+ addView(mCustomNavView);
+ } else {
+ removeView(mCustomNavView);
+ }
}
requestLayout();
@@ -317,52 +388,27 @@
final int oldMode = mNavigationMode;
if (mode != oldMode) {
switch (oldMode) {
- case ActionBar.NAVIGATION_MODE_STANDARD:
- if (mTitleLayout != null) {
- removeView(mTitleLayout);
- mTitleLayout = null;
- mTitleView = null;
- mSubtitleView = null;
- }
- break;
- case ActionBar.NAVIGATION_MODE_DROPDOWN_LIST:
+ case ActionBar.NAVIGATION_MODE_LIST:
if (mSpinner != null) {
removeView(mSpinner);
- mSpinner = null;
- }
- break;
- case ActionBar.NAVIGATION_MODE_CUSTOM:
- if (mCustomNavView != null) {
- removeView(mCustomNavView);
- mCustomNavView = null;
}
break;
case ActionBar.NAVIGATION_MODE_TABS:
if (mTabLayout != null) {
removeView(mTabScrollView);
- mTabLayout = null;
- mTabScrollView = null;
}
}
switch (mode) {
- case ActionBar.NAVIGATION_MODE_STANDARD:
- initTitle();
- break;
- case ActionBar.NAVIGATION_MODE_DROPDOWN_LIST:
+ case ActionBar.NAVIGATION_MODE_LIST:
mSpinner = new Spinner(mContext, null,
com.android.internal.R.attr.actionDropDownStyle);
+ mSpinner.setAdapter(mSpinnerAdapter);
mSpinner.setOnItemSelectedListener(mNavItemSelectedListener);
addView(mSpinner);
break;
- case ActionBar.NAVIGATION_MODE_CUSTOM:
- addView(mCustomNavView);
- break;
case ActionBar.NAVIGATION_MODE_TABS:
- mTabScrollView = new HorizontalScrollView(getContext());
- mTabLayout = new LinearLayout(getContext(), null,
- com.android.internal.R.attr.actionBarTabBarStyle);
- mTabScrollView.addView(mTabLayout);
+ ensureTabsExist();
addView(mTabScrollView);
break;
}
@@ -371,8 +417,24 @@
}
}
+ private void ensureTabsExist() {
+ if (mTabScrollView == null) {
+ mTabScrollView = new HorizontalScrollView(getContext());
+ mTabLayout = new LinearLayout(getContext(), null,
+ com.android.internal.R.attr.actionBarTabBarStyle);
+ mTabScrollView.addView(mTabLayout);
+ }
+ }
+
public void setDropdownAdapter(SpinnerAdapter adapter) {
- mSpinner.setAdapter(adapter);
+ mSpinnerAdapter = adapter;
+ if (mSpinner != null) {
+ mSpinner.setAdapter(adapter);
+ }
+ }
+
+ public SpinnerAdapter getDropdownAdapter() {
+ return mSpinnerAdapter;
}
public void setDropdownSelectedPosition(int position) {
@@ -407,6 +469,7 @@
}
public void addTab(ActionBar.Tab tab) {
+ ensureTabsExist();
final boolean isFirst = mTabLayout.getChildCount() == 0;
View tabView = createTabView(tab);
mTabLayout.addView(tabView);
@@ -416,6 +479,7 @@
}
public void addTab(ActionBar.Tab tab, int position) {
+ ensureTabsExist();
final boolean isFirst = mTabLayout.getChildCount() == 0;
final TabView tabView = createTabView(tab);
mTabLayout.addView(tabView, position);
@@ -425,46 +489,50 @@
}
public void removeTabAt(int position) {
- mTabLayout.removeViewAt(position);
+ if (mTabLayout != null) {
+ mTabLayout.removeViewAt(position);
+ }
}
@Override
protected LayoutParams generateDefaultLayoutParams() {
// Used by custom nav views if they don't supply layout params. Everything else
// added to an ActionBarView should have them already.
- return new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
+ return new ActionBar.LayoutParams(DEFAULT_CUSTOM_GRAVITY);
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
- if ((mDisplayOptions & ActionBar.DISPLAY_HIDE_HOME) == 0) {
- if (mLogo != null && (mDisplayOptions & ActionBar.DISPLAY_USE_LOGO) != 0) {
- mLogoView = new ImageView(getContext(), null,
- com.android.internal.R.attr.actionButtonStyle);
- mLogoView.setAdjustViewBounds(true);
- mLogoView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
- LayoutParams.MATCH_PARENT));
- mLogoView.setImageDrawable(mLogo);
- mLogoView.setClickable(true);
- mLogoView.setFocusable(true);
- mLogoView.setOnClickListener(mHomeClickListener);
- addView(mLogoView);
- } else if (mIcon != null) {
- mIconView = new ImageView(getContext(), null,
- com.android.internal.R.attr.actionButtonStyle);
- mIconView.setAdjustViewBounds(true);
- mIconView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
- LayoutParams.MATCH_PARENT));
- mIconView.setImageDrawable(mIcon);
- mIconView.setClickable(true);
- mIconView.setFocusable(true);
- mIconView.setOnClickListener(mHomeClickListener);
- addView(mIconView);
- }
+ final Context context = getContext();
+
+ if (mLogo != null) {
+ mLogoView = new ImageView(context);
+ mLogoView.setScaleType(ImageView.ScaleType.CENTER);
+ mLogoView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
+ LayoutParams.MATCH_PARENT));
+ mLogoView.setImageDrawable(mLogo);
+ mLogoView.setVisibility((mDisplayOptions & ActionBar.DISPLAY_USE_LOGO) != 0
+ ? VISIBLE : GONE);
+ mHomeLayout.addView(mLogoView);
}
+ if (mIcon != null) {
+ mIconView = new ImageView(context, null,
+ com.android.internal.R.attr.actionButtonStyle);
+ mIconView.setScaleType(ImageView.ScaleType.CENTER);
+ mIconView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
+ LayoutParams.MATCH_PARENT));
+ mIconView.setImageDrawable(mIcon);
+ mIconView.setVisibility(
+ (mDisplayOptions & ActionBar.DISPLAY_USE_LOGO) == 0 || mLogo == null
+ ? VISIBLE : GONE);
+ mHomeLayout.addView(mIconView);
+ }
+
+ addView(mHomeLayout);
+
switch (mNavigationMode) {
case ActionBar.NAVIGATION_MODE_STANDARD:
if (mLogoView == null) {
@@ -472,19 +540,23 @@
}
break;
- case ActionBar.NAVIGATION_MODE_DROPDOWN_LIST:
+ case ActionBar.NAVIGATION_MODE_LIST:
throw new UnsupportedOperationException(
- "Inflating dropdown list navigation isn't supported yet!");
+ "Inflating list navigation isn't supported yet!");
case ActionBar.NAVIGATION_MODE_TABS:
throw new UnsupportedOperationException(
"Inflating tab navigation isn't supported yet!");
-
- case ActionBar.NAVIGATION_MODE_CUSTOM:
- if (mCustomNavView != null) {
+ }
+
+ if (mCustomNavView != null && (mDisplayOptions & ActionBar.DISPLAY_SHOW_CUSTOM) != 0) {
+ final ViewParent parent = mCustomNavView.getParent();
+ if (parent != this) {
+ if (parent instanceof ViewGroup) {
+ ((ViewGroup) parent).removeView(mCustomNavView);
+ }
addView(mCustomNavView);
}
- break;
}
}
@@ -513,6 +585,7 @@
}
public void setTabSelected(int position) {
+ ensureTabsExist();
final int tabCount = mTabLayout.getChildCount();
for (int i = 0; i < tabCount; i++) {
final View child = mTabLayout.getChildAt(i);
@@ -544,57 +617,40 @@
mContentHeight : MeasureSpec.getSize(heightMeasureSpec);
final int verticalPadding = getPaddingTop() + getPaddingBottom();
- int availableWidth = contentWidth - getPaddingLeft() - getPaddingRight();
+ final int paddingLeft = getPaddingLeft();
+ final int paddingRight = getPaddingRight();
final int height = maxHeight - verticalPadding;
final int childSpecHeight = MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST);
- if (mLogoView != null && mLogoView.getVisibility() != GONE) {
- availableWidth = measureChildView(mLogoView, availableWidth, childSpecHeight, 0);
- }
- if (mIconView != null && mIconView.getVisibility() != GONE) {
- availableWidth = measureChildView(mIconView, availableWidth, childSpecHeight, 0);
+ int availableWidth = contentWidth - paddingLeft - paddingRight;
+ int leftOfCenter = availableWidth / 2;
+ int rightOfCenter = leftOfCenter;
+
+ if (mHomeLayout.getVisibility() != GONE) {
+ availableWidth = measureChildView(mHomeLayout, availableWidth, childSpecHeight, 0);
+ leftOfCenter -= mHomeLayout.getMeasuredWidth();
}
if (mMenuView != null) {
availableWidth = measureChildView(mMenuView, availableWidth,
childSpecHeight, 0);
+ rightOfCenter -= mMenuView.getMeasuredWidth();
}
-
+
+ if (mTitleLayout != null && (mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0) {
+ availableWidth = measureChildView(mTitleLayout, availableWidth, childSpecHeight, 0);
+ leftOfCenter -= mTitleLayout.getMeasuredWidth();
+ }
+
switch (mNavigationMode) {
- case ActionBar.NAVIGATION_MODE_STANDARD:
- if (mTitleLayout != null) {
- measureChildView(mTitleLayout, availableWidth, childSpecHeight, 0);
- }
- break;
- case ActionBar.NAVIGATION_MODE_DROPDOWN_LIST:
+ case ActionBar.NAVIGATION_MODE_LIST:
if (mSpinner != null) {
mSpinner.measure(
MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST),
MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST));
- }
- break;
- case ActionBar.NAVIGATION_MODE_CUSTOM:
- if (mCustomNavView != null) {
- LayoutParams lp = mCustomNavView.getLayoutParams();
- final int customNavWidthMode = lp.width != LayoutParams.WRAP_CONTENT ?
- MeasureSpec.EXACTLY : MeasureSpec.AT_MOST;
- final int customNavWidth = lp.width >= 0 ?
- Math.min(lp.width, availableWidth) : availableWidth;
-
- // If the action bar is wrapping to its content height, don't allow a custom
- // view to MATCH_PARENT.
- int customNavHeightMode;
- if (mContentHeight <= 0) {
- customNavHeightMode = MeasureSpec.AT_MOST;
- } else {
- customNavHeightMode = lp.height != LayoutParams.WRAP_CONTENT ?
- MeasureSpec.EXACTLY : MeasureSpec.AT_MOST;
- }
- final int customNavHeight = lp.height >= 0 ?
- Math.min(lp.height, height) : height;
- mCustomNavView.measure(
- MeasureSpec.makeMeasureSpec(customNavWidth, customNavWidthMode),
- MeasureSpec.makeMeasureSpec(customNavHeight, customNavHeightMode));
+ final int spinnerWidth = mSpinner.getMeasuredWidth();
+ availableWidth -= spinnerWidth;
+ leftOfCenter -= spinnerWidth;
}
break;
case ActionBar.NAVIGATION_MODE_TABS:
@@ -602,10 +658,56 @@
mTabScrollView.measure(
MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST),
MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
+ final int tabWidth = mTabScrollView.getMeasuredWidth();
+ availableWidth -= tabWidth;
+ leftOfCenter -= tabWidth;
}
break;
}
+ if ((mDisplayOptions & ActionBar.DISPLAY_SHOW_CUSTOM) != 0 && mCustomNavView != null) {
+ final LayoutParams lp = generateLayoutParams(mCustomNavView.getLayoutParams());
+ final ActionBar.LayoutParams ablp = lp instanceof ActionBar.LayoutParams ?
+ (ActionBar.LayoutParams) lp : null;
+
+ int horizontalMargin = 0;
+ int verticalMargin = 0;
+ if (ablp != null) {
+ horizontalMargin = ablp.leftMargin + ablp.rightMargin;
+ verticalMargin = ablp.topMargin + ablp.bottomMargin;
+ }
+
+ // If the action bar is wrapping to its content height, don't allow a custom
+ // view to MATCH_PARENT.
+ int customNavHeightMode;
+ if (mContentHeight <= 0) {
+ customNavHeightMode = MeasureSpec.AT_MOST;
+ } else {
+ customNavHeightMode = lp.height != LayoutParams.WRAP_CONTENT ?
+ MeasureSpec.EXACTLY : MeasureSpec.AT_MOST;
+ }
+ final int customNavHeight = Math.max(0,
+ (lp.height >= 0 ? Math.min(lp.height, height) : height) - verticalMargin);
+
+ final int customNavWidthMode = lp.width != LayoutParams.WRAP_CONTENT ?
+ MeasureSpec.EXACTLY : MeasureSpec.AT_MOST;
+ int customNavWidth = Math.max(0,
+ (lp.width >= 0 ? Math.min(lp.width, availableWidth) : availableWidth)
+ - horizontalMargin);
+ final int hgrav = (ablp != null ? ablp.gravity : DEFAULT_CUSTOM_GRAVITY) &
+ Gravity.HORIZONTAL_GRAVITY_MASK;
+
+ // Centering a custom view is treated specially; we try to center within the whole
+ // action bar rather than in the available space.
+ if (hgrav == Gravity.CENTER_HORIZONTAL && lp.width == LayoutParams.MATCH_PARENT) {
+ customNavWidth = Math.min(leftOfCenter, rightOfCenter) * 2;
+ }
+
+ mCustomNavView.measure(
+ MeasureSpec.makeMeasureSpec(customNavWidth, customNavWidthMode),
+ MeasureSpec.makeMeasureSpec(customNavHeight, customNavHeightMode));
+ }
+
if (mContentHeight <= 0) {
int measuredHeight = 0;
final int count = getChildCount();
@@ -642,39 +744,89 @@
final int y = getPaddingTop();
final int contentHeight = b - t - getPaddingTop() - getPaddingBottom();
- if (mLogoView != null && mLogoView.getVisibility() != GONE) {
- x += positionChild(mLogoView, x, y, contentHeight);
- }
- if (mIconView != null && mIconView.getVisibility() != GONE) {
- x += positionChild(mIconView, x, y, contentHeight);
+ if (mHomeLayout.getVisibility() != GONE) {
+ x += positionChild(mHomeLayout, x, y, contentHeight);
}
+ if (mTitleLayout != null && (mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0) {
+ x += positionChild(mTitleLayout, x, y, contentHeight);
+ }
+
switch (mNavigationMode) {
case ActionBar.NAVIGATION_MODE_STANDARD:
- if (mTitleLayout != null) {
- x += positionChild(mTitleLayout, x, y, contentHeight);
- }
break;
- case ActionBar.NAVIGATION_MODE_DROPDOWN_LIST:
+ case ActionBar.NAVIGATION_MODE_LIST:
if (mSpinner != null) {
x += positionChild(mSpinner, x, y, contentHeight);
}
break;
- case ActionBar.NAVIGATION_MODE_CUSTOM:
- if (mCustomNavView != null) {
- x += positionChild(mCustomNavView, x, y, contentHeight);
- }
- break;
case ActionBar.NAVIGATION_MODE_TABS:
if (mTabScrollView != null) {
x += positionChild(mTabScrollView, x, y, contentHeight);
}
}
- x = r - l - getPaddingRight();
-
+ int menuLeft = r - l - getPaddingRight();
if (mMenuView != null) {
- x -= positionChildInverse(mMenuView, x, y, contentHeight);
+ positionChildInverse(mMenuView, menuLeft, y, contentHeight);
+ menuLeft -= mMenuView.getMeasuredWidth();
+ }
+
+ if (mCustomNavView != null && (mDisplayOptions & ActionBar.DISPLAY_SHOW_CUSTOM) != 0) {
+ LayoutParams lp = mCustomNavView.getLayoutParams();
+ final ActionBar.LayoutParams ablp = lp instanceof ActionBar.LayoutParams ?
+ (ActionBar.LayoutParams) lp : null;
+
+ final int gravity = ablp != null ? ablp.gravity : DEFAULT_CUSTOM_GRAVITY;
+ final int navWidth = mCustomNavView.getMeasuredWidth();
+
+ int topMargin = 0;
+ int bottomMargin = 0;
+ if (ablp != null) {
+ x += ablp.leftMargin;
+ menuLeft -= ablp.rightMargin;
+ topMargin = ablp.topMargin;
+ bottomMargin = ablp.bottomMargin;
+ }
+
+ int hgravity = gravity & Gravity.HORIZONTAL_GRAVITY_MASK;
+ // See if we actually have room to truly center; if not push against left or right.
+ if (hgravity == Gravity.CENTER_HORIZONTAL) {
+ final int centeredLeft = ((mRight - mLeft) - navWidth) / 2;
+ if (centeredLeft < x) {
+ hgravity = Gravity.LEFT;
+ } else if (centeredLeft + navWidth > menuLeft) {
+ hgravity = Gravity.RIGHT;
+ }
+ }
+
+ int xpos = 0;
+ switch (hgravity) {
+ case Gravity.CENTER_HORIZONTAL:
+ xpos = ((mRight - mLeft) - navWidth) / 2;
+ break;
+ case Gravity.LEFT:
+ xpos = x;
+ break;
+ case Gravity.RIGHT:
+ xpos = menuLeft - navWidth;
+ break;
+ }
+
+ int ypos = 0;
+ switch (gravity & Gravity.VERTICAL_GRAVITY_MASK) {
+ case Gravity.CENTER_VERTICAL:
+ ypos = ((mBottom - mTop) - mCustomNavView.getMeasuredHeight()) / 2;
+ break;
+ case Gravity.TOP:
+ ypos = getPaddingTop() + topMargin;
+ break;
+ case Gravity.BOTTOM:
+ ypos = getHeight() - getPaddingBottom() - mCustomNavView.getMeasuredHeight()
+ - bottomMargin;
+ break;
+ }
+ x += positionChild(mCustomNavView, xpos, ypos, contentHeight);
}
}
diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp
index f3b9357..c4056a4 100644
--- a/core/jni/android_util_AssetManager.cpp
+++ b/core/jni/android_util_AssetManager.cpp
@@ -701,6 +701,7 @@
static jint android_content_AssetManager_loadResourceValue(JNIEnv* env, jobject clazz,
jint ident,
+ jshort density,
jobject outValue,
jboolean resolve)
{
@@ -713,7 +714,7 @@
Res_value value;
ResTable_config config;
uint32_t typeSpecFlags;
- ssize_t block = res.getResource(ident, &value, false, &typeSpecFlags, &config);
+ ssize_t block = res.getResource(ident, &value, false, density, &typeSpecFlags, &config);
#if THROW_ON_BAD_ID
if (block == BAD_INDEX) {
jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
@@ -1703,7 +1704,7 @@
(void*) android_content_AssetManager_getResourceTypeName },
{ "getResourceEntryName","(I)Ljava/lang/String;",
(void*) android_content_AssetManager_getResourceEntryName },
- { "loadResourceValue","(ILandroid/util/TypedValue;Z)I",
+ { "loadResourceValue","(ISLandroid/util/TypedValue;Z)I",
(void*) android_content_AssetManager_loadResourceValue },
{ "loadResourceBagValue","(IILandroid/util/TypedValue;Z)I",
(void*) android_content_AssetManager_loadResourceBagValue },
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 2444fce..3635fab 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -532,6 +532,13 @@
android:description="@string/permdesc_sdcardWrite"
android:protectionLevel="dangerous" />
+ <!-- Allows an application to write to internal media storage -->
+ <permission android:name="android.permission.WRITE_MEDIA_STORAGE"
+ android:permissionGroup="android.permission-group.STORAGE"
+ android:label="@string/permlab_mediaStorageWrite"
+ android:description="@string/permdesc_mediaStorageWrite"
+ android:protectionLevel="signatureOrSystem" />
+
<!-- ============================================ -->
<!-- Permissions for low-level system interaction -->
<!-- ============================================ -->
diff --git a/core/res/res/drawable-hdpi/ic_ab_back_holo_dark.png b/core/res/res/drawable-hdpi/ic_ab_back_holo_dark.png
new file mode 100644
index 0000000..a8da981
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_ab_back_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_ab_back_holo_light.png b/core/res/res/drawable-hdpi/ic_ab_back_holo_light.png
new file mode 100644
index 0000000..af0f308
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_ab_back_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_select_all.png b/core/res/res/drawable-hdpi/ic_menu_select_all.png
deleted file mode 100644
index dde6741..0000000
--- a/core/res/res/drawable-hdpi/ic_menu_select_all.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_ab_back_holo_dark.png b/core/res/res/drawable-mdpi/ic_ab_back_holo_dark.png
new file mode 100644
index 0000000..7aae741
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_ab_back_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_ab_back_holo_light.png b/core/res/res/drawable-mdpi/ic_ab_back_holo_light.png
new file mode 100644
index 0000000..66ef51c
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_ab_back_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_select_all.png b/core/res/res/drawable-mdpi/ic_menu_select_all.png
deleted file mode 100644
index 37fd3cbd..0000000
--- a/core/res/res/drawable-mdpi/ic_menu_select_all.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/text_edit_paste_window.9.png b/core/res/res/drawable-mdpi/text_edit_paste_window.9.png
new file mode 100644
index 0000000..2738b62
--- /dev/null
+++ b/core/res/res/drawable-mdpi/text_edit_paste_window.9.png
Binary files differ
diff --git a/core/res/res/layout/text_edit_no_paste_window.xml b/core/res/res/layout/text_edit_no_paste_window.xml
new file mode 100644
index 0000000..f288e6f6
--- /dev/null
+++ b/core/res/res/layout/text_edit_no_paste_window.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:background="@android:drawable/text_edit_paste_window">
+
+ <ImageView android:id="@+id/paste_icon"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_centerVertical="true"
+ android:background="@android:drawable/ic_menu_paste_dark"
+ />
+
+ <TextView android:id="@+id/title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_centerVertical="true"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:text="@android:string/pasteDisabled"
+ android:layout_toRightOf="@id/paste_icon"
+ />
+
+</RelativeLayout>
diff --git a/core/res/res/layout/text_edit_paste_window.xml b/core/res/res/layout/text_edit_paste_window.xml
new file mode 100644
index 0000000..ee2c4d2
--- /dev/null
+++ b/core/res/res/layout/text_edit_paste_window.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:background="@android:drawable/text_edit_paste_window">
+
+ <ImageView android:id="@+id/paste_icon"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_centerVertical="true"
+ android:background="@android:drawable/ic_menu_paste_light"
+ />
+
+ <TextView android:id="@+id/title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_centerVertical="true"
+ android:textAppearance="?android:attr/textAppearanceMediumInverse"
+ android:text="@android:string/paste"
+ android:layout_toRightOf="@id/paste_icon"
+ />
+
+</RelativeLayout>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index dab627c..0cac7eb 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -556,6 +556,11 @@
<!-- Reference to a drawable that will be used to display a text selection
anchor for positioning the cursor within text. -->
<attr name="textSelectHandle" format="reference" />
+ <!-- The layout of the view that is displayed on top of the cursor to paste inside a
+ TextEdit field. -->
+ <attr name="textEditPasteWindowLayout" format="reference" />
+ <!-- Variation of textEditPasteWindowLayout displayed when the clipboard is empty. -->
+ <attr name="textEditNoPasteWindowLayout" format="reference" />
<!-- Theme to use for dialogs spawned from this theme. -->
<attr name="dialogTheme" format="reference" />
@@ -2393,6 +2398,11 @@
<!-- Reference to a drawable that will be used to display a text selection
anchor for positioning the cursor within text. -->
<attr name="textSelectHandle" />
+ <!-- The layout of the view that is displayed on top of the cursor to paste inside a
+ TextEdit field. -->
+ <attr name="textEditPasteWindowLayout" />
+ <!-- Variation of textEditPasteWindowLayout displayed when the clipboard is empty. -->
+ <attr name="textEditNoPasteWindowLayout" />
<!-- Height of a line of text. -->
<attr name="textLineHeight" />
@@ -4230,18 +4240,21 @@
<attr name="navigationMode">
<!-- Normal static title text -->
<enum name="normal" value="0" />
- <!-- The action bar will use a drop-down selection in place of title text. -->
- <enum name="dropdownList" value="1" />
- <!-- The action bar will use a series of horizontal tabs in place of title text. -->
- <enum name="tabBar" value="2" />
+ <!-- The action bar will use a selection list for navigation. -->
+ <enum name="listMode" value="1" />
+ <!-- The action bar will use a series of horizontal tabs for navigation. -->
+ <enum name="tabMode" value="2" />
</attr>
<!-- Options affecting how the action bar is displayed. -->
<attr name="displayOptions">
- <flag name="useLogo" value="1" />
- <flag name="hideHome" value="2" />
+ <flag name="useLogo" value="0x1" />
+ <flag name="showHome" value="0x2" />
+ <flag name="homeAsUp" value="0x4" />
+ <flag name="showTitle" value="0x8" />
+ <flag name="showCustom" value="0x10" />
+ <!-- DEPRECATED - Remove this later!! -->
+ <flag name="hideHome" value="0x1000" />
</attr>
- <!-- Specifies the color used to style the action bar. -->
- <attr name="colorFilter" format="color" />
<!-- Specifies title text used for navigationMode="normal" -->
<attr name="title" />
<!-- Specifies subtitle text used for navigationMode="normal" -->
@@ -4262,6 +4275,8 @@
<attr name="customNavigationLayout" format="reference" />
<!-- Specifies a fixed height. -->
<attr name="height" />
+ <!-- Specifies a drawable to use for the 'home as up' indicator. -->
+ <attr name="homeAsUpIndicator" format="reference" />
</declare-styleable>
<declare-styleable name="ActionMode">
@@ -4295,4 +4310,8 @@
<flag name="end" value="4" />
</attr>
</declare-styleable>
+
+ <declare-styleable name="ActionBar_LayoutParams">
+ <attr name="layout_gravity" />
+ </declare-styleable>
</resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 47bb5f8..d704366 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1357,6 +1357,7 @@
<public type="attr" name="dividerVertical" />
<public type="attr" name="buttonGroupStyle" />
<public type="attr" name="alertDialogButtonGroupStyle" />
+ <public type="attr" name="homeAsUpIndicator" />
<public type="anim" name="animator_fade_in" />
<public type="anim" name="animator_fade_out" />
@@ -1415,5 +1416,6 @@
<public type="attr" name="actionModeCutDrawable" />
<public type="attr" name="actionModeCopyDrawable" />
<public type="attr" name="actionModePasteDrawable" />
-
+ <public type="attr" name="textEditPasteWindowLayout" />
+ <public type="attr" name="textEditNoPasteWindowLayout" />
</resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 8b9bc43..b427a0e 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1231,6 +1231,11 @@
<string name="permdesc_sdcardWrite" product="default">Allows an application to write to the SD card.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permlab_mediaStorageWrite" product="default">modify/delete internal media storage contents</string>
+ <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permdesc_mediaStorageWrite" product="default">Allows an application to modify the contents of the internal media storage.</string>
+
+ <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permlab_cache_filesystem">access the cache filesystem</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_cache_filesystem">Allows an application to read and write the cache filesystem.</string>
@@ -1961,9 +1966,12 @@
<!-- Item on EditText context menu. This action is used to cut selected the text into the clipboard. -->
<string name="copy">Copy</string>
- <!-- Item on EditText context menu. This action is used t o paste from the clipboard into the eidt field -->
+ <!-- Item on EditText context menu. This action is used to paste from the clipboard into the eidt field -->
<string name="paste">Paste</string>
+ <!-- Text displayed in a popup dialog in TextEdit when the clipboard is empty. 'paste' is used otherwise. [CHAR LIMIT=20] -->
+ <string name="pasteDisabled">Nothing to paste</string>
+
<!-- Item on EditText context menu. This action is used to copy a URL from the edit field into the clipboard. -->
<string name="copyUrl">Copy URL</string>
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 61167b5..adf1715 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -403,6 +403,8 @@
<item name="android:textSelectHandleLeft">?android:attr/textSelectHandleLeft</item>
<item name="android:textSelectHandleRight">?android:attr/textSelectHandleRight</item>
<item name="android:textSelectHandle">?android:attr/textSelectHandle</item>
+ <item name="android:textEditPasteWindowLayout">?android:attr/textEditPasteWindowLayout</item>
+ <item name="android:textEditNoPasteWindowLayout">?android:attr/textEditNoPasteWindowLayout</item>
</style>
<style name="Widget.TextView.ListSeparator">
@@ -909,7 +911,7 @@
<style name="Widget.ActionBar">
<item name="android:background">@android:drawable/action_bar_background</item>
- <item name="android:displayOptions">useLogo</item>
+ <item name="android:displayOptions">useLogo|showHome|showTitle</item>
<item name="android:divider">@android:drawable/action_bar_divider</item>
<item name="android:height">?android:attr/actionBarSize</item>
<item name="android:paddingLeft">0dip</item>
@@ -1534,6 +1536,7 @@
<item name="android:subtitleTextStyle">@android:style/TextAppearance.Holo.Widget.ActionBar.Subtitle</item>
<item name="android:background">@null</item>
<item name="android:divider">?android:attr/dividerVertical</item>
+ <item name="android:homeAsUpIndicator">@android:drawable/ic_ab_back_holo_dark</item>
</style>
<!-- Light widget styles -->
@@ -1786,6 +1789,7 @@
<item name="android:titleTextStyle">@android:style/TextAppearance.Holo.Widget.ActionBar.Title</item>
<item name="android:subtitleTextStyle">@android:style/TextAppearance.Holo.Widget.ActionBar.Subtitle</item>
<item name="android:background">@null</item>
+ <item name="android:homeAsUpIndicator">@android:drawable/ic_ab_back_holo_light</item>
</style>
<!-- Animation Styles -->
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index 552e7e5..eeefa9e 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -166,6 +166,8 @@
<item name="textSelectHandleRight">@android:drawable/text_select_handle_right</item>
<item name="textSelectHandle">@android:drawable/text_select_handle_middle</item>
<item name="textSelectHandleWindowStyle">@android:style/Widget.TextSelectHandle</item>
+ <item name="textEditPasteWindowLayout">@android:layout/text_edit_paste_window</item>
+ <item name="textEditNoPasteWindowLayout">@android:layout/text_edit_no_paste_window</item>
<!-- Widget styles -->
<item name="absListViewStyle">@android:style/Widget.AbsListView</item>
diff --git a/data/etc/platform.xml b/data/etc/platform.xml
index 439fc90..f458576 100644
--- a/data/etc/platform.xml
+++ b/data/etc/platform.xml
@@ -58,6 +58,10 @@
<group gid="sdcard_rw" />
</permission>
+ <permission name="android.permission.WRITE_MEDIA_STORAGE" >
+ <group gid="media_rw" />
+ </permission>
+
<permission name="android.permission.ACCESS_USB" >
<group gid="usb" />
</permission>
diff --git a/docs/html/sdk/adding-components.jd b/docs/html/sdk/adding-components.jd
index 63c577e..755f200 100644
--- a/docs/html/sdk/adding-components.jd
+++ b/docs/html/sdk/adding-components.jd
@@ -6,7 +6,7 @@
<div id="qv">
<h2>Quickview</h2>
<ul>
- <li>Use the Android SDK and AVD Manager to
+ <li>Use the Android SDK and AVD Manager to
set up your SDK and keep it up-to-date.</li>
</ul>
@@ -25,7 +25,7 @@
<p>Adding and updating components in your Android SDK is fast and easy. To
perform an update, use the <strong>Android SDK and AVD Manager</strong> to
install or update the individual SDK components that you need. The Android SDK
-and AVD Manager tool is included in the <a href="index.html">Android SDK
+and AVD Manager tool is included in the <a href="index.html">Android SDK
download</a>.</p>
<p>It only takes a couple of clicks to install individual versions of the
@@ -53,19 +53,19 @@
href="{@docRoot}sdk/tools-notes.html">SDK Tools</a> document for ADT
Plugin compatibility.</p>
-<div style="TEXT-ALIGN:left; width:600px;">
-<img src="{@docRoot}images/sdk_manager_packages.png"
-style="padding-bottom:0;margin-bottom:0;" />
+<div style="TEXT-ALIGN:left; width:600px;">
+<img src="{@docRoot}images/sdk_manager_packages.png"
+style="padding-bottom:0;margin-bottom:0;" />
<p class="caption" style="margin:0 0 1.5em 1em;padding:0 0 0
-1em;"><strong>Figure 1.</strong> The Android SDK and AVD Manager's
+1em;"><strong>Figure 1.</strong> The Android SDK and AVD Manager's
<strong>Available Packages</strong>
panel, which shows the SDK components that are
available for you to download into your environment. </p>
-</div>
+</div>
<h2 id="launching">Launching the Android SDK and AVD Manager</h2>
-<p>The Android SDK and AVD Manager is the tool that you use to install and
+<p>The Android SDK and AVD Manager is the tool that you use to install and
upgrade SDK components in your development environment. </p>
<p>You can access the tool in any of three ways:</p>
@@ -83,15 +83,15 @@
<ol>
<li>Open Eclipse</li>
-<li>Select <strong>Window</strong> > <strong>Android SDK and AVD
+<li>Select <strong>Window</strong> > <strong>Android SDK and AVD
Manager</strong>.</li>
</ol>
-<h4>Launching from the setup script (Windows only)</h4>
+<h4>Launching from the SDK Manager script (Windows only)</h4>
<p>For Windows only, the SDK includes a script that invokes the Android SDK and
-AVD Manager. To launch the tool using the script, double-click "SDK
-Setup.exe" at the root of the the SDK directory.</p>
+AVD Manager. To launch the tool using the script, double-click {@code SDK
+Manager.exe} at the root of the the SDK directory.</p>
<h4>Launching from a command line</h4>
@@ -100,37 +100,39 @@
<ol>
<li>Navigate to the <code><<em>sdk</em>>/tools/</code> directory.</li>
-<li>Execute the {@code android} tool command with no options.
+<li>Execute the {@code android} tool command with no options.
<pre style="width:400px">$ android</pre></li>
</ol>
<h2 id="InstallingComponents">Installing SDK Components</h2>
-<p class="caution"><strong>Important:</strong> Before you install SDK components,
-we recommend that you disable any antivirus programs that may be running on
-your computer.</p>
+<p class="caution"><strong>Caution:</strong> Before you install SDK components,
+we recommend that you disable any antivirus software that may be running on
+your computer. There are cases in which antivirus software on Windows is known to interfere with the
+installation process, so we suggest you disable your antivirus until installation is
+complete.</p>
<p>Follow these steps to install new SDK components in your environment:</p>
<ol>
<li>Launch the Android SDK and AVD Manager as described in the section above.</li>
<li>Select <strong>Available Packages</strong> in the left panel.
- This will reveal all of the components that are currently available for download
+ This will reveal all of the components that are currently available for download
from the SDK repository.</li>
<li>Select the component(s) you'd like to install and click <strong>Install
- Selected</strong>. If you aren't sure which packages to select, read <a
+ Selected</strong>. If you aren't sure which packages to select, read <a
href="installing.html#which">Which components do I need?</a>.</li>
<li>Verify and accept the components you want and click <strong>Install
Accepted</strong>. The components will now be installed into your existing
Android SDK directories.</li>
</ol>
-<p>New platforms are automatically saved into the
+<p>New platforms are automatically saved into the
<code><<em>sdk</em>>/platforms/</code> directory of your SDK;
new add-ons are saved in the <code><<em>sdk</em>>/add-ons/</code>
-directory; samples are saved in the
-<code><<em>sdk</em>>/samples/android-<<em>level</em>>/</code>;
+directory; samples are saved in the
+<code><<em>sdk</em>>/samples/android-<<em>level</em>>/</code>;
and new documentation is saved in the existing
<code><<em>sdk</em>>/docs/</code> directory (old docs are replaced).</p>
@@ -184,10 +186,10 @@
<h2 id="AddingSites">Adding New Sites</h2>
<p>By default, <strong>Available Packages</strong> only shows the default
-repository site, which offers platforms, SDK tools, documentation, the
-Google APIs Add-on, and other components. You can add other sites that host
+repository site, which offers platforms, SDK tools, documentation, the
+Google APIs Add-on, and other components. You can add other sites that host
their own Android SDK add-ons, then download the SDK add-ons
-from those sites.</p>
+from those sites.</p>
<p>For example, a mobile carrier or device manufacturer might offer additional
API libraries that are supported by their own Android-powered devices. In order
@@ -199,7 +201,7 @@
<ol>
<li>Select <strong>Available Packages</strong> in the left panel.</li>
- <li>Click <strong>Add Site</strong> and enter the URL of the
+ <li>Click <strong>Add Site</strong> and enter the URL of the
{@code repository.xml} file. Click <strong>OK</strong>.</li>
</ol>
<p>Any SDK components available from the site will now be listed under
diff --git a/docs/html/sdk/index.jd b/docs/html/sdk/index.jd
index 7016eee..2e59801 100644
--- a/docs/html/sdk/index.jd
+++ b/docs/html/sdk/index.jd
@@ -1,27 +1,27 @@
page.title=Android SDK
sdk.redirect=0
-sdk.win_download=android-sdk_r07-windows.zip
-sdk.win_bytes=23669664
-sdk.win_checksum=69c40c2d2e408b623156934f9ae574f0
+sdk.win_installer=installer_r08-windows.exe
+sdk.win_installer_bytes=TODO
+sdk.win_installer_checksum=TODO
-sdk.mac_download=android-sdk_r07-mac_x86.zip
-sdk.mac_bytes=19229546
-sdk.mac_checksum=0f330ed3ebb36786faf6dc72b8acf819
+sdk.win_download=android-sdk_r08-windows.zip
+sdk.win_bytes=TODO
+sdk.win_checksum=TODO
-sdk.linux_download=android-sdk_r07-linux_x86.tgz
-sdk.linux_bytes=17114517
-sdk.linux_checksum=e10c75da3d1aa147ddd4a5c58bfc3646
+sdk.mac_download=android-sdk_r08-mac_x86.zip
+sdk.mac_bytes=TODO
+sdk.mac_checksum=TODO
+
+sdk.linux_download=android-sdk_r08-linux_x86.tgz
+sdk.linux_bytes=TODO
+sdk.linux_checksum=TODO
@jd:body
<h2 id="quickstart">Quick Start</h2>
-<p>The steps below provide an overview of how to get started with the Android
-SDK. For detailed instructions, start with the <a
-href="{@docRoot}sdk/installing.html">Installing the SDK</a> guide. </p>
-
<p><strong>1. Prepare your development computer</strong></p>
<p>Read the <a href="{@docRoot}sdk/requirements.html">System Requirements</a>
@@ -34,38 +34,37 @@
<p><strong>2. Download and install the SDK starter package</strong></p>
-<p>Select a starter package from the table at the top of this page and download
-it to your development computer. To install the SDK, simply unpack the starter
-package to a safe location and then add the location to your PATH. </p>
+<p>Download a starter package from the table above onto your development computer.
+If you're using Windows, we recommend that you download the installer (the {@code .exe} file),
+which will launch a Wizard to guide you through the installation and check your computer for
+required software. Otherwise, download the SDK starter package ({@code .zip} or {@code .tgz})
+appropriate for your system, unpack it to a safe location, then add the location to your PATH
+environment variable. </p>
<p><strong>3. Install the ADT Plugin for Eclipse</strong></p>
-<p>If you are developing in Eclipse, set up a remote update site at
-<code>https://dl-ssl.google.com/android/eclipse/</code>. Install the Android
-Development Tools (ADT) Plugin, restart Eclipse, and set the "Android"
-preferences in Eclipse to point to the SDK install location. For detailed
-instructions, see <a href="{@docRoot}sdk/eclipse-adt.html">ADT Plugin
+<p>If you are developing in Eclipse, add a new remote update site with the URL
+<code>https://dl-ssl.google.com/android/eclipse/</code>. Install the Android
+Development Tools (ADT) Plugin from that site, restart Eclipse, and set the "Android"
+preferences in Eclipse to point to the Android SDK directory (installed in the previous step). For
+detailed instructions to setup Eclipse, see <a href="{@docRoot}sdk/eclipse-adt.html">ADT Plugin
for Eclipse</a>.</p>
<p><strong>4. Add Android platforms and other components to your SDK</strong></p>
-<p>Use the Android SDK and AVD Manager, included in the SDK starter package, to
-add one or more Android platforms (for example, Android 1.6 or Android 2.2) and
-other components to your SDK. If you aren't sure what to add, see <a
+<p>Launch the <em>Android SDK and AVD Manager</em> by executing {@code SDK Manager.exe} (Windows) or
+{@code android} (Mac/Linux) from the SDK's {@code tools/} directory (if you used the Windows
+installer, this is launched for you when the Wizard is complete). Add some Android platforms
+(such as Android 1.6 and Android 2.3) and other components (such as documentation) to your SDK. If
+you aren't sure what to add, see <a
href="installing.html#which">Which components do I need?</a></p>
-<p>To launch the Android SDK and AVD Manager on Windows, execute <code>SDK
-Setup.exe</code>, at the root of the SDK directory. On Mac OS X or Linux,
-execute the <code>android</code> tool in the <code><sdk>/tools/</code>
-folder. For detailed instructions, see <a
-href="{@docRoot}sdk/adding-components.html">Adding SDK Components</a>.</p>
-
<p><strong>Done!</strong></p>
-<p>If you are new to Android, you can use the <a
-href="{@docRoot}resources/tutorials/hello-world.html">Hello World</a> tutorial to
-get started quickly. <a href="{@docRoot}sdk/installing.html#NextSteps">Next
-Steps</a> offers other suggestions of how to begin.</p>
+<p>To write your first Android application, see the <a
+href="{@docRoot}resources/tutorials/hello-world.html">Hello World</a> tutorial. Also see <a
+href="{@docRoot}sdk/installing.html#NextSteps">Next
+Steps</a> for other suggestions about how to get started.</p>
-<p>For a more detailed guide to installing and setting up the SDK, read <a
+<p>For a more detailed guide to installing and setting up the SDK, read <a
href="installing.html">Installing the SDK</a>.</p>
diff --git a/docs/html/sdk/installing.jd b/docs/html/sdk/installing.jd
index 73190a0..8484bea 100644
--- a/docs/html/sdk/installing.jd
+++ b/docs/html/sdk/installing.jd
@@ -29,20 +29,20 @@
</div>
</div>
-<p>This page describes how to install the Android SDK
+<p>This page describes how to install the Android SDK
and set up your development environment for the first time.</p>
-<p>If you encounter any problems during installation, see the
+<p>If you encounter any problems during installation, see the
<a href="#troubleshooting">Troubleshooting</a> section at the bottom of
this page.</p>
<h4>Updating?</h4>
-<p>If you are currently using the Android 1.6 SDK or later and want to update
-to the latest tools or platforms, you do not need to install a new SDK. Instead,
-you can simply update the individual components in your SDK using the
-Android SDK and AVD Manager tool. For information about how to do that, see <a
-href="{@docRoot}sdk/adding-components.html#UpdatingComponents">Updating SDK
+<p>If you are currently using the Android 1.6 SDK or later and want to update
+to the latest tools or platforms, you do not need to install a new SDK. Instead,
+you can simply update the individual components in your SDK using the
+Android SDK and AVD Manager tool. For information about how to do that, see <a
+href="{@docRoot}sdk/adding-components.html#UpdatingComponents">Updating SDK
Components</a></p>
<p>If you are using Android 1.5 SDK or earlier, you should install a new SDK as
@@ -54,65 +54,71 @@
<p>Before getting started with the Android SDK, take a moment to confirm that
your development computer meets the <a href="requirements.html">System
-Requirements</a>. In particular, you may need to install the <a
-href="http://java.sun.com/javase/downloads/index.jsp">JDK</a> before
+Requirements</a>. In particular, you may need to install the <a
+href="http://java.sun.com/javase/downloads/index.jsp">JDK</a> before
continuing, if it's not already installed on your computer. </p>
<p>If you will be developing in Eclipse with the Android Development
Tools (ADT) Plugin — the recommended path if you are new to
Android — make sure that you have a suitable version of Eclipse
-installed on your computer (3.4 or newer is recommended). If you need
-to install Eclipse, you can download it from this location: </p>
-
+installed on your computer (3.4 or newer is recommended). If you need
+to install Eclipse, you can download it from this location: </p>
+
<p style="margin-left:2em;"><a href=
-"http://www.eclipse.org/downloads/">http://www.eclipse.org/downloads/</a></p>
-
-<p>A Java or RCP version of Eclipse is recommended. For Eclipse 3.5, the
-"Eclipse Classic" version is recommended.</p>
+"http://www.eclipse.org/downloads/">http://www.eclipse.org/downloads/</a></p>
+
+<p>A Java or RCP version of Eclipse is recommended. For Eclipse 3.5, the
+"Eclipse Classic" version is recommended.</p>
<h2 id="Installing">Step 2. Downloading the SDK Starter Package</h2>
<p>The first step in setting up your environment for developing Android applications
is downloading the Android SDK starter package. The starter package is not a full
-development environment — it includes only the core SDK Tools, which you can
-use to download the rest of the SDK components. </p>
+development environment — it includes only the core SDK Tools, which you can
+use to download the rest of the SDK components (such as the platform system images). </p>
<p>You can get the latest version of the SDK starter package from the <a
href="{@docRoot}sdk/index.html">SDK download page</a>. Make sure to download the
package that is appropriate for your development computer.</p>
-<p>After downloading, unpack the Android SDK archive to a safe location on your
-machine. By default, the SDK files are unpacked into a directory named
-<code>android-sdk-<machine-platform></code>. Make a note of the name and
-location of the unpacked SDK directory on your system — you will need to
-refer to the SDK directory later, when setting up the ADT plugin or when using
-the SDK tools.</p>
+<p class="note"><strong>Note:</strong> If you're using Windows, we recommend that you download
+the SDK installer (the {@code .exe} file from the download table). It will guide you through the
+installation process and check your computer for the required software.</p>
-<p>Optionally, you may want to add the location of the SDK's primary
-<code>tools</code> directory to your system <code>PATH</code>. The primary
-<code>tools/</code> directory is located at the root of the SDK folder. Adding
-<code>tools</code> to your path lets you run Android Debug Bridge (adb) and the
-other command line <a
+<p>If you downloaded a {@code .zip} of {@code .tgz} (instead of using the SDK installer), unpack the
+Android SDK archive to a safe location on your machine. By default, the SDK files are unpacked into
+a directory named <code>android-sdk-<machine-platform></code>.</p>
+
+<p>Make a note of the name and
+location of the unpacked SDK directory on your system — you will need to
+refer to the SDK directory later, when setting up the ADT plugin and when using
+the SDK tools from command line.</p>
+
+<p>Optionally, you might want to add the location of the SDK's primary
+<code>tools</code> directory and the additional {@code platform-tools/} directory to your system
+<code>PATH</code>. Both tool directories are located at the root of the SDK folder. Adding
+<code>tools/</code> and {@code platform-tools/} to your path lets you run Android Debug Bridge (adb)
+and the other command line <a
href="{@docRoot}guide/developing/tools/index.html">tools</a> without needing to
-supply the full path to the tools directory. </p>
+supply the full path to the tool directories. </p>
<ul>
<li>On Linux, edit your <code>~/.bash_profile</code> or <code>~/.bashrc</code> file. Look
for a line that sets the PATH environment variable and add the
- full path to the <code>tools/</code> directory to it. If you don't
+ full path to the <code>tools/</code> and {@code platform-tools/} directories to it. If you don't
see a line setting the path, you can add one:</li>
- <ul><code>export PATH=${PATH}:<em><your_sdk_dir></em>/tools</code></ul>
+ <ul><code>export PATH=${PATH}:<your_sdk_dir>/tools:<your_sdk_dir>/platform-tools</code></ul>
<li>On a Mac OS X, look in your home directory for <code>.bash_profile</code> and
- proceed as for Linux. You can create the <code>.bash_profile</code> if
+ proceed as for Linux. You can create the <code>.bash_profile</code> if
you haven't already set one up on your machine. </li>
- <li>On Windows, right-click on My Computer, and select Properties.
+ <li>On Windows, right-click on My Computer, and select Properties.
Under the Advanced tab, hit the Environment Variables button, and in the
- dialog that comes up, double-click on Path (under System Variables). Add the full path to the
- <code>tools/</code> directory to the path. </li>
+ dialog that comes up, double-click on Path (under System Variables). Add the full path to the
+ <code>tools/</code> and {@code platform-tools/} directories to the path. </li>
</ul>
<p>If you will be using the Eclipse IDE as your development environment, the
@@ -203,11 +209,11 @@
<code>com.google.android.maps</code> library. You can also add additional
repositories, so that you can download other SDK add-ons, where available. </li>
-<li><strong>USB Driver for Windows</strong> — Contains driver files
+<li><strong>USB Driver for Windows</strong> — Contains driver files
that you can install on your Windows computer, so that you can run and debug
your applications on an actual device. You <em>do not</em> need the USB driver unless
you plan to debug your application on an actual Android-powered device. If you
-develop on Mac OS X or Linux, you do not need a special driver to debug
+develop on Mac OS X or Linux, you do not need a special driver to debug
your application on an Android-powered device.</li>
<li><strong>Samples</strong> — Contains the sample code and apps available
@@ -226,15 +232,15 @@
components for download, and then install the selected components in your SDK
environment. </p>
-<div style="TEXT-ALIGN:left;width:600px;">
-<img src="/images/sdk_manager_packages.png"
-style="padding-bottom:0;margin-bottom:0;" />
+<div style="TEXT-ALIGN:left;width:600px;">
+<img src="/images/sdk_manager_packages.png"
+style="padding-bottom:0;margin-bottom:0;" />
<p class="caption" style="margin:0 0 1.5em 1em;padding:0 0 0
-1em;"><strong>Figure 1.</strong> The Android SDK and AVD Manager's
+1em;"><strong>Figure 1.</strong> The Android SDK and AVD Manager's
<strong>Available Packages</strong>
panel, which shows the SDK components that are
available for you to download into your environment. </p>
-</div>
+</div>
<h3 id="which">Which components do I need?</h3>
@@ -257,8 +263,8 @@
<td style="font-size:.9em;background-color:#FFE;color:gray">SDK Tools</td>
<td style="font-size:.9em;background-color:#FFE;color:gray">If you've installed
the SDK starter package, then you already have this component preinstalled. The
-SDK Tools component is required — you can't develop or build an application
-without it. </td>
+SDK Tools and the SDK Platform-tools components are required — you can't develop or build an
+application without these. Make sure you keep these up to date.</td>
</tr>
<tr>
@@ -324,8 +330,8 @@
to add components, see the <a href="{@docRoot}sdk/adding-components.html">Adding
SDK Components</a> document. </p>
-<p>For revision notes and other detailed information about individual SDK
-components, see the documents listed under "Downloadable SDK Components" in
+<p>For revision notes and other detailed information about individual SDK
+components, see the documents listed under "Downloadable SDK Components" in
the navigation at left.</p>
@@ -335,7 +341,7 @@
and add-ons that you need, open the SDK directory and take a look at what's
inside.</p>
-<p>The table below describes the full SDK directory contents, with components
+<p>The table below describes the full SDK directory contents, with components
installed. </p>
<table>
@@ -351,10 +357,19 @@
<tr>
<td colspan="3"><code>docs/</code></td>
<td>A full set of documentation in HTML format, including the Developer's Guide,
-API Reference, and other information. To read the documentation, load the
+API Reference, and other information. To read the documentation, load the
file <code>offline.html</code> in a web browser.</td>
</tr>
<tr>
+<td colspan="3"><code>platform-tools/</code></td>
+<td>Contains development tools that may be updated with each platform release (from the <em>Android
+SDK Platform-tools</em> component). Tools in here include {@code adb}, {@code dexdump}, and others
+others that you don't typically use directly. These tools are separate from the generic development
+tools in the {@code tools/} directory, because these tools may be updated in order to support new
+features in the latest Android platform, whereas the other tools have no dependencies on the
+platform version.</td>
+</tr>
+<tr>
<td colspan="3"><code>platforms/</code></td>
<td>Contains a set of Android platform versions that you can develop
applications against, each in a separate directory. </td>
@@ -362,7 +377,7 @@
<tr>
<td style="width:2em;border-bottom-color:white;"></td>
<td colspan="2"><code><em><platform></em>/</code></td>
-<td>Platform version directory, for example "android-1.6". All platform version
+<td>Platform version directory, for example "android-1.6". All platform version
directories contain a similar set of files and subdirectory structure.</td>
</tr>
@@ -376,8 +391,8 @@
<td style="width:2em;border-bottom-color:white;"></td>
<td style="width:2em;border-bottom-color:white;"></td>
<td><code>images/</code></td>
-<td>Storage area for default disk images, including the Android system image,
-the default userdata image, the default ramdisk image, and more. The images
+<td>Storage area for default disk images, including the Android system image,
+the default userdata image, the default ramdisk image, and more. The images
are used in emulator sessions.</td>
</tr>
<tr>
@@ -397,7 +412,8 @@
<td style="width:2em;border-bottom-color:white;"></td>
<td style="width:2em;border-bottom-color:white;"></td>
<td><code>tools/</code></td>
-<td>Any development tools that are specific to the platform version.</td>
+<td>This directory is used only by SDK Tools r7 and below for development tools that are specific to
+this platform version—it's not used by SDK Tools r8 and above.</td>
</tr>
<tr>
<td style="width:2em;"></td>
@@ -411,18 +427,21 @@
<td>Sample code and apps that are specific to platform version.</td>
</tr>
<td colspan="3"><code>tools/</code></td>
-<td>Contains the set of development and profiling tools available to you, such
-as the emulator, the <code>android</code> tool, adb, ddms, and more.</td>
+<td>Contains the set of development and profiling tools that are platform-independent, such
+as the emulator, the AVD and SDK Manager, adb, ddms, hierarchyviewer and more. The tools in
+this directory may be updated at any time (from the <em>Android SDK Tools</em> component),
+independent of platform releases, whereas the tools in {@code platform-tools/} may be updated based
+on the latest platform release.</td>
</tr>
<tr>
<td colspan="3"><code>SDK Readme.txt</code></td>
-<td>A file that explains how to perform the initial setup of your SDK,
-including how to launch the Android SDK and AVD Manager tool on all
+<td>A file that explains how to perform the initial setup of your SDK,
+including how to launch the Android SDK and AVD Manager tool on all
platforms</td>
</tr>
<tr>
-<td colspan="3"><code>SDK Setup.exe</code></td>
-<td>Windows SDK only. A shortcut that launches the Android SDK and AVD
+<td colspan="3"><code>SDK Manager.exe</code></td>
+<td>Windows SDK only. A shortcut that launches the Android SDK and AVD
Manager tool, which you use to add components to your SDK. </td>
</tr>
<!--<tr>
@@ -447,7 +466,7 @@
</li>
</ul>
-<p class="caution">Following the Hello World tutorial is an essential
+<p class="caution">Following the Hello World tutorial is an essential
first step in getting started with Android development. </p>
<p><strong>Learn about Android</strong></p>
@@ -481,20 +500,20 @@
<ul>
<li>The <a href="{@docRoot}resources/tutorials/notepad/index.html">
- Notepad Tutorial</a> shows you how to build a full Android application
- and provides helpful commentary on the Android system and API. The
+ Notepad Tutorial</a> shows you how to build a full Android application
+ and provides helpful commentary on the Android system and API. The
Notepad tutorial helps you bring together the important design
- and architectural concepts in a moderately complex application.
+ and architectural concepts in a moderately complex application.
</li>
</ul>
-<p class="caution">Following the Notepad tutorial is an excellent
+<p class="caution">Following the Notepad tutorial is an excellent
second step in getting started with Android development. </p>
<p><strong>Explore some code</strong></p>
<ul>
<li>The Android SDK includes sample code and applications for each platform
-version. You can browse the samples in the <a
+version. You can browse the samples in the <a
href="{@docRoot}resources/index.html">Resources</a> tab or download them
into your SDK using the Android SDK and AVD Manager. Once you've downloaded the
samples, you'll find them in
@@ -517,7 +536,7 @@
<ul>
<li>If you need help installing and configuring Java on your
- development machine, you might find these resources helpful:
+ development machine, you might find these resources helpful:
<ul>
<li><a href="https://help.ubuntu.com/community/Java">https://help.ubuntu.com/community/Java </a></li>
<li><a href="https://help.ubuntu.com/community/Java">https://help.ubuntu.com/community/JavaInstallation</a></li>
@@ -537,7 +556,7 @@
eclipse.org (<a
href="http://www.eclipse.org/downloads/">http://www.eclipse.org/
downloads/</a>). A Java or RCP version of Eclipse is recommended.</li>
- <li>Follow the steps given in previous sections to install the SDK
+ <li>Follow the steps given in previous sections to install the SDK
and the ADT plugin. </li>
</ol>
</li>
diff --git a/graphics/java/android/renderscript/RenderScriptGL.java b/graphics/java/android/renderscript/RenderScriptGL.java
index 0477d75..5fe69cd 100644
--- a/graphics/java/android/renderscript/RenderScriptGL.java
+++ b/graphics/java/android/renderscript/RenderScriptGL.java
@@ -141,6 +141,13 @@
nContextSetSurface(w, h, mSurface);
}
+ public int getHeight() {
+ return mHeight;
+ }
+
+ public int getWidth() {
+ return mWidth;
+ }
void pause() {
validate();
diff --git a/graphics/java/android/renderscript/ScriptC.java b/graphics/java/android/renderscript/ScriptC.java
index 5959be4..73f42de 100644
--- a/graphics/java/android/renderscript/ScriptC.java
+++ b/graphics/java/android/renderscript/ScriptC.java
@@ -76,78 +76,5 @@
rs.nScriptCSetScript(pgm, 0, pgmLength);
return rs.nScriptCCreate();
}
-
- public static class Builder extends Script.Builder {
- byte[] mProgram;
- int mProgramLength;
-
- public Builder(RenderScript rs) {
- super(rs);
- }
-
- public void setScript(String s) {
- try {
- mProgram = s.getBytes("UTF-8");
- mProgramLength = mProgram.length;
- } catch (java.io.UnsupportedEncodingException e) {
- throw new RuntimeException(e);
- }
- }
-
- public void setScript(Resources resources, int id) {
- InputStream is = resources.openRawResource(id);
- try {
- try {
- setScript(is);
- } finally {
- is.close();
- }
- } catch(IOException e) {
- throw new Resources.NotFoundException();
- }
- }
-
- public void setScript(InputStream is) throws IOException {
- byte[] buf = new byte[1024];
- int currentPos = 0;
- while(true) {
- int bytesLeft = buf.length - currentPos;
- if (bytesLeft == 0) {
- byte[] buf2 = new byte[buf.length * 2];
- System.arraycopy(buf, 0, buf2, 0, buf.length);
- buf = buf2;
- bytesLeft = buf.length - currentPos;
- }
- int bytesRead = is.read(buf, currentPos, bytesLeft);
- if (bytesRead <= 0) {
- break;
- }
- currentPos += bytesRead;
- }
- mProgram = buf;
- mProgramLength = currentPos;
- }
-
- static synchronized ScriptC internalCreate(Builder b) {
- b.mRS.nScriptCBegin();
-
- android.util.Log.e("rs", "len = " + b.mProgramLength);
- b.mRS.nScriptCSetScript(b.mProgram, 0, b.mProgramLength);
-
- int id = b.mRS.nScriptCCreate();
- ScriptC obj = new ScriptC(id, b.mRS);
- return obj;
- }
-
- public void addDefine(String name, int value) {}
- public void addDefine(String name, float value) {}
- public void addDefines(Class cl) {}
- public void addDefines(Object o) {}
- void addDefines(Field[] fields, int mask, Object o) {}
-
- public ScriptC create() {
- return internalCreate(this);
- }
- }
}
diff --git a/include/media/IMediaPlayer.h b/include/media/IMediaPlayer.h
index a1ce113..3d77278 100644
--- a/include/media/IMediaPlayer.h
+++ b/include/media/IMediaPlayer.h
@@ -48,8 +48,6 @@
virtual status_t setAudioStreamType(int type) = 0;
virtual status_t setLooping(int loop) = 0;
virtual status_t setVolume(float leftVolume, float rightVolume) = 0;
- virtual status_t suspend() = 0;
- virtual status_t resume() = 0;
virtual status_t setAuxEffectSendLevel(float level) = 0;
virtual status_t attachAuxEffect(int effectId) = 0;
diff --git a/include/media/MediaPlayerInterface.h b/include/media/MediaPlayerInterface.h
index eae0d7b..2d55a55 100644
--- a/include/media/MediaPlayerInterface.h
+++ b/include/media/MediaPlayerInterface.h
@@ -120,8 +120,6 @@
virtual status_t reset() = 0;
virtual status_t setLooping(int loop) = 0;
virtual player_type playerType() = 0;
- virtual status_t suspend() { return INVALID_OPERATION; }
- virtual status_t resume() { return INVALID_OPERATION; }
virtual void setNotifyCallback(void* cookie, notify_callback_f notifyFunc) {
mCookie = cookie; mNotify = notifyFunc; }
diff --git a/include/media/mediaplayer.h b/include/media/mediaplayer.h
index 207191d..88b0c3e 100644
--- a/include/media/mediaplayer.h
+++ b/include/media/mediaplayer.h
@@ -169,8 +169,6 @@
status_t invoke(const Parcel& request, Parcel *reply);
status_t setMetadataFilter(const Parcel& filter);
status_t getMetadata(bool update_only, bool apply_filter, Parcel *metadata);
- status_t suspend();
- status_t resume();
status_t setAudioSessionId(int sessionId);
int getAudioSessionId();
status_t setAuxEffectSendLevel(float level);
diff --git a/include/utils/ResourceTypes.h b/include/utils/ResourceTypes.h
index da86da4..ed7f53d1 100644
--- a/include/utils/ResourceTypes.h
+++ b/include/utils/ResourceTypes.h
@@ -1771,12 +1771,14 @@
*
* @return ssize_t Either a >= 0 table index or a negative error code.
*/
- ssize_t getResource(uint32_t resID, Res_value* outValue, bool mayBeBag=false,
- uint32_t* outSpecFlags=NULL, ResTable_config* outConfig=NULL) const;
+ ssize_t getResource(uint32_t resID, Res_value* outValue, bool mayBeBag = false,
+ uint16_t density = 0,
+ uint32_t* outSpecFlags = NULL,
+ ResTable_config* outConfig = NULL) const;
inline ssize_t getResource(const ResTable_ref& res, Res_value* outValue,
uint32_t* outSpecFlags=NULL) const {
- return getResource(res.ident, outValue, false, outSpecFlags, NULL);
+ return getResource(res.ident, outValue, false, 0, outSpecFlags, NULL);
}
ssize_t resolveReference(Res_value* inOutValue,
diff --git a/libs/rs/java/Balls/Android.mk b/libs/rs/java/Balls/Android.mk
new file mode 100644
index 0000000..5b65628
--- /dev/null
+++ b/libs/rs/java/Balls/Android.mk
@@ -0,0 +1,31 @@
+#
+# Copyright (C) 2008 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.
+#
+
+ifneq ($(TARGET_SIMULATOR),true)
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
+#LOCAL_STATIC_JAVA_LIBRARIES := android.renderscript
+
+LOCAL_PACKAGE_NAME := Balls
+
+include $(BUILD_PACKAGE)
+
+endif
diff --git a/libs/rs/java/Balls/AndroidManifest.xml b/libs/rs/java/Balls/AndroidManifest.xml
new file mode 100644
index 0000000..2fffc5f
--- /dev/null
+++ b/libs/rs/java/Balls/AndroidManifest.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.balls">
+ <application
+ android:label="Balls"
+ android:icon="@drawable/test_pattern">
+ <activity android:name="Balls"
+ android:screenOrientation="landscape">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+</manifest>
diff --git a/libs/rs/java/Balls/res/drawable/flares.png b/libs/rs/java/Balls/res/drawable/flares.png
new file mode 100644
index 0000000..3a5c970
--- /dev/null
+++ b/libs/rs/java/Balls/res/drawable/flares.png
Binary files differ
diff --git a/libs/rs/java/Balls/res/drawable/test_pattern.png b/libs/rs/java/Balls/res/drawable/test_pattern.png
new file mode 100644
index 0000000..e7d1455
--- /dev/null
+++ b/libs/rs/java/Balls/res/drawable/test_pattern.png
Binary files differ
diff --git a/libs/rs/java/Balls/src/com/android/balls/Balls.java b/libs/rs/java/Balls/src/com/android/balls/Balls.java
new file mode 100644
index 0000000..5957c94
--- /dev/null
+++ b/libs/rs/java/Balls/src/com/android/balls/Balls.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2008 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.balls;
+
+import android.renderscript.RSSurfaceView;
+import android.renderscript.RenderScript;
+
+import android.app.Activity;
+import android.content.res.Configuration;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.provider.Settings.System;
+import android.util.Config;
+import android.util.Log;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.Window;
+import android.widget.Button;
+import android.widget.ListView;
+
+import java.lang.Runtime;
+
+import android.app.Activity;
+import android.content.Context;
+import android.os.Bundle;
+import android.view.View;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
+
+public class Balls extends Activity implements SensorEventListener {
+ //EventListener mListener = new EventListener();
+
+ private static final String LOG_TAG = "libRS_jni";
+ private static final boolean DEBUG = false;
+ private static final boolean LOG_ENABLED = DEBUG ? Config.LOGD : Config.LOGV;
+
+ private BallsView mView;
+ private SensorManager mSensorManager;
+
+ // get the current looper (from your Activity UI thread for instance
+
+
+ public void onSensorChanged(SensorEvent event) {
+ //android.util.Log.d("rs", "sensor: " + event.sensor + ", x: " + event.values[0] + ", y: " + event.values[1] + ", z: " + event.values[2]);
+ synchronized (this) {
+ if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
+ if(mView != null) {
+ mView.setAccel(event.values[0], event.values[1], event.values[2]);
+ }
+ }
+ }
+ }
+
+ public void onAccuracyChanged(Sensor sensor, int accuracy) {
+ }
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+
+ mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
+
+ // Create our Preview view and set it as the content of our
+ // Activity
+ mView = new BallsView(this);
+ setContentView(mView);
+ }
+
+ @Override
+ protected void onResume() {
+ mSensorManager.registerListener(this,
+ mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
+ SensorManager.SENSOR_DELAY_FASTEST);
+
+ // Ideally a game should implement onResume() and onPause()
+ // to take appropriate action when the activity looses focus
+ super.onResume();
+ mView.onResume();
+ }
+
+ @Override
+ protected void onPause() {
+ Log.e("rs", "onPause");
+
+ // Ideally a game should implement onResume() and onPause()
+ // to take appropriate action when the activity looses focus
+ super.onPause();
+ mView.onPause();
+
+
+
+ //Runtime.getRuntime().exit(0);
+ }
+
+ @Override
+ protected void onStop() {
+ mSensorManager.unregisterListener(this);
+ super.onStop();
+ }
+
+ static void log(String message) {
+ if (LOG_ENABLED) {
+ Log.v(LOG_TAG, message);
+ }
+ }
+
+
+}
+
diff --git a/libs/rs/java/Balls/src/com/android/balls/BallsRS.java b/libs/rs/java/Balls/src/com/android/balls/BallsRS.java
new file mode 100644
index 0000000..f76a011
--- /dev/null
+++ b/libs/rs/java/Balls/src/com/android/balls/BallsRS.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2008 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.balls;
+
+import android.content.res.Resources;
+import android.renderscript.*;
+import android.util.Log;
+
+public class BallsRS {
+ public static final int PART_COUNT = 800;
+
+ public BallsRS() {
+ }
+
+ private Resources mRes;
+ private RenderScriptGL mRS;
+ private ScriptC_balls mScript;
+ private ScriptC_ball_physics mPhysicsScript;
+ private ProgramFragment mPF;
+ private ProgramVertex mPV;
+ private ProgramRaster mPR;
+ private ProgramStore mPS;
+ private ScriptField_Point mPoints;
+ private ScriptField_Point mArcs;
+ private ScriptField_VpConsts mVpConsts;
+
+ void updateProjectionMatrices() {
+ mVpConsts = new ScriptField_VpConsts(mRS, 1);
+ ScriptField_VpConsts.Item i = new ScriptField_VpConsts.Item();
+ Matrix4f mvp = new Matrix4f();
+ mvp.loadOrtho(0, mRS.getWidth(), mRS.getHeight(), 0, -1, 1);
+ i.MVP = mvp;
+ mVpConsts.set(i, 0, true);
+ }
+
+ private void createProgramRaster() {
+ ProgramRaster.Builder b = new ProgramRaster.Builder(mRS);
+ mPR = b.create();
+ mScript.set_gPR(mPR);
+ }
+
+ private void createProgramVertex() {
+ updateProjectionMatrices();
+
+ ProgramVertex.ShaderBuilder sb = new ProgramVertex.ShaderBuilder(mRS);
+ String t = "varying vec4 varColor;\n" +
+ "void main() {\n" +
+ " vec4 pos = vec4(0.0, 0.0, 0.0, 1.0);\n" +
+ " pos.xy = ATTRIB_position;\n" +
+ " gl_Position = UNI_MVP * pos;\n" +
+ " varColor = ATTRIB_color;\n" +
+ " gl_PointSize = ATTRIB_size;\n" +
+ "}\n";
+ sb.setShader(t);
+ sb.addConstant(mVpConsts.getType());
+ sb.addInput(mPoints.getElement());
+ ProgramVertex pvs = sb.create();
+ pvs.bindConstants(mVpConsts.getAllocation(), 0);
+ mScript.set_gPV(pvs);
+ }
+
+ private Allocation loadTexture(int id) {
+ final Allocation allocation = Allocation.createFromBitmapResource(mRS, mRes,
+ id, Element.RGB_565(mRS), false);
+ allocation.uploadToTexture(0);
+ return allocation;
+ }
+
+ public void init(RenderScriptGL rs, Resources res, int width, int height) {
+ mRS = rs;
+ mRes = res;
+
+ ProgramFragment.Builder pfb = new ProgramFragment.Builder(rs);
+ pfb.setPointSpriteTexCoordinateReplacement(true);
+ pfb.setTexture(ProgramFragment.Builder.EnvMode.MODULATE,
+ ProgramFragment.Builder.Format.RGBA, 0);
+ pfb.setVaryingColor(true);
+ mPF = pfb.create();
+ rs.contextBindProgramFragment(mPF);
+
+ mPF.bindTexture(loadTexture(R.drawable.flares), 0);
+
+ mPoints = new ScriptField_Point(mRS, PART_COUNT);
+ mArcs = new ScriptField_Point(mRS, PART_COUNT * 2);
+
+ Mesh.AllocationBuilder smb = new Mesh.AllocationBuilder(mRS);
+ smb.addVertexAllocation(mPoints.getAllocation());
+ smb.addIndexType(Primitive.POINT);
+ Mesh smP = smb.create();
+
+ smb = new Mesh.AllocationBuilder(mRS);
+ smb.addVertexAllocation(mArcs.getAllocation());
+ smb.addIndexType(Primitive.LINE);
+ Mesh smA = smb.create();
+
+ mPhysicsScript = new ScriptC_ball_physics(mRS, mRes, R.raw.ball_physics, true);
+
+ mScript = new ScriptC_balls(mRS, mRes, R.raw.balls, true);
+ mScript.set_partMesh(smP);
+ mScript.set_arcMesh(smA);
+ mScript.set_physics_script(mPhysicsScript);
+ mScript.bind_point(mPoints);
+ mScript.bind_arc(mArcs);
+ mScript.bind_balls1(new ScriptField_Ball(mRS, PART_COUNT));
+ mScript.bind_balls2(new ScriptField_Ball(mRS, PART_COUNT));
+
+ mScript.set_gPF(mPF);
+ createProgramVertex();
+ createProgramRaster();
+
+ mPS = ProgramStore.BLEND_ADD_DEPTH_NO_DEPTH(mRS);
+ mScript.set_gPS(mPS);
+
+ mPhysicsScript.set_gMinPos(new Float2(5, 5));
+ mPhysicsScript.set_gMaxPos(new Float2(width - 5, height - 5));
+
+ mScript.invoke_initParts(width, height);
+
+ mRS.contextBindRootScript(mScript);
+ }
+
+ public void newTouchPosition(float x, float y, float pressure, int id) {
+ mPhysicsScript.set_touchX(x);
+ mPhysicsScript.set_touchY(y);
+ mPhysicsScript.set_touchPressure(pressure);
+ }
+
+ public void setAccel(float x, float y) {
+ mPhysicsScript.set_gGravityVector(new Float2(x, y));
+ }
+
+}
diff --git a/libs/rs/java/Balls/src/com/android/balls/BallsView.java b/libs/rs/java/Balls/src/com/android/balls/BallsView.java
new file mode 100644
index 0000000..635dac9
--- /dev/null
+++ b/libs/rs/java/Balls/src/com/android/balls/BallsView.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2008 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.balls;
+
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.concurrent.Semaphore;
+
+import android.renderscript.RSSurfaceView;
+import android.renderscript.RenderScript;
+import android.renderscript.RenderScriptGL;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.os.Handler;
+import android.os.Message;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.Surface;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+
+public class BallsView extends RSSurfaceView {
+
+ public BallsView(Context context) {
+ super(context);
+ //setFocusable(true);
+ }
+
+ private RenderScriptGL mRS;
+ private BallsRS mRender;
+
+ public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
+ super.surfaceChanged(holder, format, w, h);
+ if (mRS == null) {
+ RenderScriptGL.SurfaceConfig sc = new RenderScriptGL.SurfaceConfig();
+ mRS = createRenderScript(sc);
+ mRS.contextSetSurface(w, h, holder.getSurface());
+ mRender = new BallsRS();
+ mRender.init(mRS, getResources(), w, h);
+ }
+ mRender.updateProjectionMatrices();
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ if(mRS != null) {
+ mRS = null;
+ destroyRenderScript();
+ }
+ }
+
+
+ @Override
+ public boolean onTouchEvent(MotionEvent ev)
+ {
+ int act = ev.getActionMasked();
+ if (act == ev.ACTION_UP) {
+ mRender.newTouchPosition(0, 0, 0, ev.getPointerId(0));
+ return false;
+ } else if (act == MotionEvent.ACTION_POINTER_UP) {
+ // only one pointer going up, we can get the index like this
+ int pointerIndex = ev.getActionIndex();
+ int pointerId = ev.getPointerId(pointerIndex);
+ mRender.newTouchPosition(0, 0, 0, pointerId);
+ }
+ int count = ev.getHistorySize();
+ int pcount = ev.getPointerCount();
+
+ for (int p=0; p < pcount; p++) {
+ int id = ev.getPointerId(p);
+ mRender.newTouchPosition(ev.getX(p),
+ ev.getY(p),
+ ev.getPressure(p),
+ id);
+
+ for (int i=0; i < count; i++) {
+ mRender.newTouchPosition(ev.getHistoricalX(p, i),
+ ev.getHistoricalY(p, i),
+ ev.getHistoricalPressure(p, i),
+ id);
+ }
+ }
+ return true;
+ }
+
+ void setAccel(float x, float y, float z) {
+ if (mRender == null) {
+ return;
+ }
+ mRender.setAccel(x, -y);
+ }
+
+}
+
+
diff --git a/libs/rs/java/Balls/src/com/android/balls/ball_physics.rs b/libs/rs/java/Balls/src/com/android/balls/ball_physics.rs
new file mode 100644
index 0000000..b5f149c
--- /dev/null
+++ b/libs/rs/java/Balls/src/com/android/balls/ball_physics.rs
@@ -0,0 +1,116 @@
+#pragma version(1)
+#pragma rs java_package_name(com.android.balls)
+
+#include "balls.rsh"
+
+float2 gGravityVector = {0.f, 9.8f};
+
+#pragma rs export_func(setGamma);
+
+float2 gMinPos = {0.f, 0.f};
+float2 gMaxPos = {1280.f, 700.f};
+
+float touchX;
+float touchY;
+float touchPressure = 0.f;
+
+void setGamma(float g) {
+}
+
+
+void root(const Ball_t *ballIn, Ball_t *ballOut, const BallControl_t *ctl, uint32_t x) {
+ float2 fv = {0, 0};
+ float2 pos = ballIn->position;
+ //rsDebug("physics pos in", pos);
+
+ int arcID = -1;
+ float arcInvStr = 100000;
+
+ const Ball_t * bPtr = rsGetElementAt(ctl->ain, 0);
+ for (uint32_t xin = 0; xin < ctl->dimX; xin++) {
+ float2 vec = bPtr[xin].position - pos;
+ float2 vec2 = vec * vec;
+ float len2 = vec2.x + vec2.y;
+
+ if (len2 < 1000) {
+ if (len2 > (4*4)) {
+ // Repulsion
+ float len = sqrt(len2);
+ if (len < arcInvStr) {
+ arcInvStr = len;
+ arcID = xin;
+ }
+ fv -= (vec / (len * len * len)) * 20000.f;
+ } else {
+ if (len2 < 0.1) {
+ continue;
+ }
+ // Collision
+ float2 axis = normalize(vec);
+ float e1 = dot(axis, ballIn->delta);
+ float e2 = dot(axis, bPtr[xin].delta);
+ float e = (e1 - e2) * 0.45f;
+ if (e1 > 0) {
+ fv -= axis * e;
+ } else {
+ fv += axis * e;
+ }
+ }
+ }
+ }
+
+ fv -= gGravityVector;
+ fv *= ctl->dt;
+
+ {
+ float2 tp = {touchX, touchY};
+ float2 vec = tp - ballIn->position;
+ float2 vec2 = vec * vec;
+ float len2 = vec2.x + vec2.y;
+
+ if (len2 > 0.2) {
+ float len = sqrt(len2);
+ fv -= (vec / (len * len)) * touchPressure * 1000.f;
+ }
+ }
+
+ ballOut->delta = ballIn->delta * 0.998f;
+ ballOut->position = ballIn->position;
+
+ ballOut->delta += fv;
+ ballOut->position += ballOut->delta * ctl->dt;
+
+ if (ballOut->position.x > gMaxPos.x) {
+ if (ballOut->delta.x > 0) {
+ ballOut->delta.x *= -0.7;
+ }
+ ballOut->position.x = gMaxPos.x;
+ }
+ if (ballOut->position.y > gMaxPos.y) {
+ if (ballOut->delta.y > 0) {
+ ballOut->delta.y *= -0.7;
+ }
+ ballOut->position.y = gMaxPos.y - 1.f;
+ }
+ if (ballOut->position.x < gMinPos.x) {
+ if (ballOut->delta.x < 0) {
+ ballOut->delta.x *= -0.7;
+ }
+ ballOut->position.x = gMinPos.x + 1.f;
+ }
+ if (ballOut->position.y < gMinPos.y) {
+ if (ballOut->delta.y < 0) {
+ ballOut->delta.y *= -0.7;
+ }
+ ballOut->position.y = gMinPos.y + 1.f;
+ }
+
+ ballOut->color.b = 1.f;
+ ballOut->color.r = min(sqrt(length(ballOut->delta)) * 0.1f, 1.f);
+ ballOut->color.g = min(sqrt(length(fv) * 0.1f), 1.f);
+ ballOut->arcID = arcID;
+ ballOut->arcStr = 8 / arcInvStr;
+
+ //rsDebug("physics pos out", ballOut->position);
+}
+
diff --git a/libs/rs/java/Balls/src/com/android/balls/balls.rs b/libs/rs/java/Balls/src/com/android/balls/balls.rs
new file mode 100644
index 0000000..9d3f30b
--- /dev/null
+++ b/libs/rs/java/Balls/src/com/android/balls/balls.rs
@@ -0,0 +1,104 @@
+#pragma version(1)
+#pragma rs java_package_name(com.android.balls)
+#include "rs_graphics.rsh"
+
+#include "balls.rsh"
+
+#pragma stateFragment(parent)
+
+rs_program_fragment gPF;
+rs_program_vertex gPV;
+rs_program_raster gPR;
+rs_program_store gPS;
+rs_mesh partMesh;
+rs_mesh arcMesh;
+
+typedef struct __attribute__((packed, aligned(4))) Point {
+ float2 position;
+ uchar4 color;
+ float size;
+} Point_t;
+Point_t *point;
+Point_t *arc;
+
+typedef struct VpConsts {
+ //rs_matrix4x4 Proj;
+ rs_matrix4x4 MVP;
+} VpConsts_t;
+VpConsts_t *vpConstants;
+
+
+#pragma rs export_func(initParts)
+
+rs_script physics_script;
+
+Ball_t *balls1;
+Ball_t *balls2;
+
+static int frame = 0;
+
+void initParts(int w, int h)
+{
+ uint32_t dimX = rsAllocationGetDimX(rsGetAllocation(balls1));
+
+ for (uint32_t ct=0; ct < dimX; ct++) {
+ balls1[ct].position.x = rsRand(0.f, (float)w);
+ balls1[ct].position.y = rsRand(0.f, (float)h);
+ balls1[ct].delta.x = 0.f;
+ balls1[ct].delta.y = 0.f;
+ balls1[ct].arcID = -1;
+ balls1[ct].color = 0.f;
+ }
+}
+
+
+
+int root() {
+ rsgClearColor(0.f, 0.f, 0.f, 1.f);
+
+ BallControl_t bc;
+ Ball_t *bout;
+
+ if (frame & 1) {
+ bc.ain = rsGetAllocation(balls2);
+ bc.aout = rsGetAllocation(balls1);
+ bout = balls2;
+ } else {
+ bc.ain = rsGetAllocation(balls1);
+ bc.aout = rsGetAllocation(balls2);
+ bout = balls1;
+ }
+
+ bc.dimX = rsAllocationGetDimX(bc.ain);
+ bc.dt = 1.f / 30.f;
+
+ rsForEach(physics_script, bc.ain, bc.aout, &bc);
+
+ uint32_t arcIdx = 0;
+ for (uint32_t ct=0; ct < bc.dimX; ct++) {
+ point[ct].position = bout[ct].position;
+ point[ct].color = rsPackColorTo8888(bout[ct].color);
+ point[ct].size = 6.f + bout[ct].color.g * 6.f;
+
+ if (bout[ct].arcID >= 0) {
+ arc[arcIdx].position = bout[ct].position;
+ arc[arcIdx].color.r = min(bout[ct].arcStr, 1.f) * 0xff;
+ arc[arcIdx].color.g = 0;
+ arc[arcIdx].color.b = 0;
+ arc[arcIdx].color.a = 0xff;
+ arc[arcIdx+1].position = bout[bout[ct].arcID].position;
+ arc[arcIdx+1].color = arc[arcIdx].color;
+ arcIdx += 2;
+ }
+ }
+
+ frame++;
+ rsgBindProgramFragment(gPF);
+ rsgBindProgramVertex(gPV);
+ rsgBindProgramRaster(gPR);
+ rsgBindProgramStore(gPS);
+ rsgDrawMesh(arcMesh, 0, 0, arcIdx);
+ rsgDrawMesh(partMesh);
+ return 1;
+}
+
diff --git a/libs/rs/java/Balls/src/com/android/balls/balls.rsh b/libs/rs/java/Balls/src/com/android/balls/balls.rsh
new file mode 100644
index 0000000..ed3c31a
--- /dev/null
+++ b/libs/rs/java/Balls/src/com/android/balls/balls.rsh
@@ -0,0 +1,17 @@
+
+typedef struct __attribute__((packed, aligned(4))) Ball {
+ float2 delta;
+ float2 position;
+ float3 color;
+ int arcID;
+ float arcStr;
+} Ball_t;
+Ball_t *balls;
+
+
+typedef struct BallControl {
+ uint32_t dimX;
+ rs_allocation ain;
+ rs_allocation aout;
+ float dt;
+} BallControl_t;
diff --git a/libs/rs/rsContext.cpp b/libs/rs/rsContext.cpp
index 3f04585..0241455 100644
--- a/libs/rs/rsContext.cpp
+++ b/libs/rs/rsContext.cpp
@@ -470,7 +470,7 @@
rsc->timerPrint();
rsc->timerReset();
}
- if (rsc->mThreadPriority > 0 && targetTime) {
+ if (targetTime > 1) {
int32_t t = (targetTime - (int32_t)(rsc->mTimeMSLastScript + rsc->mTimeMSLastSwap)) * 1000;
if (t > 0) {
usleep(t);
diff --git a/libs/rs/rsScriptC.cpp b/libs/rs/rsScriptC.cpp
index 9dce158..1f5ed7c 100644
--- a/libs/rs/rsScriptC.cpp
+++ b/libs/rs/rsScriptC.cpp
@@ -217,6 +217,32 @@
}
+static void wc_x(void *usr, uint32_t idx)
+{
+ MTLaunchStruct *mtls = (MTLaunchStruct *)usr;
+
+ while (1) {
+ uint32_t slice = (uint32_t)android_atomic_inc(&mtls->mSliceNum);
+ uint32_t xStart = mtls->xStart + slice * mtls->mSliceSize;
+ uint32_t xEnd = xStart + mtls->mSliceSize;
+ xEnd = rsMin(xEnd, mtls->xEnd);
+ if (xEnd <= xStart) {
+ return;
+ }
+
+ //LOGE("usr idx %i, x %i,%i y %i,%i", idx, mtls->xStart, mtls->xEnd, yStart, yEnd);
+ //LOGE("usr ptr in %p, out %p", mtls->ptrIn, mtls->ptrOut);
+ uint8_t *xPtrOut = mtls->ptrOut + (mtls->eStrideOut * xStart);
+ const uint8_t *xPtrIn = mtls->ptrIn + (mtls->eStrideIn * xStart);
+ for (uint32_t x = xStart; x < xEnd; x++) {
+ ((rs_t)mtls->script->mProgram.mRoot) (xPtrIn, xPtrOut, mtls->usr, x, 0, 0, 0);
+ xPtrIn += mtls->eStrideIn;
+ xPtrOut += mtls->eStrideOut;
+ }
+ }
+
+}
+
void ScriptC::runForEach(Context *rsc,
const Allocation * ain,
Allocation * aout,
@@ -296,10 +322,14 @@
mtls.eStrideOut = aout->getType()->getElementSizeBytes();
}
- if ((rsc->getWorkerPoolSize() > 1) && mEnviroment.mIsThreadable && (mtls.dimY > 1)) {
+ if ((rsc->getWorkerPoolSize() > 1) && mEnviroment.mIsThreadable) {
+ if (mtls.dimY > 1) {
+ rsc->launchThreads(wc_xy, &mtls);
+ } else {
+ rsc->launchThreads(wc_x, &mtls);
+ }
//LOGE("launch 1");
- rsc->launchThreads(wc_xy, &mtls);
} else {
//LOGE("launch 3");
for (uint32_t ar = mtls.arrayStart; ar < mtls.arrayEnd; ar++) {
diff --git a/libs/utils/ResourceTypes.cpp b/libs/utils/ResourceTypes.cpp
index 91e7df3..03d2e21 100644
--- a/libs/utils/ResourceTypes.cpp
+++ b/libs/utils/ResourceTypes.cpp
@@ -1896,7 +1896,7 @@
return false;
}
-ssize_t ResTable::getResource(uint32_t resID, Res_value* outValue, bool mayBeBag,
+ssize_t ResTable::getResource(uint32_t resID, Res_value* outValue, bool mayBeBag, uint16_t density,
uint32_t* outSpecFlags, ResTable_config* outConfig) const
{
if (mError != NO_ERROR) {
@@ -1926,7 +1926,7 @@
memset(&bestItem, 0, sizeof(bestItem)); // make the compiler shut up
if (outSpecFlags != NULL) *outSpecFlags = 0;
-
+
// Look through all resource packages, starting with the most
// recently added.
const PackageGroup* const grp = mPackageGroups[p];
@@ -1934,6 +1934,22 @@
LOGW("Bad identifier when getting value for resource number 0x%08x", resID);
return BAD_INDEX;
}
+
+ // Allow overriding density
+ const ResTable_config* desiredConfig = &mParams;
+ ResTable_config* overrideConfig = NULL;
+ if (density > 0) {
+ overrideConfig = (ResTable_config*) malloc(sizeof(ResTable_config));
+ if (overrideConfig == NULL) {
+ LOGE("Couldn't malloc ResTable_config for overrides: %s", strerror(errno));
+ return BAD_INDEX;
+ }
+ memcpy(overrideConfig, &mParams, sizeof(ResTable_config));
+ overrideConfig->density = density;
+ desiredConfig = overrideConfig;
+ }
+
+ ssize_t rc = BAD_INDEX;
size_t ip = grp->packages.size();
while (ip > 0) {
ip--;
@@ -1943,12 +1959,13 @@
const ResTable_type* type;
const ResTable_entry* entry;
const Type* typeClass;
- ssize_t offset = getEntry(package, t, e, &mParams, &type, &entry, &typeClass);
+ ssize_t offset = getEntry(package, t, e, desiredConfig, &type, &entry, &typeClass);
if (offset <= 0) {
if (offset < 0) {
LOGW("Failure getting entry for 0x%08x (t=%d e=%d) in package %zd (error %d)\n",
resID, t, e, ip, (int)offset);
- return offset;
+ rc = offset;
+ goto out;
}
continue;
}
@@ -1963,13 +1980,14 @@
TABLE_NOISY(aout << "Resource type data: "
<< HexDump(type, dtohl(type->header.size)) << endl);
-
+
if ((size_t)offset > (dtohl(type->header.size)-sizeof(Res_value))) {
LOGW("ResTable_item at %d is beyond type chunk data %d",
(int)offset, dtohl(type->header.size));
- return BAD_TYPE;
+ rc = BAD_TYPE;
+ goto out;
}
-
+
const Res_value* item =
(const Res_value*)(((const uint8_t*)type) + offset);
ResTable_config thisConfig;
@@ -2011,10 +2029,16 @@
outValue->data, &len)).string()
: "",
outValue->data));
- return bestPackage->header->index;
+ rc = bestPackage->header->index;
+ goto out;
}
- return BAD_VALUE;
+out:
+ if (overrideConfig != NULL) {
+ free(overrideConfig);
+ }
+
+ return rc;
}
ssize_t ResTable::resolveReference(Res_value* value, ssize_t blockIndex,
@@ -2027,7 +2051,7 @@
if (outLastRef) *outLastRef = value->data;
uint32_t lastRef = value->data;
uint32_t newFlags = 0;
- const ssize_t newIndex = getResource(value->data, value, true, &newFlags,
+ const ssize_t newIndex = getResource(value->data, value, true, 0, &newFlags,
outConfig);
if (newIndex == BAD_INDEX) {
return BAD_INDEX;
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index cb46a29..01134f2 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -1087,53 +1087,6 @@
private native void _reset();
/**
- * Suspends the MediaPlayer. The only methods that may be called while
- * suspended are {@link #reset()}, {@link #release()} and {@link #resume()}.
- * MediaPlayer will release its hardware resources as far as
- * possible and reasonable. A successfully suspended MediaPlayer will
- * cease sending events.
- * If suspension is successful, this method returns true, otherwise
- * false is returned and the player's state is not affected.
- * @hide
- */
- public boolean suspend() {
- if (native_suspend_resume(true) < 0) {
- return false;
- }
-
- stayAwake(false);
-
- // make sure none of the listeners get called anymore
- mEventHandler.removeCallbacksAndMessages(null);
-
- return true;
- }
-
- /**
- * Resumes the MediaPlayer. Only to be called after a previous (successful)
- * call to {@link #suspend()}.
- * MediaPlayer will return to a state close to what it was in before
- * suspension.
- * @hide
- */
- public boolean resume() {
- if (native_suspend_resume(false) < 0) {
- return false;
- }
-
- if (isPlaying()) {
- stayAwake(true);
- }
-
- return true;
- }
-
- /**
- * @hide
- */
- private native int native_suspend_resume(boolean isSuspend);
-
- /**
* Sets the audio stream type for this MediaPlayer. See {@link AudioManager}
* for a list of stream types. Must call this method before prepare() or
* prepareAsync() in order for the target stream type to become effective
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index eb3d27b..997d017 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -680,19 +680,6 @@
android_media_MediaPlayer_release(env, thiz);
}
-static jint
-android_media_MediaPlayer_native_suspend_resume(
- JNIEnv *env, jobject thiz, jboolean isSuspend) {
- LOGV("suspend_resume(%d)", isSuspend);
- sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
- if (mp == NULL ) {
- jniThrowException(env, "java/lang/IllegalStateException", NULL);
- return UNKNOWN_ERROR;
- }
-
- return isSuspend ? mp->suspend() : mp->resume();
-}
-
static void android_media_MediaPlayer_set_audio_session_id(JNIEnv *env, jobject thiz, jint sessionId) {
LOGV("set_session_id(): %d", sessionId);
sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
@@ -767,7 +754,6 @@
{"native_init", "()V", (void *)android_media_MediaPlayer_native_init},
{"native_setup", "(Ljava/lang/Object;)V", (void *)android_media_MediaPlayer_native_setup},
{"native_finalize", "()V", (void *)android_media_MediaPlayer_native_finalize},
- {"native_suspend_resume", "(Z)I", (void *)android_media_MediaPlayer_native_suspend_resume},
{"getAudioSessionId", "()I", (void *)android_media_MediaPlayer_get_audio_session_id},
{"setAudioSessionId", "(I)V", (void *)android_media_MediaPlayer_set_audio_session_id},
{"setAuxEffectSendLevel", "(F)V", (void *)android_media_MediaPlayer_setAuxEffectSendLevel},
diff --git a/media/libmedia/IMediaPlayer.cpp b/media/libmedia/IMediaPlayer.cpp
index 9dfdcb0..1a46715 100644
--- a/media/libmedia/IMediaPlayer.cpp
+++ b/media/libmedia/IMediaPlayer.cpp
@@ -45,8 +45,6 @@
INVOKE,
SET_METADATA_FILTER,
GET_METADATA,
- SUSPEND,
- RESUME,
SET_AUX_EFFECT_SEND_LEVEL,
ATTACH_AUX_EFFECT
};
@@ -215,26 +213,6 @@
return reply->readInt32();
}
- status_t suspend() {
- Parcel request;
- request.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
-
- Parcel reply;
- remote()->transact(SUSPEND, request, &reply);
-
- return reply.readInt32();
- }
-
- status_t resume() {
- Parcel request;
- request.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
-
- Parcel reply;
- remote()->transact(RESUME, request, &reply);
-
- return reply.readInt32();
- }
-
status_t setAuxEffectSendLevel(float level)
{
Parcel data, reply;
@@ -358,16 +336,6 @@
reply->writeInt32(setMetadataFilter(data));
return NO_ERROR;
} break;
- case SUSPEND: {
- CHECK_INTERFACE(IMediaPlayer, data, reply);
- reply->writeInt32(suspend());
- return NO_ERROR;
- } break;
- case RESUME: {
- CHECK_INTERFACE(IMediaPlayer, data, reply);
- reply->writeInt32(resume());
- return NO_ERROR;
- } break;
case GET_METADATA: {
CHECK_INTERFACE(IMediaPlayer, data, reply);
const status_t retcode = getMetadata(data.readInt32(), data.readInt32(), reply);
diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp
index ee3f660..34e41a1 100644
--- a/media/libmedia/mediaplayer.cpp
+++ b/media/libmedia/mediaplayer.cpp
@@ -172,16 +172,6 @@
return INVALID_OPERATION;
}
-status_t MediaPlayer::suspend() {
- Mutex::Autolock _l(mLock);
- return mPlayer->suspend();
-}
-
-status_t MediaPlayer::resume() {
- Mutex::Autolock _l(mLock);
- return mPlayer->resume();
-}
-
status_t MediaPlayer::setMetadataFilter(const Parcel& filter)
{
LOGD("setMetadataFilter");
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 80922d6..bb86e05 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -974,20 +974,6 @@
return OK;
}
-status_t MediaPlayerService::Client::suspend() {
- sp<MediaPlayerBase> p = getPlayer();
- if (p == 0) return UNKNOWN_ERROR;
-
- return p->suspend();
-}
-
-status_t MediaPlayerService::Client::resume() {
- sp<MediaPlayerBase> p = getPlayer();
- if (p == 0) return UNKNOWN_ERROR;
-
- return p->resume();
-}
-
status_t MediaPlayerService::Client::prepareAsync()
{
LOGV("[%d] prepareAsync", mConnId);
diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h
index c4e78f7..e197cde 100644
--- a/media/libmediaplayerservice/MediaPlayerService.h
+++ b/media/libmediaplayerservice/MediaPlayerService.h
@@ -225,8 +225,6 @@
virtual status_t getMetadata(bool update_only,
bool apply_filter,
Parcel *reply);
- virtual status_t suspend();
- virtual status_t resume();
virtual status_t setAuxEffectSendLevel(float level);
virtual status_t attachAuxEffect(int effectId);
diff --git a/media/libmediaplayerservice/StagefrightPlayer.cpp b/media/libmediaplayerservice/StagefrightPlayer.cpp
index b3e2da0..e0957f6 100644
--- a/media/libmediaplayerservice/StagefrightPlayer.cpp
+++ b/media/libmediaplayerservice/StagefrightPlayer.cpp
@@ -147,16 +147,6 @@
return STAGEFRIGHT_PLAYER;
}
-status_t StagefrightPlayer::suspend() {
- LOGV("suspend");
- return mPlayer->suspend();
-}
-
-status_t StagefrightPlayer::resume() {
- LOGV("resume");
- return mPlayer->resume();
-}
-
status_t StagefrightPlayer::invoke(const Parcel &request, Parcel *reply) {
return INVALID_OPERATION;
}
diff --git a/media/libmediaplayerservice/StagefrightPlayer.h b/media/libmediaplayerservice/StagefrightPlayer.h
index dd37102..3899447 100644
--- a/media/libmediaplayerservice/StagefrightPlayer.h
+++ b/media/libmediaplayerservice/StagefrightPlayer.h
@@ -51,8 +51,6 @@
virtual player_type playerType();
virtual status_t invoke(const Parcel &request, Parcel *reply);
virtual void setAudioSink(const sp<AudioSink> &audioSink);
- virtual status_t suspend();
- virtual status_t resume();
virtual status_t getMetadata(
const media::Metadata::Filter& ids, Parcel *records);
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index cf04e92..60a41bf 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -1192,6 +1192,13 @@
mFlags |= FIRST_FRAME;
mSeeking = false;
mSeekNotificationSent = false;
+
+ if (mDecryptHandle != NULL) {
+ mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
+ Playback::PAUSE, 0);
+ mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
+ Playback::START, videoTimeUs / 1000);
+ }
}
void AwesomePlayer::onVideoEvent() {
@@ -1295,13 +1302,6 @@
TimeSource *ts = (mFlags & AUDIO_AT_EOS) ? &mSystemTimeSource : mTimeSource;
- if (mDecryptHandle != NULL) {
- mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
- Playback::PAUSE, 0);
- mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
- Playback::START, timeUs / 1000);
- }
-
if (mFlags & FIRST_FRAME) {
mFlags &= ~FIRST_FRAME;
diff --git a/media/libstagefright/DataSource.cpp b/media/libstagefright/DataSource.cpp
index ea5577d..0b8997c 100644
--- a/media/libstagefright/DataSource.cpp
+++ b/media/libstagefright/DataSource.cpp
@@ -32,6 +32,8 @@
#include <media/stagefright/MediaErrors.h>
#include <utils/String8.h>
+#include <cutils/properties.h>
+
namespace android {
bool DataSource::getUInt16(off_t offset, uint16_t *x) {
@@ -105,7 +107,12 @@
RegisterSniffer(SniffAMR);
RegisterSniffer(SniffMPEG2TS);
RegisterSniffer(SniffMP3);
- //RegisterSniffer(SniffDRM);
+
+ char value[PROPERTY_VALUE_MAX];
+ if (property_get("drm.service.enabled", value, NULL)
+ && (!strcmp(value, "1") || !strcasecmp(value, "true"))) {
+ RegisterSniffer(SniffDRM);
+ }
}
// static
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index 9e79aa9..b3ed845 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -506,7 +506,7 @@
}
void MPEG4Writer::stopWriterThread() {
- LOGV("stopWriterThread");
+ LOGD("Stopping writer thread");
{
Mutex::Autolock autolock(mLock);
@@ -517,6 +517,7 @@
void *dummy;
pthread_join(mThread, &dummy);
+ LOGD("Writer thread stopped");
}
status_t MPEG4Writer::stop() {
@@ -1228,6 +1229,7 @@
}
status_t MPEG4Writer::Track::stop() {
+ LOGD("Stopping %s track", mIsAudio? "Audio": "Video");
if (mDone) {
return OK;
}
@@ -1239,6 +1241,7 @@
status_t err = (status_t) dummy;
+ LOGD("Stopping %s track source", mIsAudio? "Audio": "Video");
{
status_t status = mSource->stop();
if (err == OK && status != OK && status != ERROR_END_OF_STREAM) {
@@ -1246,6 +1249,7 @@
}
}
+ LOGD("%s track stopped", mIsAudio? "Audio": "Video");
return err;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index c164eb4..ed2ed1c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -55,6 +55,7 @@
private static final int MSG_SET_LIGHTS_ON = 0x00070000;
private static final int MSG_SHOW_MENU = 0x00080000;
+ private static final int MSG_SHOW_IME_BUTTON = 0x00090000;
private StatusBarIconList mList;
private Callbacks mCallbacks;
@@ -81,6 +82,7 @@
public void animateCollapse();
public void setLightsOn(boolean on);
public void setMenuKeyVisible(boolean visible);
+ public void setIMEButtonVisible(boolean visible);
}
public CommandQueue(Callbacks callbacks, StatusBarIconList list) {
@@ -163,6 +165,13 @@
}
}
+ public void setIMEButtonVisible(boolean visible) {
+ synchronized (mList) {
+ mHandler.removeMessages(MSG_SHOW_IME_BUTTON);
+ mHandler.obtainMessage(MSG_SHOW_IME_BUTTON, visible ? 1 : 0, 0, null).sendToTarget();
+ }
+ }
+
private final class H extends Handler {
public void handleMessage(Message msg) {
final int what = msg.what & MSG_MASK;
@@ -223,6 +232,9 @@
case MSG_SHOW_MENU:
mCallbacks.setMenuKeyVisible(msg.arg1 != 0);
break;
+ case MSG_SHOW_IME_BUTTON:
+ mCallbacks.setIMEButtonVisible(msg.arg1 != 0);
+ break;
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/PhoneStatusBarService.java b/packages/SystemUI/src/com/android/systemui/statusbar/PhoneStatusBarService.java
index bf58b37..b174973 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/PhoneStatusBarService.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/PhoneStatusBarService.java
@@ -1014,6 +1014,7 @@
// Not supported
public void setMenuKeyVisible(boolean visible) { }
+ public void setIMEButtonVisible(boolean visible) { }
private class Launcher implements View.OnClickListener {
private PendingIntent mIntent;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarService.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarService.java
index ae1fdbd..256386b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarService.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarService.java
@@ -65,7 +65,7 @@
mCommandQueue = new CommandQueue(this, iconList);
mBarService = IStatusBarService.Stub.asInterface(
ServiceManager.getService(Context.STATUS_BAR_SERVICE));
- boolean[] switches = new boolean[2];
+ boolean[] switches = new boolean[3];
try {
mBarService.registerStatusBar(mCommandQueue, iconList, notificationKeys, notifications,
switches);
@@ -75,6 +75,7 @@
setLightsOn(switches[0]);
setMenuKeyVisible(switches[1]);
+ setIMEButtonVisible(switches[2]);
// Set up the initial icon state
int N = iconList.size();
@@ -119,6 +120,7 @@
+ " icons=" + iconList.size()
+ " lights=" + (switches[0]?"on":"off")
+ " menu=" + (switches[1]?"visible":"invisible")
+ + " imeButton=" + (switches[2]?"visible":"invisible")
);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodButton.java
index 56b4f24..c416ff4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodButton.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodButton.java
@@ -16,9 +16,13 @@
package com.android.systemui.statusbar.tablet;
+import android.content.BroadcastReceiver;
import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
+import android.os.Handler;
import android.provider.Settings;
import android.util.Log;
import android.util.Slog;
@@ -32,7 +36,9 @@
import com.android.server.InputMethodManagerService;
import com.android.systemui.R;
+import java.util.Calendar;
import java.util.List;
+import java.util.TimeZone;
public class InputMethodButton extends ImageView {
@@ -61,8 +67,10 @@
});
}
+ @Override
protected void onAttachedToWindow() {
mIcon = (ImageView) findViewById(R.id.imeButton);
+
refreshStatusIcon(mKeyboardShown);
}
@@ -119,21 +127,8 @@
}
}
- private void postRefreshStatusIcon() {
- getHandler().post(new Runnable() {
- public void run() {
- refreshStatusIcon(mKeyboardShown);
- }
- });
- }
-
- public void showSoftInput() {
- mKeyboardShown = true;
- postRefreshStatusIcon();
- }
-
- public void hideSoftInput() {
- mKeyboardShown = false;
- postRefreshStatusIcon();
+ public void setIMEButtonVisible(boolean visible) {
+ mKeyboardShown = visible;
+ refreshStatusIcon(mKeyboardShown);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarService.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarService.java
index 6e9b456..abcfec8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarService.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarService.java
@@ -95,6 +95,8 @@
View mMenuButton;
View mRecentButton;
+ InputMethodButton mInputMethodButton;
+
NotificationPanel mNotificationPanel;
SystemPanel mSystemPanel;
NotificationPanel mNotificationPeekWindow;
@@ -305,6 +307,9 @@
mNavigationArea = sb.findViewById(R.id.navigationArea);
mMenuButton = mNavigationArea.findViewById(R.id.menu);
+ // The bar contents buttons
+ mInputMethodButton = (InputMethodButton) mBarContents.findViewById(R.id.imeButton);
+
// set the initial view visibility
setAreThereNotifications();
refreshNotificationTrigger();
@@ -690,6 +695,13 @@
visible ? R.anim.navigation_in : R.anim.navigation_out);
}
+ public void setIMEButtonVisible(boolean visible) {
+ if (DEBUG) {
+ Slog.d(TAG, (visible?"showing":"hiding") + " the IME button");
+ }
+ mInputMethodButton.setIMEButtonVisible(visible);
+ }
+
private void setAreThereNotifications() {
final boolean hasClearable = mNotns.hasClearableItems();
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index 3f378e1..07da0fa 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/java/com/android/server/InputMethodManagerService.java
@@ -940,6 +940,23 @@
}
}
+ public void setIMEButtonVisible(IBinder token, boolean visible) {
+ int uid = Binder.getCallingUid();
+ long ident = Binder.clearCallingIdentity();
+ try {
+ if (token == null || mCurToken != token) {
+ Slog.w(TAG, "Ignoring setIMEButtonVisible of uid " + uid + " token: " + token);
+ return;
+ }
+
+ synchronized (mMethodMap) {
+ mStatusBar.setIMEButtonVisible(visible);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
void updateFromSettingsLocked() {
// We are assuming that whoever is changing DEFAULT_INPUT_METHOD and
// ENABLED_INPUT_METHODS is taking care of keeping them correctly in
diff --git a/services/java/com/android/server/StatusBarManagerService.java b/services/java/com/android/server/StatusBarManagerService.java
index 400b31f..95d2b65 100644
--- a/services/java/com/android/server/StatusBarManagerService.java
+++ b/services/java/com/android/server/StatusBarManagerService.java
@@ -74,6 +74,8 @@
boolean mMenuVisible = false;
+ boolean mIMEButtonVisible = false;
+
private class DisableRecord implements IBinder.DeathRecipient {
String pkg;
int what;
@@ -257,6 +259,28 @@
}
}
+ public void setIMEButtonVisible(final boolean visible) {
+ enforceStatusBar();
+
+ if (SPEW) Slog.d(TAG, (visible?"showing":"hiding") + " IME Button");
+
+ synchronized(mLock) {
+ if (mIMEButtonVisible != visible) {
+ mIMEButtonVisible = visible;
+ mHandler.post(new Runnable() {
+ public void run() {
+ if (mBar != null) {
+ try {
+ mBar.setIMEButtonVisible(visible);
+ } catch (RemoteException ex) {
+ }
+ }
+ }
+ });
+ }
+ }
+ }
+
/**
* This is used for the automatic version of lights-out mode. Only call this from
* the window manager.
@@ -345,6 +369,7 @@
synchronized (mLock) {
switches[0] = mLightsOn;
switches[1] = mMenuVisible;
+ switches[2] = mIMEButtonVisible;
}
}
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 8d36e4f..60b2b67 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -6679,6 +6679,9 @@
if (info.numAnimationsRunning != 0) {
sb.append("Animations-Running: ").append(info.numAnimationsRunning).append("\n");
}
+ if (info.broadcastIntentAction != null) {
+ sb.append("Broadcast-Intent-Action: ").append(info.broadcastIntentAction).append("\n");
+ }
if (info != null && info.durationMillis != -1) {
sb.append("Duration-Millis: ").append(info.durationMillis).append("\n");
}