diff options
128 files changed, 3377 insertions, 2494 deletions
@@ -98,9 +98,9 @@ LOCAL_SRC_FILES += \ core/java/android/view/IWindowSession.aidl \ core/java/com/android/internal/app/IBatteryStats.aidl \ core/java/com/android/internal/app/IUsageStats.aidl \ - core/java/com/android/internal/gadget/IGadgetService.aidl \ - core/java/com/android/internal/gadget/IGadgetHost.aidl \ - core/java/com/android/internal/os/IResultReceiver.aidl \ + core/java/com/android/internal/appwidget/IAppWidgetService.aidl \ + core/java/com/android/internal/appwidget/IAppWidgetHost.aidl \ + core/java/com/android/internal/os/IResultReceiver.aidl \ core/java/com/android/internal/view/IInputContext.aidl \ core/java/com/android/internal/view/IInputContextCallback.aidl \ core/java/com/android/internal/view/IInputMethod.aidl \ @@ -168,7 +168,7 @@ aidl_files := \ frameworks/base/core/java/android/content/Intent.aidl \ frameworks/base/core/java/android/content/SyncStats.aidl \ frameworks/base/core/java/android/content/res/Configuration.aidl \ - frameworks/base/core/java/android/gadget/GadgetProviderInfo.aidl \ + frameworks/base/core/java/android/appwidget/AppWidgetProviderInfo.aidl \ frameworks/base/core/java/android/net/Uri.aidl \ frameworks/base/core/java/android/os/Bundle.aidl \ frameworks/base/core/java/android/os/ParcelFileDescriptor.aidl \ @@ -25763,17 +25763,6 @@ visibility="public" > </field> -<field name="CATEGORY_GADGET" - type="java.lang.String" - transient="false" - volatile="false" - value=""android.intent.category.GADGET"" - static="true" - final="true" - deprecated="not deprecated" - visibility="public" -> -</field> <field name="CATEGORY_HOME" type="java.lang.String" transient="false" diff --git a/api/current.xml b/api/current.xml index 96998ed..858b1e9 100644 --- a/api/current.xml +++ b/api/current.xml @@ -144,11 +144,11 @@ visibility="public" > </field> -<field name="BIND_GADGET" +<field name="BIND_APPWIDGET" type="java.lang.String" transient="false" volatile="false" - value=""android.permission.BIND_GADGET"" + value=""android.permission.BIND_APPWIDGET"" static="true" final="true" deprecated="not deprecated" @@ -20968,6 +20968,729 @@ </method> </interface> </package> +<package name="android.appwidget" +> +<class name="AppWidgetHost" + extends="java.lang.Object" + abstract="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<constructor name="AppWidgetHost" + type="android.appwidget.AppWidgetHost" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="context" type="android.content.Context"> +</parameter> +<parameter name="hostId" type="int"> +</parameter> +</constructor> +<method name="allocateAppWidgetId" + return="int" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> +<method name="createView" + return="android.appwidget.AppWidgetHostView" + abstract="false" + native="false" + synchronized="false" + static="false" + final="true" + deprecated="not deprecated" + visibility="public" +> +<parameter name="context" type="android.content.Context"> +</parameter> +<parameter name="appWidgetId" type="int"> +</parameter> +<parameter name="appWidget" type="android.appwidget.AppWidgetProviderInfo"> +</parameter> +</method> +<method name="deleteAllHosts" + return="void" + abstract="false" + native="false" + synchronized="false" + static="true" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> +<method name="deleteAppWidgetId" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="appWidgetId" type="int"> +</parameter> +</method> +<method name="deleteHost" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> +<method name="onCreateView" + return="android.appwidget.AppWidgetHostView" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="protected" +> +<parameter name="context" type="android.content.Context"> +</parameter> +<parameter name="appWidgetId" type="int"> +</parameter> +<parameter name="appWidget" type="android.appwidget.AppWidgetProviderInfo"> +</parameter> +</method> +<method name="onProviderChanged" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="protected" +> +<parameter name="appWidgetId" type="int"> +</parameter> +<parameter name="appWidget" type="android.appwidget.AppWidgetProviderInfo"> +</parameter> +</method> +<method name="startListening" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> +<method name="stopListening" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> +</class> +<class name="AppWidgetHostView" + extends="android.widget.FrameLayout" + abstract="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<constructor name="AppWidgetHostView" + type="android.appwidget.AppWidgetHostView" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="context" type="android.content.Context"> +</parameter> +</constructor> +<constructor name="AppWidgetHostView" + type="android.appwidget.AppWidgetHostView" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="context" type="android.content.Context"> +</parameter> +<parameter name="animationIn" type="int"> +</parameter> +<parameter name="animationOut" type="int"> +</parameter> +</constructor> +<method name="getAppWidgetId" + return="int" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> +<method name="getAppWidgetInfo" + return="android.appwidget.AppWidgetProviderInfo" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> +<method name="getDefaultView" + return="android.view.View" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="protected" +> +</method> +<method name="getErrorView" + return="android.view.View" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="protected" +> +</method> +<method name="prepareView" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="protected" +> +<parameter name="view" type="android.view.View"> +</parameter> +</method> +<method name="setAppWidget" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="appWidgetId" type="int"> +</parameter> +<parameter name="info" type="android.appwidget.AppWidgetProviderInfo"> +</parameter> +</method> +<method name="updateAppWidget" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="remoteViews" type="android.widget.RemoteViews"> +</parameter> +</method> +</class> +<class name="AppWidgetManager" + extends="java.lang.Object" + abstract="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<method name="bindAppWidgetId" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="appWidgetId" type="int"> +</parameter> +<parameter name="provider" type="android.content.ComponentName"> +</parameter> +</method> +<method name="getAppWidgetIds" + return="int[]" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="provider" type="android.content.ComponentName"> +</parameter> +</method> +<method name="getAppWidgetInfo" + return="android.appwidget.AppWidgetProviderInfo" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="appWidgetId" type="int"> +</parameter> +</method> +<method name="getInstalledProviders" + return="java.util.List<android.appwidget.AppWidgetProviderInfo>" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> +<method name="getInstance" + return="android.appwidget.AppWidgetManager" + abstract="false" + native="false" + synchronized="false" + static="true" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="context" type="android.content.Context"> +</parameter> +</method> +<method name="updateAppWidget" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="appWidgetIds" type="int[]"> +</parameter> +<parameter name="views" type="android.widget.RemoteViews"> +</parameter> +</method> +<method name="updateAppWidget" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="appWidgetId" type="int"> +</parameter> +<parameter name="views" type="android.widget.RemoteViews"> +</parameter> +</method> +<method name="updateAppWidget" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="provider" type="android.content.ComponentName"> +</parameter> +<parameter name="views" type="android.widget.RemoteViews"> +</parameter> +</method> +<field name="ACTION_APPWIDGET_CONFIGURE" + type="java.lang.String" + transient="false" + volatile="false" + value=""android.appwidget.action.APPWIDGET_CONFIGURE"" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="ACTION_APPWIDGET_DELETED" + type="java.lang.String" + transient="false" + volatile="false" + value=""android.appwidget.action.APPWIDGET_DELETED"" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="ACTION_APPWIDGET_DISABLED" + type="java.lang.String" + transient="false" + volatile="false" + value=""android.appwidget.action.APPWIDGET_DISABLED"" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="ACTION_APPWIDGET_ENABLED" + type="java.lang.String" + transient="false" + volatile="false" + value=""android.appwidget.action.APPWIDGET_ENABLED"" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="ACTION_APPWIDGET_PICK" + type="java.lang.String" + transient="false" + volatile="false" + value=""android.appwidget.action.APPWIDGET_PICK"" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="ACTION_APPWIDGET_UPDATE" + type="java.lang.String" + transient="false" + volatile="false" + value=""android.appwidget.action.APPWIDGET_UPDATE"" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="EXTRA_APPWIDGET_ID" + type="java.lang.String" + transient="false" + volatile="false" + value=""appWidgetId"" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="EXTRA_APPWIDGET_IDS" + type="java.lang.String" + transient="false" + volatile="false" + value=""appWidgetIds"" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="INVALID_APPWIDGET_ID" + type="int" + transient="false" + volatile="false" + value="0" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="META_DATA_APPWIDGET_PROVIDER" + type="java.lang.String" + transient="false" + volatile="false" + value=""android.appwidget.provider"" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +</class> +<class name="AppWidgetProvider" + extends="android.content.BroadcastReceiver" + abstract="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<constructor name="AppWidgetProvider" + type="android.appwidget.AppWidgetProvider" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</constructor> +<method name="onDeleted" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="context" type="android.content.Context"> +</parameter> +<parameter name="appWidgetIds" type="int[]"> +</parameter> +</method> +<method name="onDisabled" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="context" type="android.content.Context"> +</parameter> +</method> +<method name="onEnabled" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="context" type="android.content.Context"> +</parameter> +</method> +<method name="onReceive" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="context" type="android.content.Context"> +</parameter> +<parameter name="intent" type="android.content.Intent"> +</parameter> +</method> +<method name="onUpdate" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="context" type="android.content.Context"> +</parameter> +<parameter name="appWidgetManager" type="android.appwidget.AppWidgetManager"> +</parameter> +<parameter name="appWidgetIds" type="int[]"> +</parameter> +</method> +</class> +<class name="AppWidgetProviderInfo" + extends="java.lang.Object" + abstract="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<implements name="android.os.Parcelable"> +</implements> +<constructor name="AppWidgetProviderInfo" + type="android.appwidget.AppWidgetProviderInfo" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</constructor> +<constructor name="AppWidgetProviderInfo" + type="android.appwidget.AppWidgetProviderInfo" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="in" type="android.os.Parcel"> +</parameter> +</constructor> +<method name="describeContents" + return="int" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> +<method name="writeToParcel" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="out" type="android.os.Parcel"> +</parameter> +<parameter name="flags" type="int"> +</parameter> +</method> +<field name="CREATOR" + type="android.os.Parcelable.Creator" + transient="false" + volatile="false" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="configure" + type="android.content.ComponentName" + transient="false" + volatile="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="icon" + type="int" + transient="false" + volatile="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="initialLayout" + type="int" + transient="false" + volatile="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="label" + type="java.lang.String" + transient="false" + volatile="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="minHeight" + type="int" + transient="false" + volatile="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="minWidth" + type="int" + transient="false" + volatile="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="provider" + type="android.content.ComponentName" + transient="false" + volatile="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="updatePeriodMillis" + type="int" + transient="false" + volatile="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</field> +</class> +</package> <package name="android.content" > <class name="ActivityNotFoundException" @@ -27882,17 +28605,6 @@ visibility="public" > </field> -<field name="CATEGORY_GADGET" - type="java.lang.String" - transient="false" - volatile="false" - value=""android.intent.category.GADGET"" - static="true" - final="true" - deprecated="not deprecated" - visibility="public" -> -</field> <field name="CATEGORY_HOME" type="java.lang.String" transient="false" @@ -42328,729 +43040,6 @@ </method> </class> </package> -<package name="android.gadget" -> -<class name="GadgetHost" - extends="java.lang.Object" - abstract="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -<constructor name="GadgetHost" - type="android.gadget.GadgetHost" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -<parameter name="context" type="android.content.Context"> -</parameter> -<parameter name="hostId" type="int"> -</parameter> -</constructor> -<method name="allocateGadgetId" - return="int" - abstract="false" - native="false" - synchronized="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -</method> -<method name="createView" - return="android.gadget.GadgetHostView" - abstract="false" - native="false" - synchronized="false" - static="false" - final="true" - deprecated="not deprecated" - visibility="public" -> -<parameter name="context" type="android.content.Context"> -</parameter> -<parameter name="gadgetId" type="int"> -</parameter> -<parameter name="gadget" type="android.gadget.GadgetProviderInfo"> -</parameter> -</method> -<method name="deleteAllHosts" - return="void" - abstract="false" - native="false" - synchronized="false" - static="true" - final="false" - deprecated="not deprecated" - visibility="public" -> -</method> -<method name="deleteGadgetId" - return="void" - abstract="false" - native="false" - synchronized="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -<parameter name="gadgetId" type="int"> -</parameter> -</method> -<method name="deleteHost" - return="void" - abstract="false" - native="false" - synchronized="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -</method> -<method name="onCreateView" - return="android.gadget.GadgetHostView" - abstract="false" - native="false" - synchronized="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="protected" -> -<parameter name="context" type="android.content.Context"> -</parameter> -<parameter name="gadgetId" type="int"> -</parameter> -<parameter name="gadget" type="android.gadget.GadgetProviderInfo"> -</parameter> -</method> -<method name="onProviderChanged" - return="void" - abstract="false" - native="false" - synchronized="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="protected" -> -<parameter name="gadgetId" type="int"> -</parameter> -<parameter name="gadget" type="android.gadget.GadgetProviderInfo"> -</parameter> -</method> -<method name="startListening" - return="void" - abstract="false" - native="false" - synchronized="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -</method> -<method name="stopListening" - return="void" - abstract="false" - native="false" - synchronized="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -</method> -</class> -<class name="GadgetHostView" - extends="android.widget.FrameLayout" - abstract="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -<constructor name="GadgetHostView" - type="android.gadget.GadgetHostView" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -<parameter name="context" type="android.content.Context"> -</parameter> -</constructor> -<constructor name="GadgetHostView" - type="android.gadget.GadgetHostView" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -<parameter name="context" type="android.content.Context"> -</parameter> -<parameter name="animationIn" type="int"> -</parameter> -<parameter name="animationOut" type="int"> -</parameter> -</constructor> -<method name="getDefaultView" - return="android.view.View" - abstract="false" - native="false" - synchronized="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="protected" -> -</method> -<method name="getErrorView" - return="android.view.View" - abstract="false" - native="false" - synchronized="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="protected" -> -</method> -<method name="getGadgetId" - return="int" - abstract="false" - native="false" - synchronized="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -</method> -<method name="getGadgetInfo" - return="android.gadget.GadgetProviderInfo" - abstract="false" - native="false" - synchronized="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -</method> -<method name="prepareView" - return="void" - abstract="false" - native="false" - synchronized="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="protected" -> -<parameter name="view" type="android.view.View"> -</parameter> -</method> -<method name="setGadget" - return="void" - abstract="false" - native="false" - synchronized="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -<parameter name="gadgetId" type="int"> -</parameter> -<parameter name="info" type="android.gadget.GadgetProviderInfo"> -</parameter> -</method> -<method name="updateGadget" - return="void" - abstract="false" - native="false" - synchronized="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -<parameter name="remoteViews" type="android.widget.RemoteViews"> -</parameter> -</method> -</class> -<class name="GadgetManager" - extends="java.lang.Object" - abstract="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -<method name="bindGadgetId" - return="void" - abstract="false" - native="false" - synchronized="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -<parameter name="gadgetId" type="int"> -</parameter> -<parameter name="provider" type="android.content.ComponentName"> -</parameter> -</method> -<method name="getGadgetIds" - return="int[]" - abstract="false" - native="false" - synchronized="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -<parameter name="provider" type="android.content.ComponentName"> -</parameter> -</method> -<method name="getGadgetInfo" - return="android.gadget.GadgetProviderInfo" - abstract="false" - native="false" - synchronized="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -<parameter name="gadgetId" type="int"> -</parameter> -</method> -<method name="getInstalledProviders" - return="java.util.List<android.gadget.GadgetProviderInfo>" - abstract="false" - native="false" - synchronized="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -</method> -<method name="getInstance" - return="android.gadget.GadgetManager" - abstract="false" - native="false" - synchronized="false" - static="true" - final="false" - deprecated="not deprecated" - visibility="public" -> -<parameter name="context" type="android.content.Context"> -</parameter> -</method> -<method name="updateGadget" - return="void" - abstract="false" - native="false" - synchronized="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -<parameter name="gadgetIds" type="int[]"> -</parameter> -<parameter name="views" type="android.widget.RemoteViews"> -</parameter> -</method> -<method name="updateGadget" - return="void" - abstract="false" - native="false" - synchronized="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -<parameter name="gadgetId" type="int"> -</parameter> -<parameter name="views" type="android.widget.RemoteViews"> -</parameter> -</method> -<method name="updateGadget" - return="void" - abstract="false" - native="false" - synchronized="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -<parameter name="provider" type="android.content.ComponentName"> -</parameter> -<parameter name="views" type="android.widget.RemoteViews"> -</parameter> -</method> -<field name="ACTION_GADGET_CONFIGURE" - type="java.lang.String" - transient="false" - volatile="false" - value=""android.gadget.action.GADGET_CONFIGURE"" - static="true" - final="true" - deprecated="not deprecated" - visibility="public" -> -</field> -<field name="ACTION_GADGET_DELETED" - type="java.lang.String" - transient="false" - volatile="false" - value=""android.gadget.action.GADGET_DELETED"" - static="true" - final="true" - deprecated="not deprecated" - visibility="public" -> -</field> -<field name="ACTION_GADGET_DISABLED" - type="java.lang.String" - transient="false" - volatile="false" - value=""android.gadget.action.GADGET_DISABLED"" - static="true" - final="true" - deprecated="not deprecated" - visibility="public" -> -</field> -<field name="ACTION_GADGET_ENABLED" - type="java.lang.String" - transient="false" - volatile="false" - value=""android.gadget.action.GADGET_ENABLED"" - static="true" - final="true" - deprecated="not deprecated" - visibility="public" -> -</field> -<field name="ACTION_GADGET_PICK" - type="java.lang.String" - transient="false" - volatile="false" - value=""android.gadget.action.GADGET_PICK"" - static="true" - final="true" - deprecated="not deprecated" - visibility="public" -> -</field> -<field name="ACTION_GADGET_UPDATE" - type="java.lang.String" - transient="false" - volatile="false" - value=""android.gadget.action.GADGET_UPDATE"" - static="true" - final="true" - deprecated="not deprecated" - visibility="public" -> -</field> -<field name="EXTRA_GADGET_ID" - type="java.lang.String" - transient="false" - volatile="false" - value=""gadgetId"" - static="true" - final="true" - deprecated="not deprecated" - visibility="public" -> -</field> -<field name="EXTRA_GADGET_IDS" - type="java.lang.String" - transient="false" - volatile="false" - value=""gadgetIds"" - static="true" - final="true" - deprecated="not deprecated" - visibility="public" -> -</field> -<field name="INVALID_GADGET_ID" - type="int" - transient="false" - volatile="false" - value="0" - static="true" - final="true" - deprecated="not deprecated" - visibility="public" -> -</field> -<field name="META_DATA_GADGET_PROVIDER" - type="java.lang.String" - transient="false" - volatile="false" - value=""android.gadget.provider"" - static="true" - final="true" - deprecated="not deprecated" - visibility="public" -> -</field> -</class> -<class name="GadgetProvider" - extends="android.content.BroadcastReceiver" - abstract="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -<constructor name="GadgetProvider" - type="android.gadget.GadgetProvider" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -</constructor> -<method name="onDeleted" - return="void" - abstract="false" - native="false" - synchronized="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -<parameter name="context" type="android.content.Context"> -</parameter> -<parameter name="gadgetIds" type="int[]"> -</parameter> -</method> -<method name="onDisabled" - return="void" - abstract="false" - native="false" - synchronized="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -<parameter name="context" type="android.content.Context"> -</parameter> -</method> -<method name="onEnabled" - return="void" - abstract="false" - native="false" - synchronized="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -<parameter name="context" type="android.content.Context"> -</parameter> -</method> -<method name="onReceive" - return="void" - abstract="false" - native="false" - synchronized="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -<parameter name="context" type="android.content.Context"> -</parameter> -<parameter name="intent" type="android.content.Intent"> -</parameter> -</method> -<method name="onUpdate" - return="void" - abstract="false" - native="false" - synchronized="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -<parameter name="context" type="android.content.Context"> -</parameter> -<parameter name="gadgetManager" type="android.gadget.GadgetManager"> -</parameter> -<parameter name="gadgetIds" type="int[]"> -</parameter> -</method> -</class> -<class name="GadgetProviderInfo" - extends="java.lang.Object" - abstract="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -<implements name="android.os.Parcelable"> -</implements> -<constructor name="GadgetProviderInfo" - type="android.gadget.GadgetProviderInfo" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -</constructor> -<constructor name="GadgetProviderInfo" - type="android.gadget.GadgetProviderInfo" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -<parameter name="in" type="android.os.Parcel"> -</parameter> -</constructor> -<method name="describeContents" - return="int" - abstract="false" - native="false" - synchronized="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -</method> -<method name="writeToParcel" - return="void" - abstract="false" - native="false" - synchronized="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -<parameter name="out" type="android.os.Parcel"> -</parameter> -<parameter name="flags" type="int"> -</parameter> -</method> -<field name="CREATOR" - type="android.os.Parcelable.Creator" - transient="false" - volatile="false" - static="true" - final="true" - deprecated="not deprecated" - visibility="public" -> -</field> -<field name="configure" - type="android.content.ComponentName" - transient="false" - volatile="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -</field> -<field name="icon" - type="int" - transient="false" - volatile="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -</field> -<field name="initialLayout" - type="int" - transient="false" - volatile="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -</field> -<field name="label" - type="java.lang.String" - transient="false" - volatile="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -</field> -<field name="minHeight" - type="int" - transient="false" - volatile="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -</field> -<field name="minWidth" - type="int" - transient="false" - volatile="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -</field> -<field name="provider" - type="android.content.ComponentName" - transient="false" - volatile="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -</field> -<field name="updatePeriodMillis" - type="int" - transient="false" - volatile="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -</field> -</class> -</package> <package name="android.graphics" > <class name="AvoidXfermode" @@ -66030,7 +66019,7 @@ deprecated="not deprecated" visibility="public" > -<parameter name="l" type="android.media.MediaPlayer.OnErrorListener"> +<parameter name="listener" type="android.media.MediaPlayer.OnErrorListener"> </parameter> </method> <method name="setOnPreparedListener" @@ -85906,6 +85895,17 @@ visibility="public" > </field> +<field name="EXTRA_FORCE_CREATE" + type="java.lang.String" + transient="false" + volatile="false" + value=""com.android.contacts.action.FORCE_CREATE"" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="SEARCH_SUGGESTION_CLICKED" type="java.lang.String" transient="false" @@ -85939,6 +85939,17 @@ visibility="public" > </field> +<field name="SHOW_OR_CREATE_CONTACT" + type="java.lang.String" + transient="false" + volatile="false" + value=""com.android.contacts.action.SHOW_OR_CREATE_CONTACT"" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> </class> <class name="Contacts.Intents.Insert" extends="java.lang.Object" @@ -136709,6 +136720,17 @@ visibility="public" > </method> +<method name="getServiceInfo" + return="android.content.pm.ServiceInfo" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> <method name="getServiceName" return="java.lang.String" abstract="false" @@ -144486,6 +144508,19 @@ <parameter name="notifyOnChange" type="boolean"> </parameter> </method> +<method name="sort" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="comparator" type="java.util.Comparator<? super T>"> +</parameter> +</method> </class> <class name="AutoCompleteTextView" extends="android.widget.EditText" diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java index d447eb2..15e0a4d 100644 --- a/core/java/android/app/SearchDialog.java +++ b/core/java/android/app/SearchDialog.java @@ -31,6 +31,7 @@ import android.database.Cursor; import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Bundle; +import android.os.Handler; import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemClock; @@ -125,7 +126,14 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS // support for AutoCompleteTextView suggestions display private SuggestionsAdapter mSuggestionsAdapter; - + private Handler mHandler = new Handler(); + private Runnable mInstallSuggestionAdapter = new Runnable() { + public void run() { + if (mSearchTextField != null) { + mSearchTextField.setAdapter(mSuggestionsAdapter); + } + } + }; /** * Constructor - fires it up and makes it look like the search UI. @@ -253,7 +261,8 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS mSearchTextField.setAdapter(mSuggestionsAdapter); mSearchTextField.setText(initialQuery); } else { - mSuggestionsAdapter = new SuggestionsAdapter(getContext(), mSearchable); + mSuggestionsAdapter = new SuggestionsAdapter(getContext(), mSearchable, + mHandler, mInstallSuggestionAdapter); mSearchTextField.setAdapter(mSuggestionsAdapter); // finally, load the user's initial text (which may trigger suggestions) @@ -1296,10 +1305,15 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS // These private variables are shared by the filter thread and must be protected private WeakReference<Cursor> mRecentCursor = new WeakReference<Cursor>(null); private boolean mNonUserQuery = false; + private Handler mHandler; + private Runnable mInstallSuggestionAdapter; - public SuggestionsAdapter(Context context, SearchableInfo searchable) { + public SuggestionsAdapter(Context context, SearchableInfo searchable, + Handler handler, Runnable installSuggestionAdapter) { super(context, -1, null, null, null); mSearchable = searchable; + mHandler = handler; + mInstallSuggestionAdapter = installSuggestionAdapter; // set up provider resources (gives us icons, etc.) Context activityContext = mSearchable.getActivityContext(mContext); @@ -1414,7 +1428,11 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS } // Now actually set up the cursor, columns, and the list view changeCursorAndColumns(c, from, to); - setViewResource(layout); + setViewResource(layout); + // Force the underlying ListView to discard and reload all layouts + // (Note, this could be optimized for cases where layout/cursor remain same) + mHandler.post(mInstallSuggestionAdapter); + } else { // Provide some help for developers instead of just silently discarding Log.w(LOG_TAG, "Suggestions cursor discarded due to missing required columns."); diff --git a/core/java/android/gadget/GadgetHost.java b/core/java/android/appwidget/AppWidgetHost.java index 3d88b58..10c2b02 100644 --- a/core/java/android/gadget/GadgetHost.java +++ b/core/java/android/appwidget/AppWidgetHost.java @@ -1,5 +1,4 @@ /* - * Copyright (C) 2006 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. @@ -14,7 +13,7 @@ * limitations under the License. */ -package android.gadget; +package android.appwidget; import android.content.Context; import android.os.Handler; @@ -29,35 +28,35 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; -import com.android.internal.gadget.IGadgetHost; -import com.android.internal.gadget.IGadgetService; +import com.android.internal.appwidget.IAppWidgetHost; +import com.android.internal.appwidget.IAppWidgetService; /** - * GadgetHost provides the interaction with the Gadget Service for apps, - * like the home screen, that want to embed gadgets in their UI. + * AppWidgetHost provides the interaction with the AppWidget service for apps, + * like the home screen, that want to embed AppWidgets in their UI. */ -public class GadgetHost { +public class AppWidgetHost { static final int HANDLE_UPDATE = 1; static final int HANDLE_PROVIDER_CHANGED = 2; static Object sServiceLock = new Object(); - static IGadgetService sService; + static IAppWidgetService sService; Context mContext; String mPackageName; - class Callbacks extends IGadgetHost.Stub { - public void updateGadget(int gadgetId, RemoteViews views) { + class Callbacks extends IAppWidgetHost.Stub { + public void updateAppWidget(int appWidgetId, RemoteViews views) { Message msg = mHandler.obtainMessage(HANDLE_UPDATE); - msg.arg1 = gadgetId; + msg.arg1 = appWidgetId; msg.obj = views; msg.sendToTarget(); } - public void providerChanged(int gadgetId, GadgetProviderInfo info) { + public void providerChanged(int appWidgetId, AppWidgetProviderInfo info) { Message msg = mHandler.obtainMessage(HANDLE_PROVIDER_CHANGED); - msg.arg1 = gadgetId; + msg.arg1 = appWidgetId; msg.obj = info; msg.sendToTarget(); } @@ -71,11 +70,11 @@ public class GadgetHost { public void handleMessage(Message msg) { switch (msg.what) { case HANDLE_UPDATE: { - updateGadgetView(msg.arg1, (RemoteViews)msg.obj); + updateAppWidgetView(msg.arg1, (RemoteViews)msg.obj); break; } case HANDLE_PROVIDER_CHANGED: { - onProviderChanged(msg.arg1, (GadgetProviderInfo)msg.obj); + onProviderChanged(msg.arg1, (AppWidgetProviderInfo)msg.obj); break; } } @@ -86,22 +85,22 @@ public class GadgetHost { int mHostId; Callbacks mCallbacks = new Callbacks(); - HashMap<Integer,GadgetHostView> mViews = new HashMap(); + HashMap<Integer,AppWidgetHostView> mViews = new HashMap(); - public GadgetHost(Context context, int hostId) { + public AppWidgetHost(Context context, int hostId) { mContext = context; mHostId = hostId; mHandler = new UpdateHandler(context.getMainLooper()); synchronized (sServiceLock) { if (sService == null) { - IBinder b = ServiceManager.getService(Context.GADGET_SERVICE); - sService = IGadgetService.Stub.asInterface(b); + IBinder b = ServiceManager.getService(Context.APPWIDGET_SERVICE); + sService = IAppWidgetService.Stub.asInterface(b); } } } /** - * Start receiving onGadgetChanged calls for your gadgets. Call this when your activity + * Start receiving onAppWidgetChanged calls for your AppWidgets. Call this when your activity * becomes visible, i.e. from onStart() in your Activity. */ public void startListening() { @@ -120,12 +119,12 @@ public class GadgetHost { final int N = updatedIds.length; for (int i=0; i<N; i++) { - updateGadgetView(updatedIds[i], updatedViews.get(i)); + updateAppWidgetView(updatedIds[i], updatedViews.get(i)); } } /** - * Stop receiving onGadgetChanged calls for your gadgets. Call this when your activity is + * Stop receiving onAppWidgetChanged calls for your AppWidgets. Call this when your activity is * no longer visible, i.e. from onStop() in your Activity. */ public void stopListening() { @@ -138,16 +137,16 @@ public class GadgetHost { } /** - * Get a gadgetId for a host in the calling process. + * Get a appWidgetId for a host in the calling process. * - * @return a gadgetId + * @return a appWidgetId */ - public int allocateGadgetId() { + public int allocateAppWidgetId() { try { if (mPackageName == null) { mPackageName = mContext.getPackageName(); } - return sService.allocateGadgetId(mPackageName, mHostId); + return sService.allocateAppWidgetId(mPackageName, mHostId); } catch (RemoteException e) { throw new RuntimeException("system server dead?", e); @@ -155,13 +154,13 @@ public class GadgetHost { } /** - * Stop listening to changes for this gadget. + * Stop listening to changes for this AppWidget. */ - public void deleteGadgetId(int gadgetId) { + public void deleteAppWidgetId(int appWidgetId) { synchronized (mViews) { - mViews.remove(gadgetId); + mViews.remove(appWidgetId); try { - sService.deleteGadgetId(gadgetId); + sService.deleteAppWidgetId(appWidgetId); } catch (RemoteException e) { throw new RuntimeException("system server dead?", e); @@ -170,10 +169,10 @@ public class GadgetHost { } /** - * Remove all records about this host from the gadget manager. + * Remove all records about this host from the AppWidget manager. * <ul> * <li>Call this when initializing your database, as it might be because of a data wipe.</li> - * <li>Call this to have the gadget manager release all resources associated with your + * <li>Call this to have the AppWidget manager release all resources associated with your * host. Any future calls about this host will cause the records to be re-allocated.</li> * </ul> */ @@ -190,7 +189,7 @@ public class GadgetHost { * Remove all records about all hosts for your package. * <ul> * <li>Call this when initializing your database, as it might be because of a data wipe.</li> - * <li>Call this to have the gadget manager release all resources associated with your + * <li>Call this to have the AppWidget manager release all resources associated with your * host. Any future calls about this host will cause the records to be re-allocated.</li> * </ul> */ @@ -203,45 +202,45 @@ public class GadgetHost { } } - public final GadgetHostView createView(Context context, int gadgetId, - GadgetProviderInfo gadget) { - GadgetHostView view = onCreateView(context, gadgetId, gadget); - view.setGadget(gadgetId, gadget); + public final AppWidgetHostView createView(Context context, int appWidgetId, + AppWidgetProviderInfo appWidget) { + AppWidgetHostView view = onCreateView(context, appWidgetId, appWidget); + view.setAppWidget(appWidgetId, appWidget); synchronized (mViews) { - mViews.put(gadgetId, view); + mViews.put(appWidgetId, view); } RemoteViews views = null; try { - views = sService.getGadgetViews(gadgetId); + views = sService.getAppWidgetViews(appWidgetId); } catch (RemoteException e) { throw new RuntimeException("system server dead?", e); } - view.updateGadget(views); + view.updateAppWidget(views); return view; } /** - * Called to create the GadgetHostView. Override to return a custom subclass if you + * Called to create the AppWidgetHostView. Override to return a custom subclass if you * need it. {@more} */ - protected GadgetHostView onCreateView(Context context, int gadgetId, - GadgetProviderInfo gadget) { - return new GadgetHostView(context); + protected AppWidgetHostView onCreateView(Context context, int appWidgetId, + AppWidgetProviderInfo appWidget) { + return new AppWidgetHostView(context); } /** - * Called when the gadget provider for a gadget has been upgraded to a new apk. + * Called when the AppWidget provider for a AppWidget has been upgraded to a new apk. */ - protected void onProviderChanged(int gadgetId, GadgetProviderInfo gadget) { + protected void onProviderChanged(int appWidgetId, AppWidgetProviderInfo appWidget) { } - void updateGadgetView(int gadgetId, RemoteViews views) { - GadgetHostView v; + void updateAppWidgetView(int appWidgetId, RemoteViews views) { + AppWidgetHostView v; synchronized (mViews) { - v = mViews.get(gadgetId); + v = mViews.get(appWidgetId); } if (v != null) { - v.updateGadget(views); + v.updateAppWidget(views); } } } diff --git a/core/java/android/gadget/GadgetHostView.java b/core/java/android/appwidget/AppWidgetHostView.java index 5cbd988..be0f96e 100644 --- a/core/java/android/gadget/GadgetHostView.java +++ b/core/java/android/appwidget/AppWidgetHostView.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package android.gadget; +package android.appwidget; import android.content.Context; import android.content.pm.PackageManager; @@ -37,12 +37,12 @@ import android.widget.RemoteViews; import android.widget.TextView; /** - * Provides the glue to show gadget views. This class offers automatic animation + * Provides the glue to show AppWidget views. This class offers automatic animation * between updates, and will try recycling old views for each incoming * {@link RemoteViews}. */ -public class GadgetHostView extends FrameLayout { - static final String TAG = "GadgetHostView"; +public class AppWidgetHostView extends FrameLayout { + static final String TAG = "AppWidgetHostView"; static final boolean LOGD = false; static final boolean CROSSFADE = false; @@ -53,7 +53,7 @@ public class GadgetHostView extends FrameLayout { static final int FADE_DURATION = 1000; - // When we're inflating the initialLayout for a gadget, we only allow + // When we're inflating the initialLayout for a AppWidget, we only allow // views that are allowed in RemoteViews. static final LayoutInflater.Filter sInflaterFilter = new LayoutInflater.Filter() { public boolean onLoadClass(Class clazz) { @@ -63,8 +63,8 @@ public class GadgetHostView extends FrameLayout { Context mContext; - int mGadgetId; - GadgetProviderInfo mInfo; + int mAppWidgetId; + AppWidgetProviderInfo mInfo; View mView; int mViewMode = VIEW_MODE_NOINIT; int mLayoutId = -1; @@ -75,44 +75,44 @@ public class GadgetHostView extends FrameLayout { /** * Create a host view. Uses default fade animations. */ - public GadgetHostView(Context context) { + public AppWidgetHostView(Context context) { this(context, android.R.anim.fade_in, android.R.anim.fade_out); } /** * Create a host view. Uses specified animations when pushing - * {@link #updateGadget(RemoteViews)}. + * {@link #updateAppWidget(RemoteViews)}. * * @param animationIn Resource ID of in animation to use * @param animationOut Resource ID of out animation to use */ - public GadgetHostView(Context context, int animationIn, int animationOut) { + public AppWidgetHostView(Context context, int animationIn, int animationOut) { super(context); mContext = context; } /** - * Set the gadget that will be displayed by this view. + * Set the AppWidget that will be displayed by this view. */ - public void setGadget(int gadgetId, GadgetProviderInfo info) { - mGadgetId = gadgetId; + public void setAppWidget(int appWidgetId, AppWidgetProviderInfo info) { + mAppWidgetId = appWidgetId; mInfo = info; } - public int getGadgetId() { - return mGadgetId; + public int getAppWidgetId() { + return mAppWidgetId; } - public GadgetProviderInfo getGadgetInfo() { + public AppWidgetProviderInfo getAppWidgetInfo() { return mInfo; } /** * Process a set of {@link RemoteViews} coming in as an update from the - * gadget provider. Will animate into these new views as needed. + * AppWidget provider. Will animate into these new views as needed. */ - public void updateGadget(RemoteViews remoteViews) { - if (LOGD) Log.d(TAG, "updateGadget called mOld=" + mOld); + public void updateAppWidget(RemoteViews remoteViews) { + if (LOGD) Log.d(TAG, "updateAppWidget called mOld=" + mOld); boolean recycled = false; View content = null; @@ -180,7 +180,7 @@ public class GadgetHostView extends FrameLayout { // We've already done this -- nothing to do. return ; } - Log.w(TAG, "updateGadget couldn't find any view, using error view", exception); + Log.w(TAG, "updateAppWidget couldn't find any view, using error view", exception); content = getErrorView(); mViewMode = VIEW_MODE_ERROR; } @@ -263,7 +263,7 @@ public class GadgetHostView extends FrameLayout { } /** - * Inflate and return the default layout requested by gadget provider. + * Inflate and return the default layout requested by AppWidget provider. */ protected View getDefaultView() { View defaultView = null; @@ -288,7 +288,7 @@ public class GadgetHostView extends FrameLayout { } if (exception != null && LOGD) { - Log.w(TAG, "Error inflating gadget " + mInfo, exception); + Log.w(TAG, "Error inflating AppWidget " + mInfo, exception); } if (defaultView == null) { diff --git a/core/java/android/appwidget/AppWidgetManager.java b/core/java/android/appwidget/AppWidgetManager.java new file mode 100644 index 0000000..3b10ed2 --- /dev/null +++ b/core/java/android/appwidget/AppWidgetManager.java @@ -0,0 +1,320 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.appwidget; + +import android.content.ComponentName; +import android.content.Context; +import android.os.IBinder; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.util.Log; +import android.widget.RemoteViews; + +import com.android.internal.appwidget.IAppWidgetService; + +import java.lang.ref.WeakReference; +import java.util.List; +import java.util.WeakHashMap; + +/** + * Updates AppWidget state; gets information about installed AppWidget providers and other + * AppWidget related state. + */ +public class AppWidgetManager { + static final String TAG = "AppWidgetManager"; + + /** + * Send this from your {@link AppWidgetHost} activity when you want to pick an AppWidget to display. + * The AppWidget picker activity will be launched. + * <p> + * You must supply the following extras: + * <table> + * <tr> + * <td>{@link #EXTRA_APPWIDGET_ID}</td> + * <td>A newly allocated appWidgetId, which will be bound to the AppWidget provider + * once the user has selected one.</td> + * </tr> + * </table> + * + * <p> + * The system will respond with an onActivityResult call with the following extras in + * the intent: + * <table> + * <tr> + * <td>{@link #EXTRA_APPWIDGET_ID}</td> + * <td>The appWidgetId that you supplied in the original intent.</td> + * </tr> + * </table> + * <p> + * When you receive the result from the AppWidget pick activity, if the resultCode is + * {@link android.app.Activity#RESULT_OK}, an AppWidget has been selected. You should then + * check the AppWidgetProviderInfo for the returned AppWidget, and if it has one, launch its configuration + * activity. If {@link android.app.Activity#RESULT_CANCELED} is returned, you should delete + * the appWidgetId. + * + * @see #ACTION_APPWIDGET_CONFIGURE + */ + public static final String ACTION_APPWIDGET_PICK = "android.appwidget.action.APPWIDGET_PICK"; + + /** + * Sent when it is time to configure your AppWidget while it is being added to a host. + * This action is not sent as a broadcast to the AppWidget provider, but as a startActivity + * to the activity specified in the {@link AppWidgetProviderInfo AppWidgetProviderInfo meta-data}. + * + * <p> + * The intent will contain the following extras: + * <table> + * <tr> + * <td>{@link #EXTRA_APPWIDGET_ID}</td> + * <td>The appWidgetId to configure.</td> + * </tr> + * </table> + * + * <p>If you return {@link android.app.Activity#RESULT_OK} using + * {@link android.app.Activity#setResult Activity.setResult()}, the AppWidget will be added, + * and you will receive an {@link #ACTION_APPWIDGET_UPDATE} broadcast for this AppWidget. + * If you return {@link android.app.Activity#RESULT_CANCELED}, the host will cancel the add + * and not display this AppWidget, and you will receive a {@link #ACTION_APPWIDGET_DELETED} broadcast. + */ + public static final String ACTION_APPWIDGET_CONFIGURE = "android.appwidget.action.APPWIDGET_CONFIGURE"; + + /** + * An intent extra that contains one appWidgetId. + * <p> + * The value will be an int that can be retrieved like this: + * {@sample frameworks/base/tests/appwidgets/AppWidgetHostTest/src/com/android/tests/appwidgethost/AppWidgetHostActivity.java getExtra_EXTRA_APPWIDGET_ID} + */ + public static final String EXTRA_APPWIDGET_ID = "appWidgetId"; + + /** + * An intent extra that contains multiple appWidgetIds. + * <p> + * The value will be an int array that can be retrieved like this: + * {@sample frameworks/base/tests/appwidgets/AppWidgetHostTest/src/com/android/tests/appwidgethost/TestAppWidgetProvider.java getExtra_EXTRA_APPWIDGET_IDS} + */ + public static final String EXTRA_APPWIDGET_IDS = "appWidgetIds"; + + /** + * A sentiel value that the AppWidget manager will never return as a appWidgetId. + */ + public static final int INVALID_APPWIDGET_ID = 0; + + /** + * Sent when it is time to update your AppWidget. + * + * <p>This may be sent in response to a new instance for this AppWidget provider having + * been instantiated, the requested {@link AppWidgetProviderInfo#updatePeriodMillis update interval} + * having lapsed, or the system booting. + * + * <p> + * The intent will contain the following extras: + * <table> + * <tr> + * <td>{@link #EXTRA_APPWIDGET_IDS}</td> + * <td>The appWidgetIds to update. This may be all of the AppWidgets created for this + * provider, or just a subset. The system tries to send updates for as few AppWidget + * instances as possible.</td> + * </tr> + * </table> + * + * @see AppWidgetProvider#onUpdate AppWidgetProvider.onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) + */ + public static final String ACTION_APPWIDGET_UPDATE = "android.appwidget.action.APPWIDGET_UPDATE"; + + /** + * Sent when an instance of an AppWidget is deleted from its host. + * + * @see AppWidgetProvider#onDeleted AppWidgetProvider.onDeleted(Context context, int[] appWidgetIds) + */ + public static final String ACTION_APPWIDGET_DELETED = "android.appwidget.action.APPWIDGET_DELETED"; + + /** + * Sent when an instance of an AppWidget is removed from the last host. + * + * @see AppWidgetProvider#onEnabled AppWidgetProvider.onEnabled(Context context) + */ + public static final String ACTION_APPWIDGET_DISABLED = "android.appwidget.action.APPWIDGET_DISABLED"; + + /** + * Sent when an instance of an AppWidget is added to a host for the first time. + * This broadcast is sent at boot time if there is a AppWidgetHost installed with + * an instance for this provider. + * + * @see AppWidgetProvider#onEnabled AppWidgetProvider.onEnabled(Context context) + */ + public static final String ACTION_APPWIDGET_ENABLED = "android.appwidget.action.APPWIDGET_ENABLED"; + + /** + * Field for the manifest meta-data tag. + * + * @see AppWidgetProviderInfo + */ + public static final String META_DATA_APPWIDGET_PROVIDER = "android.appwidget.provider"; + + static WeakHashMap<Context, WeakReference<AppWidgetManager>> sManagerCache = new WeakHashMap(); + static IAppWidgetService sService; + + Context mContext; + + /** + * Get the AppWidgetManager instance to use for the supplied {@link android.content.Context + * Context} object. + */ + public static AppWidgetManager getInstance(Context context) { + synchronized (sManagerCache) { + if (sService == null) { + IBinder b = ServiceManager.getService(Context.APPWIDGET_SERVICE); + sService = IAppWidgetService.Stub.asInterface(b); + } + + WeakReference<AppWidgetManager> ref = sManagerCache.get(context); + AppWidgetManager result = null; + if (ref != null) { + result = ref.get(); + } + if (result == null) { + result = new AppWidgetManager(context); + sManagerCache.put(context, new WeakReference(result)); + } + return result; + } + } + + private AppWidgetManager(Context context) { + mContext = context; + } + + /** + * Set the RemoteViews to use for the specified appWidgetIds. + * + * <p> + * It is okay to call this method both inside an {@link #ACTION_APPWIDGET_UPDATE} broadcast, + * and outside of the handler. + * This method will only work when called from the uid that owns the AppWidget provider. + * + * @param appWidgetIds The AppWidget instances for which to set the RemoteViews. + * @param views The RemoteViews object to show. + */ + public void updateAppWidget(int[] appWidgetIds, RemoteViews views) { + try { + sService.updateAppWidgetIds(appWidgetIds, views); + } + catch (RemoteException e) { + throw new RuntimeException("system server dead?", e); + } + } + + /** + * Set the RemoteViews to use for the specified appWidgetId. + * + * <p> + * It is okay to call this method both inside an {@link #ACTION_APPWIDGET_UPDATE} broadcast, + * and outside of the handler. + * This method will only work when called from the uid that owns the AppWidget provider. + * + * @param appWidgetId The AppWidget instance for which to set the RemoteViews. + * @param views The RemoteViews object to show. + */ + public void updateAppWidget(int appWidgetId, RemoteViews views) { + updateAppWidget(new int[] { appWidgetId }, views); + } + + /** + * Set the RemoteViews to use for all AppWidget instances for the supplied AppWidget provider. + * + * <p> + * It is okay to call this method both inside an {@link #ACTION_APPWIDGET_UPDATE} broadcast, + * and outside of the handler. + * This method will only work when called from the uid that owns the AppWidget provider. + * + * @param provider The {@link ComponentName} for the {@link + * android.content.BroadcastReceiver BroadcastReceiver} provider + * for your AppWidget. + * @param views The RemoteViews object to show. + */ + public void updateAppWidget(ComponentName provider, RemoteViews views) { + try { + sService.updateAppWidgetProvider(provider, views); + } + catch (RemoteException e) { + throw new RuntimeException("system server dead?", e); + } + } + + /** + * Return a list of the AppWidget providers that are currently installed. + */ + public List<AppWidgetProviderInfo> getInstalledProviders() { + try { + return sService.getInstalledProviders(); + } + catch (RemoteException e) { + throw new RuntimeException("system server dead?", e); + } + } + + /** + * Get the available info about the AppWidget. + * + * @return A appWidgetId. If the appWidgetId has not been bound to a provider yet, or + * you don't have access to that appWidgetId, null is returned. + */ + public AppWidgetProviderInfo getAppWidgetInfo(int appWidgetId) { + try { + return sService.getAppWidgetInfo(appWidgetId); + } + catch (RemoteException e) { + throw new RuntimeException("system server dead?", e); + } + } + + /** + * Set the component for a given appWidgetId. + * + * <p class="note">You need the APPWIDGET_LIST permission. This method is to be used by the + * AppWidget picker. + * + * @param appWidgetId The AppWidget instance for which to set the RemoteViews. + * @param provider The {@link android.content.BroadcastReceiver} that will be the AppWidget + * provider for this AppWidget. + */ + public void bindAppWidgetId(int appWidgetId, ComponentName provider) { + try { + sService.bindAppWidgetId(appWidgetId, provider); + } + catch (RemoteException e) { + throw new RuntimeException("system server dead?", e); + } + } + + /** + * Get the list of appWidgetIds that have been bound to the given AppWidget + * provider. + * + * @param provider The {@link android.content.BroadcastReceiver} that is the + * AppWidget provider to find appWidgetIds for. + */ + public int[] getAppWidgetIds(ComponentName provider) { + try { + return sService.getAppWidgetIds(provider); + } + catch (RemoteException e) { + throw new RuntimeException("system server dead?", e); + } + } +} + diff --git a/core/java/android/appwidget/AppWidgetProvider.java b/core/java/android/appwidget/AppWidgetProvider.java new file mode 100755 index 0000000..f70de9c --- /dev/null +++ b/core/java/android/appwidget/AppWidgetProvider.java @@ -0,0 +1,154 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.appwidget; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; + +/** + * A conveience class to aid in implementing an AppWidget provider. + * Everything you can do with AppWidgetProvider, you can do with a regular {@link BroadcastReceiver}. + * AppWidgetProvider merely parses the relevant fields out of the Intent that is received in + * {@link #onReceive(Context,Intent) onReceive(Context,Intent)}, and calls hook methods + * with the received extras. + * + * <p>Extend this class and override one or more of the {@link #onUpdate}, {@link #onDeleted}, + * {@link #onEnabled} or {@link #onDisabled} methods to implement your own AppWidget functionality. + * + * <h3>Sample Code</h3> + * For an example of how to write a AppWidget provider, see the + * <a href="{@toroot}reference/android/appwidget/package-descr.html#providers">android.appwidget + * package overview</a>. + */ +public class AppWidgetProvider extends BroadcastReceiver { + /** + * Constructor to initialize AppWidgetProvider. + */ + public AppWidgetProvider() { + } + + /** + * Implements {@link BroadcastReceiver#onReceive} to dispatch calls to the various + * other methods on AppWidgetProvider. + * + * @param context The Context in which the receiver is running. + * @param intent The Intent being received. + */ + // BEGIN_INCLUDE(onReceive) + public void onReceive(Context context, Intent intent) { + // Protect against rogue update broadcasts (not really a security issue, + // just filter bad broacasts out so subclasses are less likely to crash). + String action = intent.getAction(); + if (AppWidgetManager.ACTION_APPWIDGET_UPDATE.equals(action)) { + Bundle extras = intent.getExtras(); + if (extras != null) { + int[] appWidgetIds = extras.getIntArray(AppWidgetManager.EXTRA_APPWIDGET_IDS); + if (appWidgetIds != null && appWidgetIds.length > 0) { + this.onUpdate(context, AppWidgetManager.getInstance(context), appWidgetIds); + } + } + } + else if (AppWidgetManager.ACTION_APPWIDGET_DELETED.equals(action)) { + Bundle extras = intent.getExtras(); + if (extras != null) { + int[] appWidgetIds = extras.getIntArray(AppWidgetManager.EXTRA_APPWIDGET_IDS); + if (appWidgetIds != null && appWidgetIds.length > 0) { + this.onDeleted(context, appWidgetIds); + } + } + } + else if (AppWidgetManager.ACTION_APPWIDGET_ENABLED.equals(action)) { + this.onEnabled(context); + } + else if (AppWidgetManager.ACTION_APPWIDGET_DISABLED.equals(action)) { + this.onDisabled(context); + } + } + // END_INCLUDE(onReceive) + + /** + * Called in response to the {@link AppWidgetManager#ACTION_APPWIDGET_UPDATE} broadcast when + * this AppWidget provider is being asked to provide {@link android.widget.RemoteViews RemoteViews} + * for a set of AppWidgets. Override this method to implement your own AppWidget functionality. + * + * {@more} + * + * @param context The {@link android.content.Context Context} in which this receiver is + * running. + * @param appWidgetManager A {@link AppWidgetManager} object you can call {@link + * AppWidgetManager#updateAppWidget} on. + * @param appWidgetIds The appWidgetIds for which an update is needed. Note that this + * may be all of the AppWidget instances for this provider, or just + * a subset of them. + * + * @see AppWidgetManager#ACTION_APPWIDGET_UPDATE + */ + public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { + } + + /** + * Called in response to the {@link AppWidgetManager#ACTION_APPWIDGET_DELETED} broadcast when + * one or more AppWidget instances have been deleted. Override this method to implement + * your own AppWidget functionality. + * + * {@more} + * + * @param context The {@link android.content.Context Context} in which this receiver is + * running. + * @param appWidgetIds The appWidgetIds that have been deleted from their host. + * + * @see AppWidgetManager#ACTION_APPWIDGET_DELETED + */ + public void onDeleted(Context context, int[] appWidgetIds) { + } + + /** + * Called in response to the {@link AppWidgetManager#ACTION_APPWIDGET_ENABLED} broadcast when + * the a AppWidget for this provider is instantiated. Override this method to implement your + * own AppWidget functionality. + * + * {@more} + * When the last AppWidget for this provider is deleted, + * {@link AppWidgetManager#ACTION_APPWIDGET_DISABLED} is sent by the AppWidget manager, and + * {@link #onDisabled} is called. If after that, an AppWidget for this provider is created + * again, onEnabled() will be called again. + * + * @param context The {@link android.content.Context Context} in which this receiver is + * running. + * + * @see AppWidgetManager#ACTION_APPWIDGET_ENABLED + */ + public void onEnabled(Context context) { + } + + /** + * Called in response to the {@link AppWidgetManager#ACTION_APPWIDGET_DISABLED} broadcast, which + * is sent when the last AppWidget instance for this provider is deleted. Override this method + * to implement your own AppWidget functionality. + * + * {@more} + * + * @param context The {@link android.content.Context Context} in which this receiver is + * running. + * + * @see AppWidgetManager#ACTION_APPWIDGET_DISABLED + */ + public void onDisabled(Context context) { + } +} diff --git a/core/java/android/gadget/GadgetProviderInfo.aidl b/core/java/android/appwidget/AppWidgetProviderInfo.aidl index 589f886..82b3ada 100644 --- a/core/java/android/gadget/GadgetProviderInfo.aidl +++ b/core/java/android/appwidget/AppWidgetProviderInfo.aidl @@ -14,6 +14,6 @@ * limitations under the License. */ -package android.gadget; +package android.appwidget; -parcelable GadgetProviderInfo; +parcelable AppWidgetProviderInfo; diff --git a/core/java/android/gadget/GadgetProviderInfo.java b/core/java/android/appwidget/AppWidgetProviderInfo.java index 95c0432..8530c35 100644 --- a/core/java/android/gadget/GadgetProviderInfo.java +++ b/core/java/android/appwidget/AppWidgetProviderInfo.java @@ -14,21 +14,21 @@ * limitations under the License. */ -package android.gadget; +package android.appwidget; import android.os.Parcel; import android.os.Parcelable; import android.content.ComponentName; /** - * Describes the meta data for an installed gadget provider. The fields in this class - * correspond to the fields in the <code><gadget-provider></code> xml tag. + * Describes the meta data for an installed AppWidget provider. The fields in this class + * correspond to the fields in the <code><appwidget-provider></code> xml tag. */ -public class GadgetProviderInfo implements Parcelable { +public class AppWidgetProviderInfo implements Parcelable { /** - * Identity of this gadget component. This component should be a {@link - * android.content.BroadcastReceiver}, and it will be sent the Gadget intents - * {@link android.gadget as described in the gadget package documentation}. + * Identity of this AppWidget component. This component should be a {@link + * android.content.BroadcastReceiver}, and it will be sent the AppWidget intents + * {@link android.appwidget as described in the AppWidget package documentation}. * * <p>This field corresponds to the <code>android:name</code> attribute in * the <code><receiver></code> element in the AndroidManifest.xml file. @@ -36,50 +36,50 @@ public class GadgetProviderInfo implements Parcelable { public ComponentName provider; /** - * Minimum width of the gadget, in dp. + * Minimum width of the AppWidget, in dp. * * <p>This field corresponds to the <code>android:minWidth</code> attribute in - * the gadget meta-data file. + * the AppWidget meta-data file. */ public int minWidth; /** - * Minimum height of the gadget, in dp. + * Minimum height of the AppWidget, in dp. * * <p>This field corresponds to the <code>android:minHeight</code> attribute in - * the gadget meta-data file. + * the AppWidget meta-data file. */ public int minHeight; /** - * How often, in milliseconds, that this gadget wants to be updated. - * The gadget manager may place a limit on how often a gadget is updated. + * How often, in milliseconds, that this AppWidget wants to be updated. + * The AppWidget manager may place a limit on how often a AppWidget is updated. * * <p>This field corresponds to the <code>android:updatePeriodMillis</code> attribute in - * the gadget meta-data file. + * the AppWidget meta-data file. */ public int updatePeriodMillis; /** - * The resource id of the initial layout for this gadget. This should be - * displayed until the RemoteViews for the gadget is available. + * The resource id of the initial layout for this AppWidget. This should be + * displayed until the RemoteViews for the AppWidget is available. * * <p>This field corresponds to the <code>android:initialLayout</code> attribute in - * the gadget meta-data file. + * the AppWidget meta-data file. */ public int initialLayout; /** - * The activity to launch that will configure the gadget. + * The activity to launch that will configure the AppWidget. * * <p>This class name of field corresponds to the <code>android:configure</code> attribute in - * the gadget meta-data file. The package name always corresponds to the package containing - * the gadget provider. + * the AppWidget meta-data file. The package name always corresponds to the package containing + * the AppWidget provider. */ public ComponentName configure; /** - * The label to display to the user in the gadget picker. If not supplied in the + * The label to display to the user in the AppWidget picker. If not supplied in the * xml, the application label will be used. * * <p>This field corresponds to the <code>android:label</code> attribute in @@ -88,7 +88,7 @@ public class GadgetProviderInfo implements Parcelable { public String label; /** - * The icon to display for this gadget in the gadget picker. If not supplied in the + * The icon to display for this AppWidget in the AppWidget picker. If not supplied in the * xml, the application icon will be used. * * <p>This field corresponds to the <code>android:icon</code> attribute in @@ -96,13 +96,13 @@ public class GadgetProviderInfo implements Parcelable { */ public int icon; - public GadgetProviderInfo() { + public AppWidgetProviderInfo() { } /** - * Unflatten the GadgetProviderInfo from a parcel. + * Unflatten the AppWidgetProviderInfo from a parcel. */ - public GadgetProviderInfo(Parcel in) { + public AppWidgetProviderInfo(Parcel in) { if (0 != in.readInt()) { this.provider = new ComponentName(in); } @@ -144,24 +144,24 @@ public class GadgetProviderInfo implements Parcelable { } /** - * Parcelable.Creator that instantiates GadgetProviderInfo objects + * Parcelable.Creator that instantiates AppWidgetProviderInfo objects */ - public static final Parcelable.Creator<GadgetProviderInfo> CREATOR - = new Parcelable.Creator<GadgetProviderInfo>() + public static final Parcelable.Creator<AppWidgetProviderInfo> CREATOR + = new Parcelable.Creator<AppWidgetProviderInfo>() { - public GadgetProviderInfo createFromParcel(Parcel parcel) + public AppWidgetProviderInfo createFromParcel(Parcel parcel) { - return new GadgetProviderInfo(parcel); + return new AppWidgetProviderInfo(parcel); } - public GadgetProviderInfo[] newArray(int size) + public AppWidgetProviderInfo[] newArray(int size) { - return new GadgetProviderInfo[size]; + return new AppWidgetProviderInfo[size]; } }; public String toString() { - return "GadgetProviderInfo(provider=" + this.provider + ")"; + return "AppWidgetProviderInfo(provider=" + this.provider + ")"; } } diff --git a/core/java/android/appwidget/package.html b/core/java/android/appwidget/package.html new file mode 100644 index 0000000..b6cd9c7 --- /dev/null +++ b/core/java/android/appwidget/package.html @@ -0,0 +1,136 @@ +<body> +<p>Android allows applications to publish views to be embedded in other applications. These +views are called widgets, and are published by "AppWidget providers." The component that can +contain widgets is called a "AppWidget host." +</p> +<h3><a href="package-descr.html#providers">AppWidget Providers</a></h3> +<ul> + <li><a href="package-descr.html#provider_manifest">Declaring a widget in the AndroidManifest</a></li> + <li><a href="package-descr.html#provider_meta_data">Adding the AppWidgetProviderInfo meta-data</a></li> + <li><a href="package-descr.html#provider_AppWidgetProvider">Using the AppWidgetProvider class</a></li> + <li><a href="package-descr.html#provider_configuration">AppWidget Configuration UI</a></li> + <li><a href="package-descr.html#provider_broadcasts">AppWidget Broadcast Intents</a></li> +</ul> +<h3><a href="package-descr.html#">AppWidget Hosts</a></h3> + + +{@more} + + +<h2><a name="providers"></a>AppWidget Providers</h2> +<p> +Any application can publish widgets. All an application needs to do to publish a widget is +to have a {@link android.content.BroadcastReceiver} that receives the {@link +android.appwidget.AppWidgetManager#ACTION_APPWIDGET_UPDATE AppWidgetManager.ACTION_APPWIDGET_UPDATE} intent, +and provide some meta-data about the widget. Android provides the +{@link android.appwidget.AppWidgetProvider} class, which extends BroadcastReceiver, as a convenience +class to aid in handling the broadcasts. + +<h3><a name="provider_manifest"></a>Declaring a widget in the AndroidManifest</h3> + +<p> +First, declare the {@link android.content.BroadcastReceiver} in your application's +<code>AndroidManifest.xml</code> file. + +{@sample frameworks/base/tests/appwidgets/AppWidgetHostTest/AndroidManifest.xml AppWidgetProvider} + +<p> +The <b><code><receiver></b> element has the following attributes: +<ul> + <li><b><code>android:name</code> -</b> which specifies the + {@link android.content.BroadcastReceiver} or {@link android.appwidget.AppWidgetProvider} + class.</li> + <li><b><code>android:label</code> -</b> which specifies the string resource that + will be shown by the widget picker as the label.</li> + <li><b><code>android:icon</code> -</b> which specifies the drawable resource that + will be shown by the widget picker as the icon.</li> +</ul> + +<p> +The <b><code><intent-filter></b> element tells the {@link android.content.pm.PackageManager} +that this {@link android.content.BroadcastReceiver} receives the {@link +android.appwidget.AppWidgetManager#ACTION_APPWIDGET_UPDATE AppWidgetManager.ACTION_APPWIDGET_UPDATE} broadcast. +The widget manager will send other broadcasts directly to your widget provider as required. +It is only necessary to explicitly declare that you accept the {@link +android.appwidget.AppWidgetManager#ACTION_APPWIDGET_UPDATE AppWidgetManager.ACTION_APPWIDGET_UPDATE} broadcast. + +<p> +The <b><code><meta-data></code></b> element tells the widget manager which xml resource to +read to find the {@link android.appwidget.AppWidgetProviderInfo} for your widget provider. It has the following +attributes: +<ul> + <li><b><code>android:name="android.appwidget.provider"</code> -</b> identifies this meta-data + as the {@link android.appwidget.AppWidgetProviderInfo} descriptor.</li> + <li><b><code>android:resource</code> -</b> is the xml resource to use as that descriptor.</li> +</ul> + + +<h3><a name="provider_meta_data"></a>Adding the {@link android.appwidget.AppWidgetProviderInfo AppWidgetProviderInfo} meta-data</h3> + +<p> +For a widget, the values in the {@link android.appwidget.AppWidgetProviderInfo} structure are supplied +in an XML resource. In the example above, the xml resource is referenced with +<code>android:resource="@xml/appwidget_info"</code>. That XML file would go in your application's +directory at <code>res/xml/appwidget_info.xml</code>. Here is a simple example. + +{@sample frameworks/base/tests/appwidgets/AppWidgetHostTest/res/xml/appwidget_info.xml AppWidgetProviderInfo} + +<p> +The attributes are as documented in the {@link android.appwidget.AppWidgetProviderInfo GagetInfo} class. (86400000 milliseconds means once per day) + + +<h3><a name="provider_AppWidgetProvider"></a>Using the {@link android.appwidget.AppWidgetProvider AppWidgetProvider} class</h3> + +<p>The AppWidgetProvider class is the easiest way to handle the widget provider intent broadcasts. +See the <code>src/com/example/android/apis/appwidget/ExampleAppWidgetProvider.java</code> +sample class in ApiDemos for an example. + +<p class="note">Keep in mind that since the the AppWidgetProvider is a BroadcastReceiver, +your process is not guaranteed to keep running after the callback methods return. See +<a href="../../../guide/topics/fundamentals.html#broadlife">Application Fundamentals > +Broadcast Receiver Lifecycle</a> for more information. + + + +<h3><a name="provider_configuration"></a>AppWidget Configuration UI</h3> + +<p> +Widget hosts have the ability to start a configuration activity when a widget is instantiated. +The activity should be declared as normal in AndroidManifest.xml, and it should be listed in +the AppWidgetProviderInfo XML file in the <code>android:configure</code> attribute. + +<p>The activity you specified will be launched with the {@link +android.appwidget.AppWidgetManager#ACTION_APPWIDGET_CONFIGURE} action. See the documentation for that +action for more info. + +<p>See the <code>src/com/example/android/apis/appwidget/ExampleAppWidgetConfigure.java</code> +sample class in ApiDemos for an example. + + + +<h3><a name="providers_broadcasts"></a>AppWidget Broadcast Intents</h3> + +<p>{@link android.appwidget.AppWidgetProvider} is just a convenience class. If you would like +to receive the widget broadcasts directly, you can. The four intents you need to care about are: +<ul> + <li>{@link android.appwidget.AppWidgetManager#ACTION_APPWIDGET_UPDATE}</li> + <li>{@link android.appwidget.AppWidgetManager#ACTION_APPWIDGET_DELETED}</li> + <li>{@link android.appwidget.AppWidgetManager#ACTION_APPWIDGET_ENABLED}</li> + <li>{@link android.appwidget.AppWidgetManager#ACTION_APPWIDGET_DISABLED}</li> +</ul> + +<p>By way of example, the implementation of +{@link android.appwidget.AppWidgetProvider#onReceive} is quite simple:</p> + +{@sample frameworks/base/core/java/android/appwidget/AppWidgetProvider.java onReceive} + + +<h2>AppWidget Hosts</h3> +<p>Widget hosts are the containers in which widgets can be placed. Most of the look and feel +details are left up to the widget hosts. For example, the home screen has one way of viewing +widgets, but the lock screen could also contain widgets, and it would have a different way of +adding, removing and otherwise managing widgets.</p> +<p>For more information on implementing your own widget host, see the +{@link android.appwidget.AppWidgetHost AppWidgetHost} class.</p> +</body> + diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index e0fe533..9a0dc9f 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -1250,12 +1250,12 @@ public abstract class Context { /** * Use with {@link #getSystemService} to retrieve a - * {@blink android.gadget.GadgetManager} for accessing wallpapers. + * {@blink android.appwidget.AppWidgetManager} for accessing AppWidgets. * * @hide * @see #getSystemService */ - public static final String GADGET_SERVICE = "gadget"; + public static final String APPWIDGET_SERVICE = "appwidget"; /** * Determine whether the given permission is allowed for a particular diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index 824fd9b..bb80e10 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -525,7 +525,6 @@ import java.util.Set; * <li> {@link #CATEGORY_INFO} * <li> {@link #CATEGORY_HOME} * <li> {@link #CATEGORY_PREFERENCE} - * <li> {@link #CATEGORY_GADGET} * <li> {@link #CATEGORY_TEST} * </ul> * @@ -1544,12 +1543,6 @@ public class Intent implements Parcelable { @SdkConstant(SdkConstantType.INTENT_CATEGORY) public static final String CATEGORY_TAB = "android.intent.category.TAB"; /** - * This activity can be embedded inside of another activity that is hosting - * gadgets. - */ - @SdkConstant(SdkConstantType.INTENT_CATEGORY) - public static final String CATEGORY_GADGET = "android.intent.category.GADGET"; - /** * Should be displayed in the top-level launcher. */ @SdkConstant(SdkConstantType.INTENT_CATEGORY) @@ -1579,9 +1572,6 @@ public class Intent implements Parcelable { public static final String CATEGORY_DEVELOPMENT_PREFERENCE = "android.intent.category.DEVELOPMENT_PREFERENCE"; /** * Capable of running inside a parent activity container. - * - * <p>Note: being removed in favor of more explicit categories such as - * CATEGORY_GADGET */ @SdkConstant(SdkConstantType.INTENT_CATEGORY) public static final String CATEGORY_EMBED = "android.intent.category.EMBED"; diff --git a/core/java/android/content/res/ColorStateList.java b/core/java/android/content/res/ColorStateList.java index 0f3f270..453a83d 100644 --- a/core/java/android/content/res/ColorStateList.java +++ b/core/java/android/content/res/ColorStateList.java @@ -304,7 +304,6 @@ public class ColorStateList implements Parcelable { for (int i=0; i<N; i++) { dest.writeIntArray(mStateSpecs[i]); } - dest.writeArray(mStateSpecs); dest.writeIntArray(mColors); } diff --git a/core/java/android/gadget/GadgetManager.java b/core/java/android/gadget/GadgetManager.java deleted file mode 100644 index d2c4055..0000000 --- a/core/java/android/gadget/GadgetManager.java +++ /dev/null @@ -1,320 +0,0 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.gadget; - -import android.content.ComponentName; -import android.content.Context; -import android.os.IBinder; -import android.os.RemoteException; -import android.os.ServiceManager; -import android.util.Log; -import android.widget.RemoteViews; - -import com.android.internal.gadget.IGadgetService; - -import java.lang.ref.WeakReference; -import java.util.List; -import java.util.WeakHashMap; - -/** - * Updates gadget state; gets information about installed gadget providers and other - * gadget related state. - */ -public class GadgetManager { - static final String TAG = "GadgetManager"; - - /** - * Send this from your gadget host activity when you want to pick a gadget to display. - * The gadget picker activity will be launched. - * <p> - * You must supply the following extras: - * <table> - * <tr> - * <td>{@link #EXTRA_GADGET_ID}</td> - * <td>A newly allocated gadgetId, which will be bound to the gadget provider - * once the user has selected one.</td> - * </tr> - * </table> - * - * <p> - * The system will respond with an onActivityResult call with the following extras in - * the intent: - * <table> - * <tr> - * <td>{@link #EXTRA_GADGET_ID}</td> - * <td>The gadgetId that you supplied in the original intent.</td> - * </tr> - * </table> - * <p> - * When you receive the result from the gadget pick activity, if the resultCode is - * {@link android.app.Activity#RESULT_OK}, a gadget has been selected. You should then - * check the GadgetProviderInfo for the returned gadget, and if it has one, launch its configuration - * activity. If {@link android.app.Activity#RESULT_CANCELED} is returned, you should delete - * the gadgetId. - * - * @see #ACTION_GADGET_CONFIGURE - */ - public static final String ACTION_GADGET_PICK = "android.gadget.action.GADGET_PICK"; - - /** - * Sent when it is time to configure your gadget while it is being added to a host. - * This action is not sent as a broadcast to the gadget provider, but as a startActivity - * to the activity specified in the {@link GadgetProviderInfo GadgetProviderInfo meta-data}. - * - * <p> - * The intent will contain the following extras: - * <table> - * <tr> - * <td>{@link #EXTRA_GADGET_ID}</td> - * <td>The gadgetId to configure.</td> - * </tr> - * </table> - * - * <p>If you return {@link android.app.Activity#RESULT_OK} using - * {@link android.app.Activity#setResult Activity.setResult()}, the gadget will be added, - * and you will receive an {@link #ACTION_GADGET_UPDATE} broadcast for this gadget. - * If you return {@link android.app.Activity#RESULT_CANCELED}, the host will cancel the add - * and not display this gadget, and you will receive a {@link #ACTION_GADGET_DELETED} broadcast. - */ - public static final String ACTION_GADGET_CONFIGURE = "android.gadget.action.GADGET_CONFIGURE"; - - /** - * An intent extra that contains one gadgetId. - * <p> - * The value will be an int that can be retrieved like this: - * {@sample frameworks/base/tests/gadgets/GadgetHostTest/src/com/android/tests/gadgethost/GadgetHostActivity.java getExtra_EXTRA_GADGET_ID} - */ - public static final String EXTRA_GADGET_ID = "gadgetId"; - - /** - * An intent extra that contains multiple gadgetIds. - * <p> - * The value will be an int array that can be retrieved like this: - * {@sample frameworks/base/tests/gadgets/GadgetHostTest/src/com/android/tests/gadgethost/TestGadgetProvider.java getExtra_EXTRA_GADGET_IDS} - */ - public static final String EXTRA_GADGET_IDS = "gadgetIds"; - - /** - * A sentiel value that the gadget manager will never return as a gadgetId. - */ - public static final int INVALID_GADGET_ID = 0; - - /** - * Sent when it is time to update your gadget. - * - * <p>This may be sent in response to a new instance for this gadget provider having - * been instantiated, the requested {@link GadgetProviderInfo#updatePeriodMillis update interval} - * having lapsed, or the system booting. - * - * <p> - * The intent will contain the following extras: - * <table> - * <tr> - * <td>{@link #EXTRA_GADGET_IDS}</td> - * <td>The gadgetIds to update. This may be all of the gadgets created for this - * provider, or just a subset. The system tries to send updates for as few gadget - * instances as possible.</td> - * </tr> - * </table> - * - * @see GadgetProvider#onUpdate GadgetProvider.onUpdate(Context context, GadgetManager gadgetManager, int[] gadgetIds) - */ - public static final String ACTION_GADGET_UPDATE = "android.gadget.action.GADGET_UPDATE"; - - /** - * Sent when an instance of a gadget is deleted from its host. - * - * @see GadgetProvider#onDeleted GadgetProvider.onDeleted(Context context, int[] gadgetIds) - */ - public static final String ACTION_GADGET_DELETED = "android.gadget.action.GADGET_DELETED"; - - /** - * Sent when an instance of a gadget is removed from the last host. - * - * @see GadgetProvider#onEnabled GadgetProvider.onEnabled(Context context) - */ - public static final String ACTION_GADGET_DISABLED = "android.gadget.action.GADGET_DISABLED"; - - /** - * Sent when an instance of a gadget is added to a host for the first time. - * This broadcast is sent at boot time if there is a gadget host installed with - * an instance for this provider. - * - * @see GadgetProvider#onEnabled GadgetProvider.onEnabled(Context context) - */ - public static final String ACTION_GADGET_ENABLED = "android.gadget.action.GADGET_ENABLED"; - - /** - * Field for the manifest meta-data tag. - * - * @see GadgetProviderInfo - */ - public static final String META_DATA_GADGET_PROVIDER = "android.gadget.provider"; - - static WeakHashMap<Context, WeakReference<GadgetManager>> sManagerCache = new WeakHashMap(); - static IGadgetService sService; - - Context mContext; - - /** - * Get the GadgetManager instance to use for the supplied {@link android.content.Context - * Context} object. - */ - public static GadgetManager getInstance(Context context) { - synchronized (sManagerCache) { - if (sService == null) { - IBinder b = ServiceManager.getService(Context.GADGET_SERVICE); - sService = IGadgetService.Stub.asInterface(b); - } - - WeakReference<GadgetManager> ref = sManagerCache.get(context); - GadgetManager result = null; - if (ref != null) { - result = ref.get(); - } - if (result == null) { - result = new GadgetManager(context); - sManagerCache.put(context, new WeakReference(result)); - } - return result; - } - } - - private GadgetManager(Context context) { - mContext = context; - } - - /** - * Set the RemoteViews to use for the specified gadgetIds. - * - * <p> - * It is okay to call this method both inside an {@link #ACTION_GADGET_UPDATE} broadcast, - * and outside of the handler. - * This method will only work when called from the uid that owns the gadget provider. - * - * @param gadgetIds The gadget instances for which to set the RemoteViews. - * @param views The RemoteViews object to show. - */ - public void updateGadget(int[] gadgetIds, RemoteViews views) { - try { - sService.updateGadgetIds(gadgetIds, views); - } - catch (RemoteException e) { - throw new RuntimeException("system server dead?", e); - } - } - - /** - * Set the RemoteViews to use for the specified gadgetId. - * - * <p> - * It is okay to call this method both inside an {@link #ACTION_GADGET_UPDATE} broadcast, - * and outside of the handler. - * This method will only work when called from the uid that owns the gadget provider. - * - * @param gadgetId The gadget instance for which to set the RemoteViews. - * @param views The RemoteViews object to show. - */ - public void updateGadget(int gadgetId, RemoteViews views) { - updateGadget(new int[] { gadgetId }, views); - } - - /** - * Set the RemoteViews to use for all gadget instances for the supplied gadget provider. - * - * <p> - * It is okay to call this method both inside an {@link #ACTION_GADGET_UPDATE} broadcast, - * and outside of the handler. - * This method will only work when called from the uid that owns the gadget provider. - * - * @param provider The {@link ComponentName} for the {@link - * android.content.BroadcastReceiver BroadcastReceiver} provider - * for your gadget. - * @param views The RemoteViews object to show. - */ - public void updateGadget(ComponentName provider, RemoteViews views) { - try { - sService.updateGadgetProvider(provider, views); - } - catch (RemoteException e) { - throw new RuntimeException("system server dead?", e); - } - } - - /** - * Return a list of the gadget providers that are currently installed. - */ - public List<GadgetProviderInfo> getInstalledProviders() { - try { - return sService.getInstalledProviders(); - } - catch (RemoteException e) { - throw new RuntimeException("system server dead?", e); - } - } - - /** - * Get the available info about the gadget. - * - * @return A gadgetId. If the gadgetId has not been bound to a provider yet, or - * you don't have access to that gadgetId, null is returned. - */ - public GadgetProviderInfo getGadgetInfo(int gadgetId) { - try { - return sService.getGadgetInfo(gadgetId); - } - catch (RemoteException e) { - throw new RuntimeException("system server dead?", e); - } - } - - /** - * Set the component for a given gadgetId. - * - * <p class="note">You need the GADGET_LIST permission. This method is to be used by the - * gadget picker. - * - * @param gadgetId The gadget instance for which to set the RemoteViews. - * @param provider The {@link android.content.BroadcastReceiver} that will be the gadget - * provider for this gadget. - */ - public void bindGadgetId(int gadgetId, ComponentName provider) { - try { - sService.bindGadgetId(gadgetId, provider); - } - catch (RemoteException e) { - throw new RuntimeException("system server dead?", e); - } - } - - /** - * Get the list of gadgetIds that have been bound to the given gadget - * provider. - * - * @param provider The {@link android.content.BroadcastReceiver} that is the - * gadget provider to find gadgetIds for. - */ - public int[] getGadgetIds(ComponentName provider) { - try { - return sService.getGadgetIds(provider); - } - catch (RemoteException e) { - throw new RuntimeException("system server dead?", e); - } - } -} - diff --git a/core/java/android/gadget/GadgetProvider.java b/core/java/android/gadget/GadgetProvider.java deleted file mode 100755 index 7e10e78..0000000 --- a/core/java/android/gadget/GadgetProvider.java +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.gadget; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; - -/** - * A conveience class to aid in implementing a gadget provider. - * Everything you can do with GadgetProvider, you can do with a regular {@link BroadcastReceiver}. - * GadgetProvider merely parses the relevant fields out of the Intent that is received in - * {@link #onReceive(Context,Intent) onReceive(Context,Intent)}, and calls hook methods - * with the received extras. - * - * <p>Extend this class and override one or more of the {@link #onUpdate}, {@link #onDeleted}, - * {@link #onEnabled} or {@link #onDisabled} methods to implement your own gadget functionality. - * - * <h3>Sample Code</h3> - * For an example of how to write a gadget provider, see the - * <a href="{@toroot}reference/android/gadget/package-descr.html#providers">android.gadget - * package overview</a>. - */ -public class GadgetProvider extends BroadcastReceiver { - /** - * Constructor to initialize GadgetProvider. - */ - public GadgetProvider() { - } - - /** - * Implements {@link BroadcastReceiver#onReceive} to dispatch calls to the various - * other methods on GadgetProvider. - * - * @param context The Context in which the receiver is running. - * @param intent The Intent being received. - */ - // BEGIN_INCLUDE(onReceive) - public void onReceive(Context context, Intent intent) { - // Protect against rogue update broadcasts (not really a security issue, - // just filter bad broacasts out so subclasses are less likely to crash). - String action = intent.getAction(); - if (GadgetManager.ACTION_GADGET_UPDATE.equals(action)) { - Bundle extras = intent.getExtras(); - if (extras != null) { - int[] gadgetIds = extras.getIntArray(GadgetManager.EXTRA_GADGET_IDS); - if (gadgetIds != null && gadgetIds.length > 0) { - this.onUpdate(context, GadgetManager.getInstance(context), gadgetIds); - } - } - } - else if (GadgetManager.ACTION_GADGET_DELETED.equals(action)) { - Bundle extras = intent.getExtras(); - if (extras != null) { - int[] gadgetIds = extras.getIntArray(GadgetManager.EXTRA_GADGET_IDS); - if (gadgetIds != null && gadgetIds.length > 0) { - this.onDeleted(context, gadgetIds); - } - } - } - else if (GadgetManager.ACTION_GADGET_ENABLED.equals(action)) { - this.onEnabled(context); - } - else if (GadgetManager.ACTION_GADGET_DISABLED.equals(action)) { - this.onDisabled(context); - } - } - // END_INCLUDE(onReceive) - - /** - * Called in response to the {@link GadgetManager#ACTION_GADGET_UPDATE} broadcast when - * this gadget provider is being asked to provide {@link android.widget.RemoteViews RemoteViews} - * for a set of gadgets. Override this method to implement your own gadget functionality. - * - * {@more} - * - * @param context The {@link android.content.Context Context} in which this receiver is - * running. - * @param gadgetManager A {@link GadgetManager} object you can call {@link - * GadgetManager#updateGadget} on. - * @param gadgetIds The gadgetsIds for which an update is needed. Note that this - * may be all of the gadget instances for this provider, or just - * a subset of them. - * - * @see GadgetManager#ACTION_GADGET_UPDATE - */ - public void onUpdate(Context context, GadgetManager gadgetManager, int[] gadgetIds) { - } - - /** - * Called in response to the {@link GadgetManager#ACTION_GADGET_DELETED} broadcast when - * one or more gadget instances have been deleted. Override this method to implement - * your own gadget functionality. - * - * {@more} - * - * @param context The {@link android.content.Context Context} in which this receiver is - * running. - * @param gadgetIds The gadgetsIds that have been deleted from their host. - * - * @see GadgetManager#ACTION_GADGET_DELETED - */ - public void onDeleted(Context context, int[] gadgetIds) { - } - - /** - * Called in response to the {@link GadgetManager#ACTION_GADGET_ENABLED} broadcast when - * the a gadget for this provider is instantiated. Override this method to implement your - * own gadget functionality. - * - * {@more} - * When the last gadget for this provider is deleted, - * {@link GadgetManager#ACTION_GADGET_DISABLED} is sent by the gadget manager, and - * {@link #onDisabled} is called. If after that, a gadget for this provider is created - * again, onEnabled() will be called again. - * - * @param context The {@link android.content.Context Context} in which this receiver is - * running. - * - * @see GadgetManager#ACTION_GADGET_ENABLED - */ - public void onEnabled(Context context) { - } - - /** - * Called in response to the {@link GadgetManager#ACTION_GADGET_DISABLED} broadcast, which - * is sent when the last gadget instance for this provider is deleted. Override this method - * to implement your own gadget functionality. - * - * {@more} - * - * @param context The {@link android.content.Context Context} in which this receiver is - * running. - * - * @see GadgetManager#ACTION_GADGET_DISABLED - */ - public void onDisabled(Context context) { - } -} diff --git a/core/java/android/gadget/package.html b/core/java/android/gadget/package.html deleted file mode 100644 index 4c04396..0000000 --- a/core/java/android/gadget/package.html +++ /dev/null @@ -1,136 +0,0 @@ -<body> -<p>Android allows applications to publish views to be embedded in other applications. These -views are called gadgets, and are published by "gadget providers." The component that can -contain gadgets is called a "gadget host." -</p> -<h3><a href="package-descr.html#providers">Gadget Providers</a></h3> -<ul> - <li><a href="package-descr.html#provider_manifest">Declaring a gadget in the AndroidManifest</a></li> - <li><a href="package-descr.html#provider_meta_data">Adding the GadgetProviderInfo meta-data</a></li> - <li><a href="package-descr.html#provider_GadgetProvider">Using the GadgetProvider class</a></li> - <li><a href="package-descr.html#provider_configuration">Gadget Configuration UI</a></li> - <li><a href="package-descr.html#provider_broadcasts">Gadget Broadcast Intents</a></li> -</ul> -<h3><a href="package-descr.html#">Gadget Hosts</a></h3> - - -{@more} - - -<h2><a name="providers"></a>Gadget Providers</h2> -<p> -Any application can publish gadgets. All an application needs to do to publish a gadget is -to have a {@link android.content.BroadcastReceiver} that receives the {@link -android.gadget.GadgetManager#ACTION_GADGET_UPDATE GadgetManager.ACTION_GADGET_UPDATE} intent, -and provide some meta-data about the gadget. Android provides the -{@link android.gadget.GadgetProvider} class, which extends BroadcastReceiver, as a convenience -class to aid in handling the broadcasts. - -<h3><a name="provider_manifest"></a>Declaring a gadget in the AndroidManifest</h3> - -<p> -First, declare the {@link android.content.BroadcastReceiver} in your application's -<code>AndroidManifest.xml</code> file. - -{@sample frameworks/base/tests/gadgets/GadgetHostTest/AndroidManifest.xml GadgetProvider} - -<p> -The <b><code><receiver></b> element has the following attributes: -<ul> - <li><b><code>android:name</code> -</b> which specifies the - {@link android.content.BroadcastReceiver} or {@link android.gadget.GadgetProvider} - class.</li> - <li><b><code>android:label</code> -</b> which specifies the string resource that - will be shown by the gadget picker as the label.</li> - <li><b><code>android:icon</code> -</b> which specifies the drawable resource that - will be shown by the gadget picker as the icon.</li> -</ul> - -<p> -The <b><code><intent-filter></b> element tells the {@link android.content.pm.PackageManager} -that this {@link android.content.BroadcastReceiver} receives the {@link -android.gadget.GadgetManager#ACTION_GADGET_UPDATE GadgetManager.ACTION_GADGET_UPDATE} broadcast. -The gadget manager will send other broadcasts directly to your gadget provider as required. -It is only necessary to explicitly declare that you accept the {@link -android.gadget.GadgetManager#ACTION_GADGET_UPDATE GadgetManager.ACTION_GADGET_UPDATE} broadcast. - -<p> -The <b><code><meta-data></code></b> element tells the gadget manager which xml resource to -read to find the {@link android.gadget.GadgetProviderInfo} for your gadget provider. It has the following -attributes: -<ul> - <li><b><code>android:name="android.gadget.provider"</code> -</b> identifies this meta-data - as the {@link android.gadget.GadgetProviderInfo} descriptor.</li> - <li><b><code>android:resource</code> -</b> is the xml resource to use as that descriptor.</li> -</ul> - - -<h3><a name="provider_meta_data"></a>Adding the {@link android.gadget.GadgetProviderInfo GadgetProviderInfo} meta-data</h3> - -<p> -For a gadget, the values in the {@link android.gadget.GadgetProviderInfo} structure are supplied -in an XML resource. In the example above, the xml resource is referenced with -<code>android:resource="@xml/gadget_info"</code>. That XML file would go in your application's -directory at <code>res/xml/gadget_info.xml</code>. Here is a simple example. - -{@sample frameworks/base/tests/gadgets/GadgetHostTest/res/xml/gadget_info.xml GadgetProviderInfo} - -<p> -The attributes are as documented in the {@link android.gadget.GadgetProviderInfo GagetInfo} class. (86400000 milliseconds means once per day) - - -<h3><a name="provider_GadgetProvider"></a>Using the {@link android.gadget.GadgetProvider GadgetProvider} class</h3> - -<p>The GadgetProvider class is the easiest way to handle the gadget provider intent broadcasts. -See the <code>src/com/example/android/apis/gadget/ExampleGadgetProvider.java</code> -sample class in ApiDemos for an example. - -<p class="note">Keep in mind that since the the GadgetProvider is a BroadcastReceiver, -your process is not guaranteed to keep running after the callback methods return. See -<a href="../../../guide/topics/fundamentals.html#broadlife">Application Fundamentals > -Broadcast Receiver Lifecycle</a> for more information. - - - -<h3><a name="provider_configuration"></a>Gadget Configuration UI</h3> - -<p> -Gadget hosts have the ability to start a configuration activity when a gadget is instantiated. -The activity should be declared as normal in AndroidManifest.xml, and it should be listed in -the GadgetProviderInfo XML file in the <code>android:configure</code> attribute. - -<p>The activity you specified will be launched with the {@link -android.gadget.GadgetManager#ACTION_GADGET_CONFIGURE} action. See the documentation for that -action for more info. - -<p>See the <code>src/com/example/android/apis/gadget/ExampleGadgetConfigure.java</code> -sample class in ApiDemos for an example. - - - -<h3><a name="providers_broadcasts"></a>Gadget Broadcast Intents</h3> - -<p>{@link android.gadget.GadgetProvider} is just a convenience class. If you would like -to receive the gadget broadcasts directly, you can. The four intents you need to care about are: -<ul> - <li>{@link android.gadget.GadgetManager#ACTION_GADGET_UPDATE}</li> - <li>{@link android.gadget.GadgetManager#ACTION_GADGET_DELETED}</li> - <li>{@link android.gadget.GadgetManager#ACTION_GADGET_ENABLED}</li> - <li>{@link android.gadget.GadgetManager#ACTION_GADGET_DISABLED}</li> -</ul> - -<p>By way of example, the implementation of -{@link android.gadget.GadgetProvider#onReceive} is quite simple:</p> - -{@sample frameworks/base/core/java/android/gadget/GadgetProvider.java onReceive} - - -<h2>Gadget Hosts</h3> -<p>Gadget hosts are the containers in which gadgets can be placed. Most of the look and feel -details are left up to the gadget hosts. For example, the home screen has one way of viewing -gadgets, but the lock screen could also contain gadgets, and it would have a different way of -adding, removing and otherwise managing gadgets.</p> -<p>For more information on implementing your own gadget host, see the -{@link android.gadget.GadgetHost GadgetHost} class.</p> -</body> - diff --git a/core/java/android/inputmethodservice/ExtractButton.java b/core/java/android/inputmethodservice/ExtractButton.java new file mode 100644 index 0000000..d6fe38d --- /dev/null +++ b/core/java/android/inputmethodservice/ExtractButton.java @@ -0,0 +1,30 @@ +package android.inputmethodservice; + +import android.content.Context; +import android.util.AttributeSet; +import android.widget.Button; + +/*** + * Specialization of {@link Button} that ignores the window not being focused. + */ +class ExtractButton extends Button { + public ExtractButton(Context context) { + super(context, null); + } + + public ExtractButton(Context context, AttributeSet attrs) { + super(context, attrs, com.android.internal.R.attr.buttonStyle); + } + + public ExtractButton(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + /** + * Pretend like the window this view is in always has focus, so it will + * highlight when selected. + */ + @Override public boolean hasWindowFocus() { + return this.isEnabled() ? true : false; + } +} diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java index 34d5695..32270c4 100644 --- a/core/java/android/inputmethodservice/InputMethodService.java +++ b/core/java/android/inputmethodservice/InputMethodService.java @@ -1398,10 +1398,17 @@ public class InputMethodService extends AbstractInputMethodService { int newSelStart, int newSelEnd, int candidatesStart, int candidatesEnd) { final ExtractEditText eet = mExtractEditText; - if (eet != null && mExtractedText != null) { + if (eet != null && isFullscreenMode() && mExtractedText != null) { final int off = mExtractedText.startOffset; eet.startInternalChanges(); - eet.setSelection(newSelStart-off, newSelEnd-off); + newSelStart -= off; + newSelEnd -= off; + final int len = eet.getText().length(); + if (newSelStart < 0) newSelStart = 0; + else if (newSelStart > len) newSelStart = len; + if (newSelEnd < 0) newSelEnd = 0; + else if (newSelEnd > len) newSelEnd = len; + eet.setSelection(newSelStart, newSelEnd); eet.finishInternalChanges(); } } diff --git a/core/java/android/provider/Contacts.java b/core/java/android/provider/Contacts.java index 3bffaec..d0bd2a5 100644 --- a/core/java/android/provider/Contacts.java +++ b/core/java/android/provider/Contacts.java @@ -1423,7 +1423,42 @@ public class Contacts { */ public static final String ATTACH_IMAGE = "com.android.contacts.action.ATTACH_IMAGE"; - + + /** + * Takes as input a data URI with a mailto: or tel: scheme. If a single + * contact exists with the given data it will be shown. If no contact + * exists, a dialog will ask the user if they want to create a new + * contact with the provided details filled in. If multiple contacts + * share the data the user will be prompted to pick which contact they + * want to view. + * <p> + * For <code>mailto:</code> URIs, the scheme specific portion must be a + * raw email address, such as one built using + * {@link Uri#fromParts(String, String, String)}. + * <p> + * For <code>tel:</code> URIs, the scheme specific portion is compared + * to existing numbers using the standard caller ID lookup algorithm. + * The number must be properly encoded, for example using + * {@link Uri#fromParts(String, String, String)}. + * <p> + * Any extras from the {@link Insert} class will be passed along to the + * create activity if there are no contacts to show. + * <p> + * Passing true for the {@link #EXTRA_FORCE_CREATE} extra will skip + * prompting the user when the contact doesn't exist. + */ + public static final String SHOW_OR_CREATE_CONTACT = + "com.android.contacts.action.SHOW_OR_CREATE_CONTACT"; + + /** + * Used with {@link #SHOW_OR_CREATE_CONTACT} to force creating a new contact if no matching + * contact found. Otherwise, default behavior is to prompt user with dialog before creating. + * + * <P>Type: BOOLEAN</P> + */ + public static final String EXTRA_FORCE_CREATE = + "com.android.contacts.action.FORCE_CREATE"; + /** * Intents related to the Contacts app UI. */ diff --git a/core/java/android/provider/Gmail.java b/core/java/android/provider/Gmail.java index 5b3c223..cc03968 100644 --- a/core/java/android/provider/Gmail.java +++ b/core/java/android/provider/Gmail.java @@ -1540,7 +1540,15 @@ public final class Gmail { /** Returns the number of unread conversation with a given label. */ public int getNumUnreadConversations(long labelId) { - return getLabelIdValues(labelId).getAsInteger(LabelColumns.NUM_UNREAD_CONVERSATIONS); + Integer unreadConversations = + getLabelIdValues(labelId).getAsInteger(LabelColumns.NUM_UNREAD_CONVERSATIONS); + // There seems to be a race condition here that can get the label maps into a bad + // state and lose state on a particular label. + if (unreadConversations == null) { + return 0; + } else { + return unreadConversations; + } } /** diff --git a/core/java/android/server/BluetoothA2dpService.java b/core/java/android/server/BluetoothA2dpService.java index f8bc765..3aa4078 100644 --- a/core/java/android/server/BluetoothA2dpService.java +++ b/core/java/android/server/BluetoothA2dpService.java @@ -208,6 +208,15 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub { if (mAudioDevices == null) { return BluetoothError.ERROR; } + // ignore if there are any active sinks + if (lookupSinksMatchingStates(new int[] { + BluetoothA2dp.STATE_CONNECTING, + BluetoothA2dp.STATE_CONNECTED, + BluetoothA2dp.STATE_PLAYING, + BluetoothA2dp.STATE_DISCONNECTING}).size() != 0) { + return BluetoothError.ERROR; + } + String path = lookupPath(address); if (path == null) { path = createHeadsetNative(address); diff --git a/core/java/android/server/BluetoothDeviceService.java b/core/java/android/server/BluetoothDeviceService.java index 6f5513a..e271909 100644 --- a/core/java/android/server/BluetoothDeviceService.java +++ b/core/java/android/server/BluetoothDeviceService.java @@ -287,6 +287,7 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { } else { intent = new Intent(BluetoothIntent.DISABLED_ACTION); } + intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); mContext.sendBroadcast(intent, BLUETOOTH_PERM); mEnableThread = null; diff --git a/core/java/android/server/BluetoothEventLoop.java b/core/java/android/server/BluetoothEventLoop.java index e4ebcca..8e77eed 100644 --- a/core/java/android/server/BluetoothEventLoop.java +++ b/core/java/android/server/BluetoothEventLoop.java @@ -52,6 +52,7 @@ class BluetoothEventLoop { private Context mContext; private static final int EVENT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY = 1; + private static final int EVENT_RESTART_BLUETOOTH = 2; // The time (in millisecs) to delay the pairing attempt after the first // auto pairing attempt fails. We use an exponential delay with @@ -74,6 +75,10 @@ class BluetoothEventLoop { return; } break; + case EVENT_RESTART_BLUETOOTH: + mBluetoothService.disable(); + mBluetoothService.enable(null); + break; } } }; @@ -372,6 +377,13 @@ class BluetoothEventLoop { } } + private void onRestartRequired() { + if (mBluetoothService.isEnabled()) { + Log.e(TAG, "*** A serious error occured (did hcid crash?) - restarting Bluetooth ***"); + mHandler.sendEmptyMessage(EVENT_RESTART_BLUETOOTH); + } + } + private static void log(String msg) { Log.d(TAG, msg); } diff --git a/core/java/android/text/method/QwertyKeyListener.java b/core/java/android/text/method/QwertyKeyListener.java index 3f8288c..21bc2a6 100644 --- a/core/java/android/text/method/QwertyKeyListener.java +++ b/core/java/android/text/method/QwertyKeyListener.java @@ -298,8 +298,10 @@ public class QwertyKeyListener extends BaseKeyListener { content.removeSpan(repl[0]); // only cancel the autocomplete if the cursor is at the end of - // the replaced span - if (selStart == en) { + // the replaced span (or after it, because the user is + // backspacing over the space after the word, not the word + // itself). + if (selStart >= en) { content.setSpan(TextKeyListener.INHIBIT_REPLACEMENT, en, en, Spannable.SPAN_POINT_POINT); content.replace(st, en, old); diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index d78320a..c3e00c4 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -1511,8 +1511,14 @@ public class View implements Drawable.Callback, KeyEvent.Callback { @ViewDebug.ExportedProperty int mUserPaddingBottom; - private int mOldWidthMeasureSpec = Integer.MIN_VALUE; - private int mOldHeightMeasureSpec = Integer.MIN_VALUE; + /** + * @hide + */ + int mOldWidthMeasureSpec = Integer.MIN_VALUE; + /** + * @hide + */ + int mOldHeightMeasureSpec = Integer.MIN_VALUE; private Resources mResources = null; @@ -2661,9 +2667,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback { * @attr ref android.R.styleable#View_visibility */ @ViewDebug.ExportedProperty(mapping = { - @ViewDebug.IntToString(from = 0, to = "VISIBLE"), - @ViewDebug.IntToString(from = 4, to = "INVISIBLE"), - @ViewDebug.IntToString(from = 8, to = "GONE") + @ViewDebug.IntToString(from = VISIBLE, to = "VISIBLE"), + @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"), + @ViewDebug.IntToString(from = GONE, to = "GONE") }) public int getVisibility() { return mViewFlags & VISIBILITY_MASK; @@ -3291,8 +3297,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback { * when ViewDebug.SYSTEM_PROPERTY_CAPTURE_VIEW) is set */ private static void captureViewInfo(String subTag, View v) { - if (v == null || - SystemProperties.getInt(ViewDebug.SYSTEM_PROPERTY_CAPTURE_VIEW, 0) == 0) { + if (v == null || SystemProperties.getInt(ViewDebug.SYSTEM_PROPERTY_CAPTURE_VIEW, 0) == 0) { return; } ViewDebug.dumpCapturedView(subTag, v); diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java index 883c7bd..0a043bd 100644 --- a/core/java/android/view/ViewDebug.java +++ b/core/java/android/view/ViewDebug.java @@ -17,9 +17,12 @@ package android.view; import android.util.Log; +import android.util.DisplayMetrics; import android.content.res.Resources; import android.graphics.Bitmap; +import android.graphics.Canvas; import android.os.Environment; +import android.os.Debug; import java.io.File; import java.io.BufferedWriter; @@ -43,6 +46,7 @@ import java.lang.annotation.RetentionPolicy; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.AccessibleObject; /** * Various debugging/tracing tools related to {@link View} and the view hierarchy. @@ -73,7 +77,7 @@ public class ViewDebug { * when it is set, we log key events, touch/motion and trackball events */ static final String SYSTEM_PROPERTY_CAPTURE_EVENT = "debug.captureevent"; - + /** * This annotation can be used to mark fields and methods to be dumped by * the view server. Only non-void methods with no arguments can be annotated @@ -113,6 +117,27 @@ public class ViewDebug { IntToString[] mapping() default { }; /** + * A mapping can be defined to map array indices to specific strings. + * A mapping can be used to see human readable values for the indices + * of an array: + * + * <pre> + * @ViewDebug.ExportedProperty(mapping = { + * @ViewDebug.IntToString(from = 0, to = "INVALID"), + * @ViewDebug.IntToString(from = 1, to = "FIRST"), + * @ViewDebug.IntToString(from = 2, to = "SECOND") + * }) + * private int[] mElements; + * <pre> + * + * @return An array of int to String mappings + * + * @see android.view.ViewDebug.IntToString + * @see #mapping() + */ + IntToString[] indexMapping() default { }; + + /** * When deep export is turned on, this property is not dumped. Instead, the * properties contained in this property are dumped. Each child property * is prefixed with the name of this property. @@ -187,10 +212,12 @@ public class ViewDebug { private static final String REMOTE_COMMAND_DUMP = "DUMP"; private static final String REMOTE_COMMAND_INVALIDATE = "INVALIDATE"; private static final String REMOTE_COMMAND_REQUEST_LAYOUT = "REQUEST_LAYOUT"; + private static final String REMOTE_PROFILE = "PROFILE"; private static HashMap<Class<?>, Field[]> sFieldsForClasses; private static HashMap<Class<?>, Method[]> sMethodsForClasses; - + private static HashMap<AccessibleObject, ExportedProperty> sAnnotations; + /** * Defines the type of hierarhcy trace to output to the hierarchy traces file. */ @@ -347,6 +374,7 @@ public class ViewDebug { } File recyclerDump = new File(Environment.getExternalStorageDirectory(), "view-recycler/"); + //noinspection ResultOfMethodCallIgnored recyclerDump.mkdirs(); recyclerDump = new File(recyclerDump, sRecyclerTracePrefix + ".recycler"); @@ -450,6 +478,7 @@ public class ViewDebug { } File hierarchyDump = new File(Environment.getExternalStorageDirectory(), "view-hierarchy/"); + //noinspection ResultOfMethodCallIgnored hierarchyDump.mkdirs(); hierarchyDump = new File(hierarchyDump, prefix + ".traces"); @@ -497,6 +526,7 @@ public class ViewDebug { sHierarchyTraces = null; File hierarchyDump = new File(Environment.getExternalStorageDirectory(), "view-hierarchy/"); + //noinspection ResultOfMethodCallIgnored hierarchyDump.mkdirs(); hierarchyDump = new File(hierarchyDump, sHierarchyTracePrefix + ".tree"); @@ -538,32 +568,41 @@ public class ViewDebug { invalidate(view, params[0]); } else if (REMOTE_COMMAND_REQUEST_LAYOUT.equalsIgnoreCase(command)) { requestLayout(view, params[0]); + } else if (REMOTE_PROFILE.equalsIgnoreCase(command)) { + profile(view, clientStream, params[0]); } } } - private static View findViewByHashCode(View root, String parameter) { - final String[] ids = parameter.split("@"); - final String className = ids[0]; - final int hashCode = Integer.parseInt(ids[1], 16); + private static View findView(View root, String parameter) { + // Look by type/hashcode + if (parameter.indexOf('@') != -1) { + final String[] ids = parameter.split("@"); + final String className = ids[0]; + final int hashCode = Integer.parseInt(ids[1], 16); - View view = root.getRootView(); - if (view instanceof ViewGroup) { - return findView((ViewGroup) view, className, hashCode); + View view = root.getRootView(); + if (view instanceof ViewGroup) { + return findView((ViewGroup) view, className, hashCode); + } + } else { + // Look by id + final int id = root.getResources().getIdentifier(parameter, null, null); + return root.getRootView().findViewById(id); } return null; } private static void invalidate(View root, String parameter) { - final View view = findViewByHashCode(root, parameter); + final View view = findView(root, parameter); if (view != null) { view.postInvalidate(); } } private static void requestLayout(View root, String parameter) { - final View view = findViewByHashCode(root, parameter); + final View view = findView(root, parameter); if (view != null) { root.post(new Runnable() { public void run() { @@ -573,19 +612,139 @@ public class ViewDebug { } } - private static void capture(View root, final OutputStream clientStream, String parameter) + private static void profile(View root, OutputStream clientStream, String parameter) throws IOException { + final View view = findView(root, parameter); + BufferedWriter out = null; + try { + out = new BufferedWriter(new OutputStreamWriter(clientStream), 32 * 1024); + + if (view != null) { + final long durationMeasure = profileViewOperation(view, new ViewOperation<Void>() { + public Void[] pre() { + forceLayout(view); + return null; + } + + private void forceLayout(View view) { + view.forceLayout(); + if (view instanceof ViewGroup) { + ViewGroup group = (ViewGroup) view; + final int count = group.getChildCount(); + for (int i = 0; i < count; i++) { + forceLayout(group.getChildAt(i)); + } + } + } + + public void run(Void... data) { + view.measure(view.mOldWidthMeasureSpec, view.mOldHeightMeasureSpec); + } + + public void post(Void... data) { + } + }); + + final long durationLayout = profileViewOperation(view, new ViewOperation<Void>() { + public Void[] pre() { + return null; + } + + public void run(Void... data) { + view.layout(view.mLeft, view.mTop, view.mRight, view.mBottom); + } + + public void post(Void... data) { + } + }); + + final long durationDraw = profileViewOperation(view, new ViewOperation<Object>() { + public Object[] pre() { + final DisplayMetrics metrics = view.getResources().getDisplayMetrics(); + final Bitmap bitmap = Bitmap.createBitmap(metrics.widthPixels, + metrics.heightPixels, Bitmap.Config.ARGB_8888); + final Canvas canvas = new Canvas(bitmap); + return new Object[] { bitmap, canvas }; + } + + public void run(Object... data) { + view.draw((Canvas) data[1]); + } + + public void post(Object... data) { + ((Bitmap) data[0]).recycle(); + } + }); + + out.write(String.valueOf(durationMeasure)); + out.write(' '); + out.write(String.valueOf(durationLayout)); + out.write(' '); + out.write(String.valueOf(durationDraw)); + out.newLine(); + } else { + out.write("-1 -1 -1"); + out.newLine(); + } + } catch (Exception e) { + android.util.Log.w("View", "Problem profiling the view:", e); + } finally { + if (out != null) { + out.close(); + } + } + } + + interface ViewOperation<T> { + T[] pre(); + void run(T... data); + void post(T... data); + } + + private static <T> long profileViewOperation(View view, final ViewOperation<T> operation) { final CountDownLatch latch = new CountDownLatch(1); - final View captureView = findViewByHashCode(root, parameter); + final long[] duration = new long[1]; + + view.post(new Runnable() { + public void run() { + try { + T[] data = operation.pre(); + long start = Debug.threadCpuTimeNanos(); + operation.run(data); + duration[0] = Debug.threadCpuTimeNanos() - start; + operation.post(data); + } finally { + latch.countDown(); + } + } + }); + + try { + latch.await(CAPTURE_TIMEOUT, TimeUnit.MILLISECONDS); + } catch (InterruptedException e) { + Log.w("View", "Could not complete the profiling of the view " + view); + Thread.currentThread().interrupt(); + return -1; + } + + return duration[0]; + } + + private static void capture(View root, final OutputStream clientStream, String parameter) + throws IOException { + + final View captureView = findView(root, parameter); if (captureView != null) { + final CountDownLatch latch = new CountDownLatch(1); final Bitmap[] cache = new Bitmap[1]; final boolean hasCache = captureView.isDrawingCacheEnabled(); final boolean willNotCache = captureView.willNotCacheDrawing(); if (willNotCache) { + // TODO: Should happen on the UI thread captureView.setWillNotCacheDrawing(false); } @@ -619,12 +778,15 @@ public class ViewDebug { } } } catch (InterruptedException e) { - Log.w("View", "Could not complete the capture of the view " + captureView); + Log.w("View", "Could not complete the capture of the view " + captureView); + Thread.currentThread().interrupt(); } finally { if (willNotCache) { + // TODO: Should happen on the UI thread captureView.setWillNotCacheDrawing(true); } if (!hasCache) { + // TODO: Should happen on the UI thread captureView.destroyDrawingCache(); } } @@ -642,6 +804,8 @@ public class ViewDebug { } out.write("DONE."); out.newLine(); + } catch (Exception e) { + android.util.Log.w("View", "Problem dumping the view:", e); } finally { if (out != null) { out.close(); @@ -713,7 +877,12 @@ public class ViewDebug { if (sFieldsForClasses == null) { sFieldsForClasses = new HashMap<Class<?>, Field[]>(); } + if (sAnnotations == null) { + sAnnotations = new HashMap<AccessibleObject, ExportedProperty>(512); + } + final HashMap<Class<?>, Field[]> map = sFieldsForClasses; + final HashMap<AccessibleObject, ExportedProperty> annotations = sAnnotations; Field[] fields = map.get(klass); if (fields != null) { @@ -729,6 +898,7 @@ public class ViewDebug { if (field.isAnnotationPresent(ExportedProperty.class)) { field.setAccessible(true); foundFields.add(field); + annotations.put(field, field.getAnnotation(ExportedProperty.class)); } } @@ -740,9 +910,14 @@ public class ViewDebug { private static Method[] getExportedPropertyMethods(Class<?> klass) { if (sMethodsForClasses == null) { - sMethodsForClasses = new HashMap<Class<?>, Method[]>(); + sMethodsForClasses = new HashMap<Class<?>, Method[]>(100); + } + if (sAnnotations == null) { + sAnnotations = new HashMap<AccessibleObject, ExportedProperty>(512); } + final HashMap<Class<?>, Method[]> map = sMethodsForClasses; + final HashMap<AccessibleObject, ExportedProperty> annotations = sAnnotations; Method[] methods = map.get(klass); if (methods != null) { @@ -756,10 +931,11 @@ public class ViewDebug { for (int i = 0; i < count; i++) { final Method method = methods[i]; if (method.getParameterTypes().length == 0 && - method.isAnnotationPresent(ExportedProperty.class) && - method.getReturnType() != Void.class) { + method.isAnnotationPresent(ExportedProperty.class) && + method.getReturnType() != Void.class) { method.setAccessible(true); foundMethods.add(method); + annotations.put(method, method.getAnnotation(ExportedProperty.class)); } } @@ -799,20 +975,10 @@ public class ViewDebug { final Class<?> returnType = method.getReturnType(); if (returnType == int.class) { - ExportedProperty property = method.getAnnotation(ExportedProperty.class); + final ExportedProperty property = sAnnotations.get(method); if (property.resolveId() && view instanceof View) { - final Resources resources = ((View) view).getContext().getResources(); final int id = (Integer) methodValue; - if (id >= 0) { - try { - methodValue = resources.getResourceTypeName(id) + '/' + - resources.getResourceEntryName(id); - } catch (Resources.NotFoundException e) { - methodValue = "UNKNOWN"; - } - } else { - methodValue = "NO_ID"; - } + methodValue = resolveId(view, id); } else { final IntToString[] mapping = property.mapping(); if (mapping.length > 0) { @@ -833,28 +999,22 @@ public class ViewDebug { } } } + } else if (returnType == int[].class) { + final ExportedProperty property = sAnnotations.get(method); + final int[] array = (int[]) methodValue; + final String valuePrefix = prefix + method.getName() + '_'; + final String suffix = "()"; + + exportUnrolledArray(view, out, property, array, valuePrefix, suffix); } else if (!returnType.isPrimitive()) { - ExportedProperty property = method.getAnnotation(ExportedProperty.class); + final ExportedProperty property = sAnnotations.get(method); if (property.deepExport()) { dumpViewProperties(methodValue, out, prefix + property.prefix()); continue; } } - out.write(prefix); - out.write(method.getName()); - out.write("()="); - - if (methodValue != null) { - final String value = methodValue.toString().replace("\n", "\\n"); - out.write(String.valueOf(value.length())); - out.write(","); - out.write(value); - } else { - out.write("4,null"); - } - - out.write(' '); + writeEntry(out, prefix, method.getName(), "()", methodValue); } catch (IllegalAccessException e) { } catch (InvocationTargetException e) { } @@ -875,20 +1035,10 @@ public class ViewDebug { final Class<?> type = field.getType(); if (type == int.class) { - ExportedProperty property = field.getAnnotation(ExportedProperty.class); + final ExportedProperty property = sAnnotations.get(field); if (property.resolveId() && view instanceof View) { - final Resources resources = ((View) view).getContext().getResources(); final int id = field.getInt(view); - if (id >= 0) { - try { - fieldValue = resources.getResourceTypeName(id) + '/' + - resources.getResourceEntryName(id); - } catch (Resources.NotFoundException e) { - fieldValue = "UNKNOWN"; - } - } else { - fieldValue = "NO_ID"; - } + fieldValue = resolveId(view, id); } else { final IntToString[] mapping = property.mapping(); if (mapping.length > 0) { @@ -907,8 +1057,18 @@ public class ViewDebug { } } } + } else if (type == int[].class) { + final ExportedProperty property = sAnnotations.get(field); + final int[] array = (int[]) field.get(view); + final String valuePrefix = prefix + field.getName() + '_'; + final String suffix = ""; + + exportUnrolledArray(view, out, property, array, valuePrefix, suffix); + + // We exit here! + return; } else if (!type.isPrimitive()) { - ExportedProperty property = field.getAnnotation(ExportedProperty.class); + final ExportedProperty property = sAnnotations.get(field); if (property.deepExport()) { dumpViewProperties(field.get(view), out, prefix + property.prefix()); continue; @@ -917,24 +1077,100 @@ public class ViewDebug { if (fieldValue == null) { fieldValue = field.get(view); - } + } - out.write(prefix); - out.write(field.getName()); - out.write('='); + writeEntry(out, prefix, field.getName(), "", fieldValue); + } catch (IllegalAccessException e) { + } + } + } - if (fieldValue != null) { - final String value = fieldValue.toString().replace("\n", "\\n"); - out.write(String.valueOf(value.length())); - out.write(","); - out.write(value); - } else { - out.write("4,null"); + private static void writeEntry(BufferedWriter out, String prefix, String name, + String suffix, Object value) throws IOException { + + out.write(prefix); + out.write(name); + out.write(suffix); + out.write("="); + writeValue(out, value); + out.write(' '); + } + + private static void exportUnrolledArray(Object view, BufferedWriter out, + ExportedProperty property, int[] array, String prefix, String suffix) + throws IOException { + + final IntToString[] indexMapping = property.indexMapping(); + final boolean hasIndexMapping = indexMapping.length > 0; + + final IntToString[] mapping = property.mapping(); + final boolean hasMapping = mapping.length > 0; + + final boolean resolveId = property.resolveId() && view instanceof View; + final int valuesCount = array.length; + + for (int j = 0; j < valuesCount; j++) { + String name; + String value; + + final int intValue = array[j]; + + name = String.valueOf(j); + if (hasIndexMapping) { + int mappingCount = indexMapping.length; + for (int k = 0; k < mappingCount; k++) { + final IntToString mapped = indexMapping[k]; + if (mapped.from() == j) { + name = mapped.to(); + break; + } } + } - out.write(' '); - } catch (IllegalAccessException e) { + value = String.valueOf(intValue); + if (hasMapping) { + int mappingCount = mapping.length; + for (int k = 0; k < mappingCount; k++) { + final IntToString mapped = mapping[k]; + if (mapped.from() == intValue) { + value = mapped.to(); + break; + } + } + } + + if (resolveId) { + value = (String) resolveId(view, intValue); } + + writeEntry(out, prefix, name, suffix, value); + } + } + + private static Object resolveId(Object view, int id) { + Object fieldValue; + final Resources resources = ((View) view).getContext().getResources(); + if (id >= 0) { + try { + fieldValue = resources.getResourceTypeName(id) + '/' + + resources.getResourceEntryName(id); + } catch (Resources.NotFoundException e) { + fieldValue = "id/0x" + Integer.toHexString(id); + } + } else { + fieldValue = "NO_ID"; + } + return fieldValue; + } + + private static void writeValue(BufferedWriter out, Object value) throws IOException { + if (value != null) { + String output = value.toString().replace("\n", "\\n"); + out.write(String.valueOf(output.length())); + out.write(","); + out.write(output); + } else { + out.write("4,null"); } } diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java index 0f15b17..220869c 100644 --- a/core/java/android/view/WindowManagerPolicy.java +++ b/core/java/android/view/WindowManagerPolicy.java @@ -54,7 +54,7 @@ import android.view.animation.Animation; * window manager is a very low-level system service, there are few other * system services you can call with this lock held. It is explicitly okay to * make calls into the package manager and power manager; it is explicitly not - * okay to make calls into the activity manager. Note that + * okay to make calls into the activity manager or most other services. Note that * {@link android.content.Context#checkPermission(String, int, int)} and * variations require calling into the activity manager. * <dt> Li <dd> Called with the input thread lock held. This lock can be @@ -748,7 +748,7 @@ public interface WindowManagerPolicy { * ActivityInfo.SCREEN_ORIENTATION_PORTRAIT}), return a surface * rotation. */ - public int rotationForOrientation(int orientation, int lastRotation, + public int rotationForOrientationLw(int orientation, int lastRotation, boolean displayEnabled); /** @@ -781,16 +781,16 @@ public interface WindowManagerPolicy { */ public boolean isCheekPressedAgainstScreen(MotionEvent ev); - public void setCurrentOrientation(int newOrientation); + public void setCurrentOrientationLw(int newOrientation); /** * Call from application to perform haptic feedback on its window. */ - public boolean performHapticFeedback(WindowState win, int effectId, boolean always); + public boolean performHapticFeedbackLw(WindowState win, int effectId, boolean always); /** * Called when we have stopped keeping the screen on because a window * requesting this is no longer visible. */ - public void screenOnStopped(); + public void screenOnStoppedLw(); } diff --git a/core/java/android/view/inputmethod/InputMethodInfo.java b/core/java/android/view/inputmethod/InputMethodInfo.java index 4e98591..b4c5b72 100644 --- a/core/java/android/view/inputmethod/InputMethodInfo.java +++ b/core/java/android/view/inputmethod/InputMethodInfo.java @@ -174,6 +174,14 @@ public final class InputMethodInfo implements Parcelable { } /** + * Return the raw information about the Service implementing this + * input method. Do not modify the returned object. + */ + public ServiceInfo getServiceInfo() { + return mService.serviceInfo; + } + + /** * Return the component of the service that implements this input * method. */ diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java index 7f2142e..4de9eef 100644 --- a/core/java/android/view/inputmethod/InputMethodManager.java +++ b/core/java/android/view/inputmethod/InputMethodManager.java @@ -921,6 +921,7 @@ public final class InputMethodManager { startInputInner(); } }); + return; } // Okay we are now ready to call into the served view and have it diff --git a/core/java/android/webkit/LoadListener.java b/core/java/android/webkit/LoadListener.java index 8d4b220..f9fb0b0 100644 --- a/core/java/android/webkit/LoadListener.java +++ b/core/java/android/webkit/LoadListener.java @@ -376,6 +376,11 @@ class LoadListener extends Handler implements EventHandler { } } } + + // if there is buffered data, commit them in the end + boolean needToCommit = mAuthHeader != null && !mustAuthenticate + && mNativeLoader != 0 && !mDataBuilder.isEmpty(); + // it is only here that we can reset the last mAuthHeader object // (if existed) and start a new one!!! mAuthHeader = null; @@ -410,6 +415,10 @@ class LoadListener extends Handler implements EventHandler { } } commitHeadersCheckRedirect(); + + if (needToCommit) { + commitLoad(); + } } /** diff --git a/core/java/android/webkit/TextDialog.java b/core/java/android/webkit/TextDialog.java index efc131f..9de97c9 100644 --- a/core/java/android/webkit/TextDialog.java +++ b/core/java/android/webkit/TextDialog.java @@ -540,7 +540,9 @@ import java.util.ArrayList; public void setSingleLine(boolean single) { int inputType = EditorInfo.TYPE_CLASS_TEXT; if (!single) { - inputType |= EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE; + inputType |= EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE + | EditorInfo.TYPE_TEXT_FLAG_CAP_SENTENCES + | EditorInfo.TYPE_TEXT_FLAG_AUTO_CORRECT; } mSingle = single; setHorizontallyScrolling(single); diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java index 4e2b2ab..65544d4 100644 --- a/core/java/android/webkit/WebSettings.java +++ b/core/java/android/webkit/WebSettings.java @@ -134,7 +134,7 @@ public class WebSettings { private int mDefaultFixedFontSize = 13; private boolean mLoadsImagesAutomatically = true; private boolean mBlockNetworkImage = false; - private boolean mBlockNetworkLoads = false; + private boolean mBlockNetworkLoads; private boolean mJavaScriptEnabled = false; private boolean mPluginsEnabled = false; private boolean mJavaScriptCanOpenWindowsAutomatically = false; @@ -248,7 +248,9 @@ public class WebSettings { mUserAgent = getCurrentUserAgent(); mUseDefaultUserAgent = true; - verifyNetworkAccess(); + mBlockNetworkLoads = mContext.checkPermission( + "android.permission.INTERNET", android.os.Process.myPid(), + android.os.Process.myUid()) != PackageManager.PERMISSION_GRANTED; } /** @@ -835,7 +837,7 @@ public class WebSettings { private void verifyNetworkAccess() { if (!mBlockNetworkLoads) { if (mContext.checkPermission("android.permission.INTERNET", - android.os.Process.myPid(), 0) != + android.os.Process.myPid(), android.os.Process.myUid()) != PackageManager.PERMISSION_GRANTED) { throw new SecurityException ("Permission denied - " + diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java index dc39b90..f61ce40 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -21,7 +21,6 @@ import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.DialogInterface.OnCancelListener; -import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; @@ -46,9 +45,6 @@ import android.util.AttributeSet; import android.util.Config; import android.util.EventLog; import android.util.Log; -import android.view.animation.AlphaAnimation; -import android.view.animation.Animation; -import android.view.animation.AnimationUtils; import android.view.Gravity; import android.view.KeyEvent; import android.view.LayoutInflater; @@ -68,12 +64,9 @@ import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.ImageView; import android.widget.ListView; -import android.widget.RelativeLayout; import android.widget.Scroller; import android.widget.Toast; import android.widget.ZoomButtonsController; -import android.widget.ZoomControls; -import android.widget.FrameLayout; import android.widget.AdapterView.OnItemClickListener; import java.io.File; @@ -113,57 +106,6 @@ public class WebView extends AbsoluteLayout static final boolean DEBUG = false; static final boolean LOGV_ENABLED = DEBUG ? Config.LOGD : Config.LOGV; - private class ExtendedZoomControls extends FrameLayout { - public ExtendedZoomControls(Context context, AttributeSet attrs) { - super(context, attrs); - LayoutInflater inflater = (LayoutInflater) - context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); - inflater.inflate(com.android.internal.R.layout.zoom_magnify, this, true); - mZoomControls = (ZoomControls) findViewById(com.android.internal.R.id.zoomControls); - mZoomMagnify = (ImageView) findViewById(com.android.internal.R.id.zoomMagnify); - } - - public void show(boolean showZoom, boolean canZoomOut) { - mZoomControls.setVisibility(showZoom ? View.VISIBLE : View.GONE); - mZoomMagnify.setVisibility(canZoomOut ? View.VISIBLE : View.GONE); - fade(View.VISIBLE, 0.0f, 1.0f); - } - - public void hide() { - fade(View.GONE, 1.0f, 0.0f); - } - - private void fade(int visibility, float startAlpha, float endAlpha) { - AlphaAnimation anim = new AlphaAnimation(startAlpha, endAlpha); - anim.setDuration(500); - startAnimation(anim); - setVisibility(visibility); - } - - public void setIsZoomMagnifyEnabled(boolean isEnabled) { - mZoomMagnify.setEnabled(isEnabled); - } - - public boolean hasFocus() { - return mZoomControls.hasFocus() || mZoomMagnify.hasFocus(); - } - - public void setOnZoomInClickListener(OnClickListener listener) { - mZoomControls.setOnZoomInClickListener(listener); - } - - public void setOnZoomOutClickListener(OnClickListener listener) { - mZoomControls.setOnZoomOutClickListener(listener); - } - - public void setOnZoomMagnifyClickListener(OnClickListener listener) { - mZoomMagnify.setOnClickListener(listener); - } - - ZoomControls mZoomControls; - ImageView mZoomMagnify; - } - /** * Transportation object for returning WebView across thread boundaries. */ @@ -281,8 +223,10 @@ public class WebView extends AbsoluteLayout */ // pre-computed square of ViewConfiguration.getScaledTouchSlop() private int mTouchSlopSquare; - // pre-computed square of ViewConfiguration.getScaledDoubleTapSlop() + // pre-computed square of the density adjusted double tap slop private int mDoubleTapSlopSquare; + // pre-computed density adjusted navigation slop + private int mNavSlop; // This should be ViewConfiguration.getTapTimeout() // But system time out is 100ms, which is too short for the browser. // In the browser, if it switches out of tap too soon, jump tap won't work. @@ -295,9 +239,6 @@ public class WebView extends AbsoluteLayout private static final int LONG_PRESS_TIMEOUT = 1000; // needed to avoid flinging after a pause of no movement private static final int MIN_FLING_TIME = 250; - // The time that the Zoom Controls are visible before fading away - private static final long ZOOM_CONTROLS_TIMEOUT = - ViewConfiguration.getZoomControlsTimeout(); // The amount of content to overlap between two screens when going through // pages with the space bar, in pixels. private static final int PAGE_SCROLL_OVERLAP = 24; @@ -337,10 +278,6 @@ public class WebView extends AbsoluteLayout private boolean mWrapContent; - // The View containing the zoom controls - private ExtendedZoomControls mZoomControls; - private Runnable mZoomControlRunnable; - // true if we should call webcore to draw the content, false means we have // requested something but it isn't ready to draw yet. private WebViewCore.FocusData mFocusData; @@ -550,6 +487,7 @@ public class WebView extends AbsoluteLayout private ZoomButtonsController mZoomButtonsController; private ImageView mZoomOverviewButton; + private ImageView mZoomFitPageButton; // These keep track of the center point of the zoom. They are used to // determine the point around which we should zoom. @@ -564,28 +502,13 @@ public class WebView extends AbsoluteLayout // in this callback } - public void onOverview() { - mZoomButtonsController.setVisible(false); - zoomScrollOut(); - if (mLogEvent) { - Checkin.updateStats(mContext.getContentResolver(), - Checkin.Stats.Tag.BROWSER_ZOOM_OVERVIEW, 1, 0.0); - } - } - public void onVisibilityChanged(boolean visible) { if (visible) { switchOutDrawHistory(); - mZoomButtonsController.setOverviewVisible(true); - updateButtonsEnabled(); + updateZoomButtonsEnabled(); } } - private void updateButtonsEnabled() { - mZoomButtonsController.setZoomInEnabled(mActualScale < mMaxZoomScale); - mZoomButtonsController.setZoomOutEnabled(mActualScale > mMinZoomScale); - } - public void onZoom(boolean zoomIn) { if (zoomIn) { zoomIn(); @@ -593,7 +516,7 @@ public class WebView extends AbsoluteLayout zoomOut(); } - updateButtonsEnabled(); + updateZoomButtonsEnabled(); } }; @@ -633,8 +556,49 @@ public class WebView extends AbsoluteLayout mFocusData.mX = 0; mFocusData.mY = 0; mScroller = new Scroller(context); + + initZoomController(context); + } + + private void initZoomController(Context context) { + // Create the buttons controller mZoomButtonsController = new ZoomButtonsController(context, this); mZoomButtonsController.setCallback(mZoomListener); + + // Create the accessory buttons + LayoutInflater inflater = + (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + ViewGroup container = mZoomButtonsController.getContainer(); + inflater.inflate(com.android.internal.R.layout.zoom_browser_accessory_buttons, container); + mZoomOverviewButton = + (ImageView) container.findViewById(com.android.internal.R.id.zoom_page_overview); + mZoomOverviewButton.setOnClickListener( + new View.OnClickListener() { + public void onClick(View v) { + mZoomButtonsController.setVisible(false); + zoomScrollOut(); + if (mLogEvent) { + Checkin.updateStats(mContext.getContentResolver(), + Checkin.Stats.Tag.BROWSER_ZOOM_OVERVIEW, 1, 0.0); + } + } + }); + mZoomFitPageButton = + (ImageView) container.findViewById(com.android.internal.R.id.zoom_fit_page); + mZoomFitPageButton.setOnClickListener( + new View.OnClickListener() { + public void onClick(View v) { + zoomWithPreview(1f); + updateZoomButtonsEnabled(); + } + }); + } + + private void updateZoomButtonsEnabled() { + mZoomButtonsController.setZoomInEnabled(mActualScale < mMaxZoomScale); + mZoomButtonsController.setZoomOutEnabled(mActualScale > mMinZoomScale); + mZoomFitPageButton.setEnabled(mActualScale != 1); + mZoomOverviewButton.setEnabled(canZoomScrollOut()); } private void init() { @@ -647,9 +611,16 @@ public class WebView extends AbsoluteLayout final int slop = ViewConfiguration.get(getContext()).getScaledTouchSlop(); mTouchSlopSquare = slop * slop; mMinLockSnapReverseDistance = slop; - final int doubleTapslop = ViewConfiguration.get(getContext()) - .getScaledDoubleTapSlop(); + // use twice the line height, 32 based on our current default font, for + // the double tap slop as the ViewConfiguration's double tap slop, 100, + // is too big for the Browser + final int doubleTapslop = (int) (32 * getContext().getResources() + .getDisplayMetrics().density); mDoubleTapSlopSquare = doubleTapslop * doubleTapslop; + // use one line height, 16 based on our current default font, for how + // far we allow a touch be away from the edge of a link + mNavSlop = (int) (16 * getContext().getResources() + .getDisplayMetrics().density); } /* package */ boolean onSavePassword(String schemePlusHost, String username, @@ -1380,13 +1351,7 @@ public class WebView extends AbsoluteLayout return; } clearTextEntry(); - ExtendedZoomControls zoomControls = (ExtendedZoomControls) - getZoomControls(); - zoomControls.show(true, canZoomScrollOut()); - zoomControls.requestFocus(); - mPrivateHandler.removeCallbacks(mZoomControlRunnable); - mPrivateHandler.postDelayed(mZoomControlRunnable, - ZOOM_CONTROLS_TIMEOUT); + mZoomButtonsController.setVisible(true); } /** @@ -1498,7 +1463,8 @@ public class WebView extends AbsoluteLayout private static int pinLoc(int x, int viewMax, int docMax) { // Log.d(LOGTAG, "-- pinLoc " + x + " " + viewMax + " " + docMax); if (docMax < viewMax) { // the doc has room on the sides for "blank" - x = -(viewMax - docMax) >> 1; + // pin the short document to the top/left of the screen + x = 0; // Log.d(LOGTAG, "--- center " + x); } else if (x < 0) { x = 0; @@ -2589,11 +2555,8 @@ public class WebView extends AbsoluteLayout private void startZoomScrollOut() { setHorizontalScrollBarEnabled(false); setVerticalScrollBarEnabled(false); - if (mZoomControlRunnable != null) { - mPrivateHandler.removeCallbacks(mZoomControlRunnable); - } - if (mZoomControls != null) { - mZoomControls.hide(); + if (mZoomButtonsController.isVisible()) { + mZoomButtonsController.setVisible(false); } int width = getViewWidth(); int height = getViewHeight(); @@ -3263,6 +3226,7 @@ public class WebView extends AbsoluteLayout // Clean up the zoom controller mZoomButtonsController.setVisible(false); + ZoomButtonsController.finishZoomTutorial(mContext, false); } // Implementation for OnHierarchyChangeListener @@ -3518,22 +3482,29 @@ public class WebView extends AbsoluteLayout nativeMoveSelection(viewToContent(mSelectX) , viewToContent(mSelectY), false); mTouchSelection = mExtendSelection = true; - } else if (!ZoomButtonsController.useOldZoom(mContext) && - mPrivateHandler.hasMessages(RELEASE_SINGLE_TAP) && - (deltaX * deltaX + deltaY * deltaY < mDoubleTapSlopSquare)) { - // Found doubletap, invoke the zoom controller + } else if (!ZoomButtonsController.useOldZoom(mContext) + && mPrivateHandler.hasMessages(RELEASE_SINGLE_TAP)) { mPrivateHandler.removeMessages(RELEASE_SINGLE_TAP); - int contentX = viewToContent((int) mLastTouchX + mScrollX); - int contentY = viewToContent((int) mLastTouchY + mScrollY); - if (inEditingMode()) { - mTextEntry.updateCachedTextfield(); - } - nativeClearFocus(contentX, contentY); - if (mLogEvent) { - EventLog.writeEvent(EVENT_LOG_DOUBLE_TAP_DURATION, - (eventTime - mLastTouchUpTime), eventTime); + if (deltaX * deltaX + deltaY * deltaY < mDoubleTapSlopSquare) { + // Found doubletap, invoke the zoom controller + int contentX = viewToContent((int) mLastTouchX + + mScrollX); + int contentY = viewToContent((int) mLastTouchY + + mScrollY); + if (inEditingMode()) { + mTextEntry.updateCachedTextfield(); + } + nativeClearFocus(contentX, contentY); + if (mLogEvent) { + EventLog.writeEvent(EVENT_LOG_DOUBLE_TAP_DURATION, + (eventTime - mLastTouchUpTime), eventTime); + } + return mZoomButtonsController.handleDoubleTapEvent(ev); + } else { + // commit the short press action + doShortPress(); + // continue, mTouchMode should be still TOUCH_INIT_MODE } - return mZoomButtonsController.handleDoubleTapEvent(ev); } else { mTouchMode = TOUCH_INIT_MODE; mPreventDrag = mForwardTouchEvents; @@ -3678,20 +3649,6 @@ public class WebView extends AbsoluteLayout mLastTouchTime = eventTime; mUserScroll = true; } - - if (ZoomButtonsController.useOldZoom(mContext)) { - boolean showPlusMinus = mMinZoomScale < mMaxZoomScale; - boolean showMagnify = canZoomScrollOut(); - if (mZoomControls != null && (showPlusMinus || showMagnify)) { - if (mZoomControls.getVisibility() == View.VISIBLE) { - mPrivateHandler.removeCallbacks(mZoomControlRunnable); - } else { - mZoomControls.show(showPlusMinus, showMagnify); - } - mPrivateHandler.postDelayed(mZoomControlRunnable, - ZOOM_CONTROLS_TIMEOUT); - } - } if (done) { // return false to indicate that we can't pan out of the // view space @@ -3706,8 +3663,7 @@ public class WebView extends AbsoluteLayout mPrivateHandler.removeMessages(SWITCH_TO_SHORTPRESS); if (getSettings().supportZoom()) { mPrivateHandler.sendMessageDelayed(mPrivateHandler - .obtainMessage(RELEASE_SINGLE_TAP, - new Boolean(true)), + .obtainMessage(RELEASE_SINGLE_TAP), DOUBLE_TAP_TIMEOUT); } else { // do short press now @@ -3755,8 +3711,7 @@ public class WebView extends AbsoluteLayout // as tap instead of short press. mTouchMode = TOUCH_INIT_MODE; mPrivateHandler.sendMessageDelayed(mPrivateHandler - .obtainMessage(RELEASE_SINGLE_TAP, - new Boolean(true)), + .obtainMessage(RELEASE_SINGLE_TAP), DOUBLE_TAP_TIMEOUT); } else { mTouchMode = TOUCH_DONE_MODE; @@ -4178,42 +4133,41 @@ public class WebView extends AbsoluteLayout } /** + * An InvisibleView is an invisible, zero-sized View for backwards + * compatibility + */ + private final class InvisibleView extends View { + + private InvisibleView(Context context) { + super(context); + setVisibility(GONE); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + setMeasuredDimension(0, 0); + } + + @Override + public void draw(Canvas canvas) { + } + + @Override + protected void dispatchDraw(Canvas canvas) { + } + } + + /** * Returns a view containing zoom controls i.e. +/- buttons. The caller is * in charge of installing this view to the view hierarchy. This view will * become visible when the user starts scrolling via touch and fade away if * the user does not interact with it. + * <p/> + * From 1.5, WebView change to use ZoomButtonsController. This will return + * an invisible dummy view for backwards compatibility. */ public View getZoomControls() { - if (!getSettings().supportZoom()) { - Log.w(LOGTAG, "This WebView doesn't support zoom."); - return null; - } - if (mZoomControls == null) { - mZoomControls = createZoomControls(); - - /* - * need to be set to VISIBLE first so that getMeasuredHeight() in - * {@link #onSizeChanged()} can return the measured value for proper - * layout. - */ - mZoomControls.setVisibility(View.VISIBLE); - mZoomControlRunnable = new Runnable() { - public void run() { - - /* Don't dismiss the controls if the user has - * focus on them. Wait and check again later. - */ - if (!mZoomControls.hasFocus()) { - mZoomControls.hide(); - } else { - mPrivateHandler.removeCallbacks(mZoomControlRunnable); - mPrivateHandler.postDelayed(mZoomControlRunnable, - ZOOM_CONTROLS_TIMEOUT); - } - } - }; - } - return mZoomControls; + return new InvisibleView(mContext); } /** @@ -4236,46 +4190,6 @@ public class WebView extends AbsoluteLayout return zoomWithPreview(mActualScale * 0.8f); } - private ExtendedZoomControls createZoomControls() { - ExtendedZoomControls zoomControls = new ExtendedZoomControls(mContext - , null); - zoomControls.setOnZoomInClickListener(new OnClickListener() { - public void onClick(View v) { - // reset time out - mPrivateHandler.removeCallbacks(mZoomControlRunnable); - mPrivateHandler.postDelayed(mZoomControlRunnable, - ZOOM_CONTROLS_TIMEOUT); - zoomIn(); - } - }); - zoomControls.setOnZoomOutClickListener(new OnClickListener() { - public void onClick(View v) { - // reset time out - mPrivateHandler.removeCallbacks(mZoomControlRunnable); - mPrivateHandler.postDelayed(mZoomControlRunnable, - ZOOM_CONTROLS_TIMEOUT); - zoomOut(); - } - }); - zoomControls.setOnZoomMagnifyClickListener(new OnClickListener() { - public void onClick(View v) { - mPrivateHandler.removeCallbacks(mZoomControlRunnable); - mPrivateHandler.postDelayed(mZoomControlRunnable, - ZOOM_CONTROLS_TIMEOUT); - zoomScrollOut(); - } - }); - return zoomControls; - } - - // This used to be the value returned by ViewConfiguration.getTouchSlop(). - // We pass this to the navigation cache to find where the user clicked. - // TouchSlop has been increased for other purposes, but for the - // navigation cache it is too big, and may result in clicking the wrong - // spot. This is a concern when the cache is out of date, and clicking - // finds a node which is wrong but nearby. - private static final int NAV_SLOP = 12; - private void updateSelection() { if (mNativeClass == 0) { return; @@ -4283,9 +4197,8 @@ public class WebView extends AbsoluteLayout // mLastTouchX and mLastTouchY are the point in the current viewport int contentX = viewToContent((int) mLastTouchX + mScrollX); int contentY = viewToContent((int) mLastTouchY + mScrollY); - int contentSize = NAV_SLOP; - Rect rect = new Rect(contentX - contentSize, contentY - contentSize, - contentX + contentSize, contentY + contentSize); + Rect rect = new Rect(contentX - mNavSlop, contentY - mNavSlop, + contentX + mNavSlop, contentY + mNavSlop); // If we were already focused on a textfield, update its cache. if (inEditingMode()) { mTextEntry.updateCachedTextfield(); @@ -4298,8 +4211,7 @@ public class WebView extends AbsoluteLayout View v = mTextEntry; int x = viewToContent((v.getLeft() + v.getRight()) >> 1); int y = viewToContent((v.getTop() + v.getBottom()) >> 1); - int contentSize = NAV_SLOP; - nativeMotionUp(x, y, contentSize, true); + nativeMotionUp(x, y, mNavSlop, true); } } @@ -4311,8 +4223,7 @@ public class WebView extends AbsoluteLayout // mLastTouchX and mLastTouchY are the point in the current viewport int contentX = viewToContent((int) mLastTouchX + mScrollX); int contentY = viewToContent((int) mLastTouchY + mScrollY); - int contentSize = NAV_SLOP; - if (nativeMotionUp(contentX, contentY, contentSize, true)) { + if (nativeMotionUp(contentX, contentY, mNavSlop, true)) { if (mLogEvent) { Checkin.updateStats(mContext.getContentResolver(), Checkin.Stats.Tag.BROWSER_SNAP_CENTER, 1, 0.0); @@ -4538,9 +4449,7 @@ public class WebView extends AbsoluteLayout } case RELEASE_SINGLE_TAP: { mTouchMode = TOUCH_DONE_MODE; - if ((Boolean)msg.obj) { - doShortPress(); - } + doShortPress(); break; } case SWITCH_TO_ENTER: diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java index 6ab088d..e10ffa1 100644 --- a/core/java/android/webkit/WebViewCore.java +++ b/core/java/android/webkit/WebViewCore.java @@ -271,11 +271,6 @@ final class WebViewCore { static native String nativeFindAddress(String addr); /** - * Rebuild the nav cache if the dom changed. - */ - private native void nativeCheckNavCache(); - - /** * Empty the picture set. */ private native void nativeClearContent(); @@ -1298,7 +1293,6 @@ final class WebViewCore { mViewportMinimumScale == 0 ? nativeGetContentMinPrefWidth() : 0, 0, draw).sendToTarget(); - nativeCheckNavCache(); if (mWebkitScrollX != 0 || mWebkitScrollY != 0) { // as we have the new picture, try to sync the scroll position Message.obtain(mWebView.mPrivateHandler, diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java index f517dc9..7fc96fc 100644 --- a/core/java/android/widget/AbsListView.java +++ b/core/java/android/widget/AbsListView.java @@ -41,10 +41,8 @@ import android.view.ViewConfiguration; import android.view.ViewDebug; import android.view.ViewGroup; import android.view.ViewTreeObserver; -import android.view.inputmethod.CompletionInfo; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputConnection; -import android.view.inputmethod.InputConnectionWrapper; import android.view.inputmethod.InputMethodManager; import android.view.ContextMenu.ContextMenuInfo; @@ -2917,11 +2915,14 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te */ @Override public InputConnection onCreateInputConnection(EditorInfo outAttrs) { - // XXX we need to have the text filter created, so we can get an - // InputConnection to proxy to. Unfortunately this means we pretty - // much need to make it as soon as a list view gets focus. - createTextFilter(false); - return mTextFilter.onCreateInputConnection(outAttrs); + if (isTextFilterEnabled()) { + // XXX we need to have the text filter created, so we can get an + // InputConnection to proxy to. Unfortunately this means we pretty + // much need to make it as soon as a list view gets focus. + createTextFilter(false); + return mTextFilter.onCreateInputConnection(outAttrs); + } + return null; } /** @@ -3015,7 +3016,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te * filtering as the text changes. */ public void onTextChanged(CharSequence s, int start, int before, int count) { - if (mPopup != null) { + if (mPopup != null && isTextFilterEnabled()) { int length = s.length(); boolean showing = mPopup.isShowing(); if (!showing && length > 0) { diff --git a/core/java/android/widget/ArrayAdapter.java b/core/java/android/widget/ArrayAdapter.java index c65a3ce..c28210d 100644 --- a/core/java/android/widget/ArrayAdapter.java +++ b/core/java/android/widget/ArrayAdapter.java @@ -25,6 +25,8 @@ import android.view.ViewGroup; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Comparator; +import java.util.Collections; /** * A ListAdapter that manages a ListView backed by an array of arbitrary @@ -227,6 +229,17 @@ public class ArrayAdapter<T> extends BaseAdapter implements Filterable { } /** + * Sorts the content of this adapter using the specified comparator. + * + * @param comparator The comparator used to sort the objects contained + * in this adapter. + */ + public void sort(Comparator<? super T> comparator) { + Collections.sort(mObjects, comparator); + if (mNotifyOnChange) notifyDataSetChanged(); + } + + /** * {@inheritDoc} */ @Override diff --git a/core/java/android/widget/AutoCompleteTextView.java b/core/java/android/widget/AutoCompleteTextView.java index 0c1c72a..7b9670b 100644 --- a/core/java/android/widget/AutoCompleteTextView.java +++ b/core/java/android/widget/AutoCompleteTextView.java @@ -461,14 +461,6 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe // by ensuring it has focus and getting its window out // of touch mode. mDropDownList.requestFocusFromTouch(); - if (false) { - // Update whether the pop-up is in front of or behind - // the input method, depending on whether the user has - // moved down in it. - mPopup.setInputMethodMode(curIndex > 0 - ? PopupWindow.INPUT_METHOD_NOT_NEEDED - : PopupWindow.INPUT_METHOD_NEEDED); - } mPopup.update(); switch (keyCode) { @@ -504,6 +496,10 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe boolean handled = super.onKeyDown(keyCode, event); mLastKeyCode = KeyEvent.KEYCODE_UNKNOWN; + if (handled && isPopupShowing() && mDropDownList != null) { + clearListSelection(); + } + return handled; } @@ -833,7 +829,6 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe mPopup.update(getDropDownAnchorView(), mDropDownHorizontalOffset, mDropDownVerticalOffset, widthSpec, height); } else { - int widthSpec; if (mDropDownWidth == ViewGroup.LayoutParams.FILL_PARENT) { mPopup.setWindowLayoutMode(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); @@ -1119,6 +1114,7 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe protected int[] onCreateDrawableState(int extraSpace) { int[] res = super.onCreateDrawableState(extraSpace); + //noinspection ConstantIfStatement if (false) { StringBuilder sb = new StringBuilder("Created drawable state: ["); for (int i=0; i<res.length; i++) { diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java index c2f3a85..aced533 100644 --- a/core/java/android/widget/ListView.java +++ b/core/java/android/widget/ListView.java @@ -126,7 +126,7 @@ public class ListView extends AbsListView { private SparseBooleanArray mCheckStates; // used for temporary calculations. - private Rect mTempRect = new Rect(); + private final Rect mTempRect = new Rect(); // the single allocated result per list view; kinda cheesey but avoids // allocating these thingies too often. @@ -1656,7 +1656,8 @@ public class ListView extends AbsListView { } p.viewType = mAdapter.getItemViewType(position); - if (recycled || (p.recycledHeaderFooter && p.viewType == AdapterView.ITEM_VIEW_TYPE_HEADER_OR_FOOTER)) { + if (recycled || (p.recycledHeaderFooter && + p.viewType == AdapterView.ITEM_VIEW_TYPE_HEADER_OR_FOOTER)) { attachViewToParent(child, flowDown ? -1 : 0, p); } else { if (p.viewType == AdapterView.ITEM_VIEW_TYPE_HEADER_OR_FOOTER) { @@ -2643,6 +2644,7 @@ public class ListView extends AbsListView { final int listBottom = getHeight() - mListPadding.bottom; final int listTop = mListPadding.top; + final AbsListView.RecycleBin recycleBin = mRecycler; if (amount < 0) { // shifted items up @@ -2670,8 +2672,13 @@ public class ListView extends AbsListView { // top views may be panned off screen View first = getChildAt(0); while (first.getBottom() < listTop) { - removeViewInLayout(first); - mRecycler.addScrapView(first); + AbsListView.LayoutParams layoutParams = (LayoutParams) first.getLayoutParams(); + if (recycleBin.shouldRecycleViewType(layoutParams.viewType)) { + removeViewInLayout(first); + recycleBin.addScrapView(first); + } else { + detachViewFromParent(first); + } first = getChildAt(0); mFirstPosition++; } @@ -2696,8 +2703,13 @@ public class ListView extends AbsListView { // bottom view may be panned off screen while (last.getTop() > listBottom) { - removeViewInLayout(last); - mRecycler.addScrapView(last); + AbsListView.LayoutParams layoutParams = (LayoutParams) last.getLayoutParams(); + if (recycleBin.shouldRecycleViewType(layoutParams.viewType)) { + removeViewInLayout(last); + recycleBin.addScrapView(last); + } else { + detachViewFromParent(last); + } last = getChildAt(--lastIndex); } } diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java index 53db77e..a4f729f 100644 --- a/core/java/android/widget/PopupWindow.java +++ b/core/java/android/widget/PopupWindow.java @@ -837,7 +837,7 @@ public class PopupWindow { if (!mTouchable) { curFlags |= WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; } - if (mTouchable) { + if (mOutsideTouchable) { curFlags |= WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH; } if (!mClippingEnabled) { diff --git a/core/java/android/widget/RelativeLayout.java b/core/java/android/widget/RelativeLayout.java index ba63ec3..52c421c 100644 --- a/core/java/android/widget/RelativeLayout.java +++ b/core/java/android/widget/RelativeLayout.java @@ -22,6 +22,7 @@ import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; import android.view.Gravity; +import android.view.ViewDebug; import android.widget.RemoteViews.RemoteView; import android.graphics.Rect; import com.android.internal.R; @@ -803,13 +804,33 @@ public class RelativeLayout extends ViewGroup { * @attr ref android.R.styleable#RelativeLayout_Layout_layout_centerVertical */ public static class LayoutParams extends ViewGroup.MarginLayoutParams { + @ViewDebug.ExportedProperty(resolveId = true, indexMapping = { + @ViewDebug.IntToString(from = ABOVE, to = "above"), + @ViewDebug.IntToString(from = ALIGN_BASELINE, to = "alignBaseline"), + @ViewDebug.IntToString(from = ALIGN_BOTTOM, to = "alignBottom"), + @ViewDebug.IntToString(from = ALIGN_LEFT, to = "alignLeft"), + @ViewDebug.IntToString(from = ALIGN_PARENT_BOTTOM, to = "alignParentBottom"), + @ViewDebug.IntToString(from = ALIGN_PARENT_LEFT, to = "alignParentLeft"), + @ViewDebug.IntToString(from = ALIGN_PARENT_RIGHT, to = "alignParentRight"), + @ViewDebug.IntToString(from = ALIGN_PARENT_TOP, to = "alignParentTop"), + @ViewDebug.IntToString(from = ALIGN_RIGHT, to = "alignRight"), + @ViewDebug.IntToString(from = ALIGN_TOP, to = "alignTop"), + @ViewDebug.IntToString(from = BELOW, to = "below"), + @ViewDebug.IntToString(from = CENTER_HORIZONTAL, to = "centerHorizontal"), + @ViewDebug.IntToString(from = CENTER_IN_PARENT, to = "center"), + @ViewDebug.IntToString(from = CENTER_VERTICAL, to = "centerVertical"), + @ViewDebug.IntToString(from = LEFT_OF, to = "leftOf"), + @ViewDebug.IntToString(from = RIGHT_OF, to = "rightOf") + }, mapping = { @ViewDebug.IntToString(from = TRUE, to = "true") }) private int[] mRules = new int[VERB_COUNT]; + private int mLeft, mTop, mRight, mBottom; /** * When true, uses the parent as the anchor if the anchor doesn't exist or if * the anchor's visibility is GONE. */ + @ViewDebug.ExportedProperty public boolean alignWithParent; public LayoutParams(Context c, AttributeSet attrs) { diff --git a/core/java/android/widget/SlidingDrawer.java b/core/java/android/widget/SlidingDrawer.java index e77c4ca..e0f1bb4 100644 --- a/core/java/android/widget/SlidingDrawer.java +++ b/core/java/android/widget/SlidingDrawer.java @@ -358,15 +358,17 @@ public class SlidingDrawer extends ViewGroup { } if (action == MotionEvent.ACTION_DOWN) { - if (mOnDrawerScrollListener != null) { - mOnDrawerScrollListener.onScrollStarted(); - } mTracking = true; handle.setPressed(true); // Must be called before prepareTracking() prepareContent(); + // Must be called after prepareContent() + if (mOnDrawerScrollListener != null) { + mOnDrawerScrollListener.onScrollStarted(); + } + if (mVertical) { final int top = mHandle.getTop(); mTouchDelta = (int) y - top; @@ -447,6 +449,8 @@ public class SlidingDrawer extends ViewGroup { } else { animateOpen(vertical ? top : left); } + } else { + performFling(vertical ? top : left, velocity, false); } } else { @@ -762,11 +766,11 @@ public class SlidingDrawer extends ViewGroup { * @see #toggle() */ public void animateClose() { + prepareContent(); final OnDrawerScrollListener scrollListener = mOnDrawerScrollListener; if (scrollListener != null) { scrollListener.onScrollStarted(); } - prepareContent(); animateClose(mVertical ? mHandle.getTop() : mHandle.getLeft()); if (scrollListener != null) { scrollListener.onScrollEnded(); @@ -783,11 +787,11 @@ public class SlidingDrawer extends ViewGroup { * @see #toggle() */ public void animateOpen() { + prepareContent(); final OnDrawerScrollListener scrollListener = mOnDrawerScrollListener; if (scrollListener != null) { scrollListener.onScrollStarted(); } - prepareContent(); animateOpen(mVertical ? mHandle.getTop() : mHandle.getLeft()); if (scrollListener != null) { scrollListener.onScrollEnded(); diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 8271a9a..426d711 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -3242,6 +3242,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } }; mPopup.setFocusable(false); + // The user is entering text, so the input method is needed. We + // don't want the popup to be displayed on top of it. + mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED); } TextView tv = (TextView) mPopup.getContentView(); diff --git a/core/java/android/widget/VideoView.java b/core/java/android/widget/VideoView.java index ec6f88b..4c5df2f 100644 --- a/core/java/android/widget/VideoView.java +++ b/core/java/android/widget/VideoView.java @@ -302,15 +302,15 @@ public class VideoView extends SurfaceView implements MediaPlayerControl { private MediaPlayer.OnErrorListener mErrorListener = new MediaPlayer.OnErrorListener() { - public boolean onError(MediaPlayer mp, int a, int b) { - Log.d(TAG, "Error: " + a + "," + b); + public boolean onError(MediaPlayer mp, int framework_err, int impl_err) { + Log.d(TAG, "Error: " + framework_err + "," + impl_err); if (mMediaController != null) { mMediaController.hide(); } /* If an error handler has been supplied, use it and finish. */ if (mOnErrorListener != null) { - if (mOnErrorListener.onError(mMediaPlayer, a, b)) { + if (mOnErrorListener.onError(mMediaPlayer, framework_err, impl_err)) { return true; } } @@ -322,9 +322,17 @@ public class VideoView extends SurfaceView implements MediaPlayerControl { */ if (getWindowToken() != null) { Resources r = mContext.getResources(); + int messageId; + + if (framework_err == MediaPlayer.MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK) { + messageId = com.android.internal.R.string.VideoView_error_text_invalid_progressive_playback; + } else { + messageId = com.android.internal.R.string.VideoView_error_text_unknown; + } + new AlertDialog.Builder(mContext) .setTitle(com.android.internal.R.string.VideoView_error_title) - .setMessage(com.android.internal.R.string.VideoView_error_text_unknown) + .setMessage(messageId) .setPositiveButton(com.android.internal.R.string.VideoView_error_button, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { diff --git a/core/java/android/widget/ZoomButtonsController.java b/core/java/android/widget/ZoomButtonsController.java index 1ba2dce..6729fd1 100644 --- a/core/java/android/widget/ZoomButtonsController.java +++ b/core/java/android/widget/ZoomButtonsController.java @@ -36,6 +36,7 @@ import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewConfiguration; +import android.view.ViewGroup; import android.view.Window; import android.view.WindowManager; import android.view.View.OnClickListener; @@ -61,7 +62,7 @@ public class ZoomButtonsController implements View.OnTouchListener, View.OnKeyLi // TODO: scaled to density private static final int ZOOM_CONTROLS_TOUCH_PADDING = 20; - + private Context mContext; private WindowManager mWindowManager; @@ -84,7 +85,7 @@ public class ZoomButtonsController implements View.OnTouchListener, View.OnKeyLi private int[] mContainerLocation = new int[2]; private ZoomControls mControls; - + /** * The view (or null) that should receive touch events. This will get set if * the touch down hits the container. It will be reset on the touch up. @@ -100,7 +101,7 @@ public class ZoomButtonsController implements View.OnTouchListener, View.OnKeyLi * up/cancel, and then set the owner's touch listener to null. */ private boolean mReleaseTouchListenerOnUp; - + private boolean mIsSecondTapDown; private boolean mIsVisible; @@ -145,7 +146,7 @@ public class ZoomButtonsController implements View.OnTouchListener, View.OnKeyLi * we delay the setVisible(true) call until it is not null. */ private static final int MSG_POST_SET_VISIBLE = 4; - + private Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { @@ -157,7 +158,7 @@ public class ZoomButtonsController implements View.OnTouchListener, View.OnKeyLi case MSG_DISMISS_ZOOM_CONTROLS: setVisible(false); break; - + case MSG_POST_SET_VISIBLE: if (mOwnerView.getWindowToken() == null) { // Doh, it is still null, throw an exception @@ -179,19 +180,19 @@ public class ZoomButtonsController implements View.OnTouchListener, View.OnKeyLi mContainer = createContainer(); } - + public void setZoomInEnabled(boolean enabled) { mControls.setIsZoomInEnabled(enabled); } - + public void setZoomOutEnabled(boolean enabled) { mControls.setIsZoomOutEnabled(enabled); } - + public void setZoomSpeed(long speed) { mControls.setZoomSpeed(speed); } - + private FrameLayout createContainer() { LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); lp.gravity = Gravity.BOTTOM | Gravity.CENTER; @@ -202,19 +203,18 @@ public class ZoomButtonsController implements View.OnTouchListener, View.OnKeyLi lp.width = LayoutParams.FILL_PARENT; lp.type = LayoutParams.TYPE_APPLICATION_PANEL; lp.format = PixelFormat.TRANSPARENT; - // TODO: make a new animation for this - lp.windowAnimations = com.android.internal.R.style.Animation_InputMethodFancy; + lp.windowAnimations = com.android.internal.R.style.Animation_ZoomButtons; mContainerLayoutParams = lp; - + FrameLayout container = new FrameLayout(mContext); container.setLayoutParams(lp); container.setMeasureAllChildren(true); container.setOnKeyListener(this); - + LayoutInflater inflater = (LayoutInflater) mContext .getSystemService(Context.LAYOUT_INFLATER_SERVICE); - inflater.inflate(com.android.internal.R.layout.zoom_magnify, container); - + inflater.inflate(com.android.internal.R.layout.zoom_container, container); + mControls = (ZoomControls) container.findViewById(com.android.internal.R.id.zoomControls); mControls.setOnZoomInClickListener(new OnClickListener() { public void onClick(View v) { @@ -229,38 +229,24 @@ public class ZoomButtonsController implements View.OnTouchListener, View.OnKeyLi } }); - View overview = container.findViewById(com.android.internal.R.id.zoomMagnify); - overview.setVisibility(View.GONE); - overview.setOnClickListener(new OnClickListener() { - public void onClick(View v) { - dismissControlsDelayed(ZOOM_CONTROLS_TIMEOUT); - if (mCallback != null) mCallback.onOverview(); - } - }); - return container; } - + public void setCallback(OnZoomListener callback) { mCallback = callback; } public void setFocusable(boolean focusable) { if (focusable) { - mContainerLayoutParams.flags &= ~LayoutParams.FLAG_NOT_FOCUSABLE; + mContainerLayoutParams.flags &= ~LayoutParams.FLAG_NOT_FOCUSABLE; } else { mContainerLayoutParams.flags |= LayoutParams.FLAG_NOT_FOCUSABLE; } - + if (mIsVisible) { mWindowManager.updateViewLayout(mContainer, mContainerLayoutParams); } } - - public void setOverviewVisible(boolean visible) { - mContainer.findViewById(com.android.internal.R.id.zoomMagnify) - .setVisibility(visible ? View.VISIBLE : View.GONE); - } public boolean isVisible() { return mIsVisible; @@ -269,7 +255,7 @@ public class ZoomButtonsController implements View.OnTouchListener, View.OnKeyLi public void setVisible(boolean visible) { if (!useThisZoom(mContext)) return; - + if (visible) { if (mOwnerView.getWindowToken() == null) { /* @@ -282,7 +268,7 @@ public class ZoomButtonsController implements View.OnTouchListener, View.OnKeyLi } return; } - + dismissControlsDelayed(ZOOM_CONTROLS_TIMEOUT); } @@ -350,14 +336,10 @@ public class ZoomButtonsController implements View.OnTouchListener, View.OnKeyLi * * @return TODO */ - public FrameLayout getContainer() { + public ViewGroup getContainer() { return mContainer; } - public int getZoomControlsId() { - return mControls.getId(); - } - private void dismissControlsDelayed(int delay) { mHandler.removeMessages(MSG_DISMISS_ZOOM_CONTROLS); mHandler.sendEmptyMessageDelayed(MSG_DISMISS_ZOOM_CONTROLS, delay); @@ -372,7 +354,7 @@ public class ZoomButtonsController implements View.OnTouchListener, View.OnKeyLi */ public boolean handleDoubleTapEvent(MotionEvent event) { if (!useThisZoom(mContext)) return false; - + int action = event.getAction(); if (action == MotionEvent.ACTION_DOWN) { @@ -428,7 +410,7 @@ public class ZoomButtonsController implements View.OnTouchListener, View.OnKeyLi // The second tap can no longer be down mIsSecondTapDown = false; } - + if (mReleaseTouchListenerOnUp) { // The controls were dismissed but we need to throw away all events until the up if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) { @@ -443,7 +425,7 @@ public class ZoomButtonsController implements View.OnTouchListener, View.OnKeyLi // TODO: optimize this (it ends up removing message and queuing another) dismissControlsDelayed(ZOOM_CONTROLS_TIMEOUT); - + View targetView = mTouchTargetView; switch (action) { @@ -556,7 +538,7 @@ public class ZoomButtonsController implements View.OnTouchListener, View.OnKeyLi com.android.internal.R.layout.alert_dialog_simple_text, null) .findViewById(android.R.id.text1); textView.setText(com.android.internal.R.string.tutorial_double_tap_to_zoom_message_short); - + sTutorialDialog = new AlertDialog.Builder(context) .setView(textView) .setIcon(0) @@ -603,7 +585,7 @@ public class ZoomButtonsController implements View.OnTouchListener, View.OnKeyLi // Temporary methods for different zoom types static int getZoomType(Context context) { - return Settings.System.getInt(context.getContentResolver(), "zoom", 1); + return Settings.System.getInt(context.getContentResolver(), "zoom", 2); } public static boolean useOldZoom(Context context) { @@ -618,6 +600,5 @@ public class ZoomButtonsController implements View.OnTouchListener, View.OnKeyLi void onCenter(int x, int y); void onVisibilityChanged(boolean visible); void onZoom(boolean zoomIn); - void onOverview(); } } diff --git a/core/java/com/android/internal/gadget/IGadgetHost.aidl b/core/java/com/android/internal/appwidget/IAppWidgetHost.aidl index e7b5a1e..2ed4773 100644 --- a/core/java/com/android/internal/gadget/IGadgetHost.aidl +++ b/core/java/com/android/internal/appwidget/IAppWidgetHost.aidl @@ -14,15 +14,15 @@ * limitations under the License. */ -package com.android.internal.gadget; +package com.android.internal.appwidget; import android.content.ComponentName; -import android.gadget.GadgetProviderInfo; +import android.appwidget.AppWidgetProviderInfo; import android.widget.RemoteViews; /** {@hide} */ -oneway interface IGadgetHost { - void updateGadget(int gadgetId, in RemoteViews views); - void providerChanged(int gadgetId, in GadgetProviderInfo info); +oneway interface IAppWidgetHost { + void updateAppWidget(int appWidgetId, in RemoteViews views); + void providerChanged(int appWidgetId, in AppWidgetProviderInfo info); } diff --git a/core/java/com/android/internal/gadget/IGadgetService.aidl b/core/java/com/android/internal/appwidget/IAppWidgetService.aidl index 9c66b95..496aa1a 100644 --- a/core/java/com/android/internal/gadget/IGadgetService.aidl +++ b/core/java/com/android/internal/appwidget/IAppWidgetService.aidl @@ -14,37 +14,37 @@ * limitations under the License. */ -package com.android.internal.gadget; +package com.android.internal.appwidget; import android.content.ComponentName; -import android.gadget.GadgetProviderInfo; -import com.android.internal.gadget.IGadgetHost; +import android.appwidget.AppWidgetProviderInfo; +import com.android.internal.appwidget.IAppWidgetHost; import android.widget.RemoteViews; /** {@hide} */ -interface IGadgetService { +interface IAppWidgetService { // - // for GadgetHost + // for AppWidgetHost // - int[] startListening(IGadgetHost host, String packageName, int hostId, + int[] startListening(IAppWidgetHost host, String packageName, int hostId, out List<RemoteViews> updatedViews); void stopListening(int hostId); - int allocateGadgetId(String packageName, int hostId); - void deleteGadgetId(int gadgetId); + int allocateAppWidgetId(String packageName, int hostId); + void deleteAppWidgetId(int appWidgetId); void deleteHost(int hostId); void deleteAllHosts(); - RemoteViews getGadgetViews(int gadgetId); + RemoteViews getAppWidgetViews(int appWidgetId); // - // for GadgetManager + // for AppWidgetManager // - void updateGadgetIds(in int[] gadgetIds, in RemoteViews views); - void updateGadgetProvider(in ComponentName provider, in RemoteViews views); - List<GadgetProviderInfo> getInstalledProviders(); - GadgetProviderInfo getGadgetInfo(int gadgetId); - void bindGadgetId(int gadgetId, in ComponentName provider); - int[] getGadgetIds(in ComponentName provider); + void updateAppWidgetIds(in int[] appWidgetIds, in RemoteViews views); + void updateAppWidgetProvider(in ComponentName provider, in RemoteViews views); + List<AppWidgetProviderInfo> getInstalledProviders(); + AppWidgetProviderInfo getAppWidgetInfo(int appWidgetId); + void bindAppWidgetId(int appWidgetId, in ComponentName provider); + int[] getAppWidgetIds(in ComponentName provider); } diff --git a/core/java/com/android/internal/gadget/package.html b/core/java/com/android/internal/appwidget/package.html index db6f78b..db6f78b 100644 --- a/core/java/com/android/internal/gadget/package.html +++ b/core/java/com/android/internal/appwidget/package.html diff --git a/core/java/com/android/internal/widget/NumberPicker.java b/core/java/com/android/internal/widget/NumberPicker.java index 1647c20..2f08c8d 100644 --- a/core/java/com/android/internal/widget/NumberPicker.java +++ b/core/java/com/android/internal/widget/NumberPicker.java @@ -30,6 +30,7 @@ import android.view.View.OnFocusChangeListener; import android.view.View.OnLongClickListener; import android.widget.TextView; import android.widget.LinearLayout; +import android.widget.EditText; import com.android.internal.R; @@ -76,7 +77,7 @@ public class NumberPicker extends LinearLayout implements OnClickListener, } }; - private final TextView mText; + private final EditText mText; private final InputFilter mNumberInputFilter; private String[] mDisplayedValues; @@ -117,7 +118,7 @@ public class NumberPicker extends LinearLayout implements OnClickListener, mDecrementButton.setOnLongClickListener(this); mDecrementButton.setNumberPicker(this); - mText = (TextView) findViewById(R.id.timepicker_input); + mText = (EditText) findViewById(R.id.timepicker_input); mText.setOnFocusChangeListener(this); mText.setFilters(new InputFilter[] {inputFilter}); mText.setRawInputType(InputType.TYPE_CLASS_NUMBER); @@ -188,11 +189,8 @@ public class NumberPicker extends LinearLayout implements OnClickListener, } public void onClick(View v) { - - /* The text view may still have focus so clear it's focus which will - * trigger the on focus changed and any typed values to be pulled. - */ - mText.clearFocus(); + validateInput(mText); + if (!mText.hasFocus()) mText.requestFocus(); // now perform the increment/decrement if (R.id.increment == v.getId()) { @@ -239,6 +237,7 @@ public class NumberPicker extends LinearLayout implements OnClickListener, } else { mText.setText(mDisplayedValues[mCurrent - mStart]); } + mText.setSelection(mText.getText().length()); } private void validateCurrentView(CharSequence str) { @@ -257,16 +256,20 @@ public class NumberPicker extends LinearLayout implements OnClickListener, * has valid values. */ if (!hasFocus) { - String str = String.valueOf(((TextView) v).getText()); - if ("".equals(str)) { - - // Restore to the old value as we don't allow empty values - updateView(); - } else { - - // Check the new value and ensure it's in range - validateCurrentView(str); - } + validateInput(v); + } + } + + private void validateInput(View v) { + String str = String.valueOf(((TextView) v).getText()); + if ("".equals(str)) { + + // Restore to the old value as we don't allow empty values + updateView(); + } else { + + // Check the new value and ensure it's in range + validateCurrentView(str); } } diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp index 28c602b..f4643f4 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -220,7 +220,7 @@ int register_com_android_internal_os_RuntimeInit(JNIEnv* env) AndroidRuntime::AndroidRuntime() { - SkGraphics::Init(false); // true means run unittests (slow) + SkGraphics::Init(); // this sets our preference for 16bit images during decode // in case the src is opaque and 24bit SkImageDecoder::SetDeviceConfig(SkBitmap::kRGB_565_Config); diff --git a/core/jni/android_server_BluetoothEventLoop.cpp b/core/jni/android_server_BluetoothEventLoop.cpp index adfd912..c03bab6 100644 --- a/core/jni/android_server_BluetoothEventLoop.cpp +++ b/core/jni/android_server_BluetoothEventLoop.cpp @@ -61,6 +61,8 @@ static jmethodID method_onPasskeyAgentCancel; static jmethodID method_onAuthAgentAuthorize; static jmethodID method_onAuthAgentCancel; +static jmethodID method_onRestartRequired; + typedef event_loop_native_data_t native_data_t; // Only valid during waitForAndDispatchEventNative() @@ -99,6 +101,8 @@ static void classInitNative(JNIEnv* env, jclass clazz) { method_onAuthAgentCancel = env->GetMethodID(clazz, "onAuthAgentCancel", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V"); method_onGetRemoteServiceChannelResult = env->GetMethodID(clazz, "onGetRemoteServiceChannelResult", "(Ljava/lang/String;I)V"); + method_onRestartRequired = env->GetMethodID(clazz, "onRestartRequired", "()V"); + field_mNativeData = env->GetFieldID(clazz, "mNativeData", "I"); #endif } @@ -165,6 +169,13 @@ static jboolean setUpEventLoopNative(JNIEnv *env, jobject object) { // Set which messages will be processed by this dbus connection dbus_bus_add_match(nat->conn, + "type='signal',interface='org.freedesktop.DBus'", + &err); + if (dbus_error_is_set(&err)) { + LOG_AND_FREE_DBUS_ERROR(&err); + return JNI_FALSE; + } + dbus_bus_add_match(nat->conn, "type='signal',interface='"BLUEZ_DBUS_BASE_IFC".Adapter'", &err); if (dbus_error_is_set(&err)) { @@ -302,6 +313,12 @@ static void tearDownEventLoopNative(JNIEnv *env, jobject object) { if (dbus_error_is_set(&err)) { LOG_AND_FREE_DBUS_ERROR(&err); } + dbus_bus_remove_match(nat->conn, + "type='signal',interface='org.freedesktop.DBus'", + &err); + if (dbus_error_is_set(&err)) { + LOG_AND_FREE_DBUS_ERROR(&err); + } dbus_connection_remove_filter(nat->conn, event_filter, nat); } @@ -509,6 +526,28 @@ static DBusHandlerResult event_filter(DBusConnection *conn, DBusMessage *msg, env->NewStringUTF(c_name)); } else LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg); return DBUS_HANDLER_RESULT_HANDLED; + } else if (dbus_message_is_signal(msg, + "org.freedesktop.DBus", + "NameOwnerChanged")) { + char *c_name; + char *c_old_owner; + char *c_new_owner; + if (dbus_message_get_args(msg, &err, + DBUS_TYPE_STRING, &c_name, + DBUS_TYPE_STRING, &c_old_owner, + DBUS_TYPE_STRING, &c_new_owner, + DBUS_TYPE_INVALID)) { + LOGV("... name = %s", c_name); + LOGV("... old_owner = %s", c_old_owner); + LOGV("... new_owner = %s", c_new_owner); + if (!strcmp(c_name, "org.bluez") && c_new_owner[0] != '\0') { + // New owner of org.bluez. This can only happen when hcid + // restarts. Need to restart framework BT services to recover. + LOGE("Looks like hcid restarted"); + env->CallVoidMethod(nat->me, method_onRestartRequired); + } + } else LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg); + return DBUS_HANDLER_RESULT_HANDLED; } return a2dp_event_filter(msg, env); diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index e9db5f0..1b145af 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -924,13 +924,13 @@ android:description="@string/permdesc_batteryStats" android:protectionLevel="normal" /> - <!-- Allows an application to tell the gadget service which application - can access gadget's data. The normal user flow is that a user - picks a gadget to go into a particular host, thereby giving that - host application access to the private data from the gadget app. + <!-- Allows an application to tell the AppWidget service which application + can access AppWidget's data. The normal user flow is that a user + picks an AppWidget to go into a particular host, thereby giving that + host application access to the private data from the AppWidget app. An application that has this permission should honor that contract. Very few applications should need to use this permission. --> - <permission android:name="android.permission.BIND_GADGET" + <permission android:name="android.permission.BIND_APPWIDGET" android:permissionGroup="android.permission-group.PERSONAL_INFO" android:label="@string/permlab_bindGadget" android:description="@string/permdesc_bindGadget" diff --git a/core/res/res/drawable/btn_browser_zoom_fit_page.xml b/core/res/res/drawable/btn_browser_zoom_fit_page.xml new file mode 100644 index 0000000..2f4761a --- /dev/null +++ b/core/res/res/drawable/btn_browser_zoom_fit_page.xml @@ -0,0 +1,20 @@ +<?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. +--> + +<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:drawable="@android:drawable/btn_square_overlay" /> + <item android:drawable="@android:drawable/ic_btn_square_browser_zoom_fit_page" /> +</layer-list> diff --git a/core/res/res/drawable/btn_browser_zoom_page_overview.xml b/core/res/res/drawable/btn_browser_zoom_page_overview.xml new file mode 100644 index 0000000..16fb1e6 --- /dev/null +++ b/core/res/res/drawable/btn_browser_zoom_page_overview.xml @@ -0,0 +1,20 @@ +<?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. +--> + +<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:drawable="@android:drawable/btn_square_overlay" /> + <item android:drawable="@android:drawable/ic_btn_square_browser_zoom_page_overview" /> +</layer-list> diff --git a/core/res/res/drawable/btn_square_overlay.xml b/core/res/res/drawable/btn_square_overlay.xml new file mode 100644 index 0000000..a2c698c --- /dev/null +++ b/core/res/res/drawable/btn_square_overlay.xml @@ -0,0 +1,26 @@ +<?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. +--> + +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:state_enabled="false" android:state_focused="true" + android:state_window_focused="true" + android:drawable="@drawable/btn_square_overlay_disabled_focused" /> + <item android:state_enabled="false" android:drawable="@drawable/btn_square_overlay_disabled" /> + <item android:state_pressed="true" android:drawable="@drawable/btn_square_overlay_pressed" /> + <item android:state_focused="true" android:state_window_focused="true" + android:drawable="@drawable/btn_square_overlay_selected" /> + <item android:drawable="@drawable/btn_square_overlay_normal" /> +</selector>
\ No newline at end of file diff --git a/core/res/res/drawable/btn_square_overlay_disabled.png b/core/res/res/drawable/btn_square_overlay_disabled.png Binary files differnew file mode 100644 index 0000000..cf7e4ea --- /dev/null +++ b/core/res/res/drawable/btn_square_overlay_disabled.png diff --git a/core/res/res/drawable/btn_square_overlay_disabled_focused.png b/core/res/res/drawable/btn_square_overlay_disabled_focused.png Binary files differnew file mode 100644 index 0000000..5aa1143 --- /dev/null +++ b/core/res/res/drawable/btn_square_overlay_disabled_focused.png diff --git a/core/res/res/drawable/btn_square_overlay_normal.png b/core/res/res/drawable/btn_square_overlay_normal.png Binary files differnew file mode 100644 index 0000000..45fa4fe --- /dev/null +++ b/core/res/res/drawable/btn_square_overlay_normal.png diff --git a/core/res/res/drawable/btn_square_overlay_pressed.png b/core/res/res/drawable/btn_square_overlay_pressed.png Binary files differnew file mode 100644 index 0000000..952571b --- /dev/null +++ b/core/res/res/drawable/btn_square_overlay_pressed.png diff --git a/core/res/res/drawable/btn_square_overlay_selected.png b/core/res/res/drawable/btn_square_overlay_selected.png Binary files differnew file mode 100644 index 0000000..ce4515e --- /dev/null +++ b/core/res/res/drawable/btn_square_overlay_selected.png diff --git a/core/res/res/drawable/btn_zoom_down.xml b/core/res/res/drawable/btn_zoom_down.xml new file mode 100644 index 0000000..e7449aa --- /dev/null +++ b/core/res/res/drawable/btn_zoom_down.xml @@ -0,0 +1,27 @@ +<?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. +--> + +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:state_enabled="false" android:state_focused="true" + android:state_window_focused="true" + android:drawable="@drawable/btn_zoom_down_disabled_focused" /> + <item android:state_enabled="false" android:drawable="@drawable/btn_zoom_down_disabled" /> + <item android:state_pressed="true" android:drawable="@drawable/btn_zoom_down_pressed" /> + <item android:state_focused="true" android:state_window_focused="true" + android:drawable="@drawable/btn_zoom_down_selected" /> + <item android:drawable="@drawable/btn_zoom_down_normal" /> +</selector> + diff --git a/core/res/res/drawable/btn_zoom_down_disabled.9.png b/core/res/res/drawable/btn_zoom_down_disabled.9.png Binary files differnew file mode 100644 index 0000000..7780bd7 --- /dev/null +++ b/core/res/res/drawable/btn_zoom_down_disabled.9.png diff --git a/core/res/res/drawable/btn_zoom_down_disabled_focused.9.png b/core/res/res/drawable/btn_zoom_down_disabled_focused.9.png Binary files differnew file mode 100644 index 0000000..39131c5 --- /dev/null +++ b/core/res/res/drawable/btn_zoom_down_disabled_focused.9.png diff --git a/core/res/res/drawable/btn_zoom_down_longpress.9.png b/core/res/res/drawable/btn_zoom_down_longpress.9.png Binary files differnew file mode 100644 index 0000000..09a3bb3 --- /dev/null +++ b/core/res/res/drawable/btn_zoom_down_longpress.9.png diff --git a/core/res/res/drawable/btn_zoom_down_normal.9.png b/core/res/res/drawable/btn_zoom_down_normal.9.png Binary files differnew file mode 100644 index 0000000..b589a84 --- /dev/null +++ b/core/res/res/drawable/btn_zoom_down_normal.9.png diff --git a/core/res/res/drawable/btn_zoom_down_pressed.9.png b/core/res/res/drawable/btn_zoom_down_pressed.9.png Binary files differnew file mode 100644 index 0000000..a8ca467 --- /dev/null +++ b/core/res/res/drawable/btn_zoom_down_pressed.9.png diff --git a/core/res/res/drawable/btn_zoom_down_selected.9.png b/core/res/res/drawable/btn_zoom_down_selected.9.png Binary files differnew file mode 100644 index 0000000..af551e7 --- /dev/null +++ b/core/res/res/drawable/btn_zoom_down_selected.9.png diff --git a/core/res/res/drawable/btn_zoom_up.xml b/core/res/res/drawable/btn_zoom_up.xml new file mode 100644 index 0000000..045b3c3 --- /dev/null +++ b/core/res/res/drawable/btn_zoom_up.xml @@ -0,0 +1,27 @@ +<?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. +--> + +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:state_enabled="false" android:state_focused="true" + android:state_window_focused="true" + android:drawable="@drawable/btn_zoom_up_disabled_focused" /> + <item android:state_enabled="false" android:drawable="@drawable/btn_zoom_up_disabled" /> + <item android:state_pressed="true" android:drawable="@drawable/btn_zoom_up_pressed" /> + <item android:state_focused="true" android:state_window_focused="true" + android:drawable="@drawable/btn_zoom_up_selected" /> + <item android:drawable="@drawable/btn_zoom_up_normal" /> +</selector> + diff --git a/core/res/res/drawable/btn_zoom_up_disabled.9.png b/core/res/res/drawable/btn_zoom_up_disabled.9.png Binary files differnew file mode 100644 index 0000000..5203630 --- /dev/null +++ b/core/res/res/drawable/btn_zoom_up_disabled.9.png diff --git a/core/res/res/drawable/btn_zoom_up_disabled_focused.9.png b/core/res/res/drawable/btn_zoom_up_disabled_focused.9.png Binary files differnew file mode 100644 index 0000000..c72c9cd --- /dev/null +++ b/core/res/res/drawable/btn_zoom_up_disabled_focused.9.png diff --git a/core/res/res/drawable/btn_zoom_up_longpress.9.png b/core/res/res/drawable/btn_zoom_up_longpress.9.png Binary files differnew file mode 100644 index 0000000..8de48d1 --- /dev/null +++ b/core/res/res/drawable/btn_zoom_up_longpress.9.png diff --git a/core/res/res/drawable/btn_zoom_up_normal.9.png b/core/res/res/drawable/btn_zoom_up_normal.9.png Binary files differnew file mode 100644 index 0000000..5027348 --- /dev/null +++ b/core/res/res/drawable/btn_zoom_up_normal.9.png diff --git a/core/res/res/drawable/btn_zoom_up_pressed.9.png b/core/res/res/drawable/btn_zoom_up_pressed.9.png Binary files differnew file mode 100644 index 0000000..1a93e3a --- /dev/null +++ b/core/res/res/drawable/btn_zoom_up_pressed.9.png diff --git a/core/res/res/drawable/btn_zoom_up_selected.9.png b/core/res/res/drawable/btn_zoom_up_selected.9.png Binary files differnew file mode 100644 index 0000000..26aafee --- /dev/null +++ b/core/res/res/drawable/btn_zoom_up_selected.9.png diff --git a/core/res/res/drawable/ic_btn_square_browser_zoom_fit_page.xml b/core/res/res/drawable/ic_btn_square_browser_zoom_fit_page.xml new file mode 100644 index 0000000..bec869a --- /dev/null +++ b/core/res/res/drawable/ic_btn_square_browser_zoom_fit_page.xml @@ -0,0 +1,20 @@ +<?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. +--> + +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:state_enabled="false" android:drawable="@drawable/ic_btn_square_browser_zoom_fit_page_disabled" /> + <item android:drawable="@drawable/ic_btn_square_browser_zoom_fit_page_normal" /> +</selector>
\ No newline at end of file diff --git a/core/res/res/drawable/ic_btn_square_browser_zoom_fit_page_disabled.png b/core/res/res/drawable/ic_btn_square_browser_zoom_fit_page_disabled.png Binary files differnew file mode 100644 index 0000000..326397c --- /dev/null +++ b/core/res/res/drawable/ic_btn_square_browser_zoom_fit_page_disabled.png diff --git a/core/res/res/drawable/ic_btn_square_browser_zoom_fit_page_normal.png b/core/res/res/drawable/ic_btn_square_browser_zoom_fit_page_normal.png Binary files differnew file mode 100644 index 0000000..5583401 --- /dev/null +++ b/core/res/res/drawable/ic_btn_square_browser_zoom_fit_page_normal.png diff --git a/core/res/res/drawable/ic_btn_square_browser_zoom_page_overview.png b/core/res/res/drawable/ic_btn_square_browser_zoom_page_overview.png Binary files differnew file mode 100644 index 0000000..4e8ff35 --- /dev/null +++ b/core/res/res/drawable/ic_btn_square_browser_zoom_page_overview.png diff --git a/core/res/res/drawable/seek_thumb.xml b/core/res/res/drawable/seek_thumb.xml index 7fe51b3..c7a862d 100644 --- a/core/res/res/drawable/seek_thumb.xml +++ b/core/res/res/drawable/seek_thumb.xml @@ -14,7 +14,7 @@ limitations under the License. --> -<!-- This is the rating bar drawable that is used to a show a filled star. --> +<!-- This is the thumb on the seek bar. --> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_pressed="true" diff --git a/core/res/res/drawable/seek_thumb_normal.png b/core/res/res/drawable/seek_thumb_normal.png Binary files differindex dbaae91..e9f2e23 100644 --- a/core/res/res/drawable/seek_thumb_normal.png +++ b/core/res/res/drawable/seek_thumb_normal.png diff --git a/core/res/res/drawable/seek_thumb_pressed.png b/core/res/res/drawable/seek_thumb_pressed.png Binary files differindex dbaae91..3ea5051 100644 --- a/core/res/res/drawable/seek_thumb_pressed.png +++ b/core/res/res/drawable/seek_thumb_pressed.png diff --git a/core/res/res/drawable/seek_thumb_selected.png b/core/res/res/drawable/seek_thumb_selected.png Binary files differindex dbaae91..98b7ba0 100644 --- a/core/res/res/drawable/seek_thumb_selected.png +++ b/core/res/res/drawable/seek_thumb_selected.png diff --git a/core/res/res/layout/input_method_extract_view.xml b/core/res/res/layout/input_method_extract_view.xml index 13b619a..1244c1d 100644 --- a/core/res/res/layout/input_method_extract_view.xml +++ b/core/res/res/layout/input_method_extract_view.xml @@ -44,7 +44,7 @@ android:background="@android:drawable/keyboard_accessory_bg_landscape" > - <Button android:id="@+id/inputExtractAction" + <android.inputmethodservice.ExtractButton android:id="@+id/inputExtractAction" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" diff --git a/core/res/res/layout/keyguard_screen_glogin_unlock.xml b/core/res/res/layout/keyguard_screen_glogin_unlock.xml index b78bb94..4834b28 100644 --- a/core/res/res/layout/keyguard_screen_glogin_unlock.xml +++ b/core/res/res/layout/keyguard_screen_glogin_unlock.xml @@ -20,7 +20,7 @@ android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" - android:background="#A0000000" + android:background="@android:color/background_dark" > <ScrollView android:layout_width="fill_parent" @@ -35,10 +35,11 @@ <TextView android:id="@+id/topHeader" android:layout_width="fill_parent" - android:layout_height="wrap_content" + android:layout_height="64dip" android:layout_alignParentTop="true" - android:textSize="24sp" - android:layout_marginTop="8dip" + android:layout_marginLeft="4dip" + android:textAppearance="?android:attr/textAppearanceMedium" + android:gravity="center_vertical" android:drawableLeft="@drawable/ic_lock_idle_lock" android:drawablePadding="5dip" android:text="@android:string/lockscreen_glogin_too_many_attempts" @@ -50,8 +51,7 @@ android:layout_width="fill_parent" android:layout_height="1dip" android:layout_below="@id/topHeader" - android:layout_marginTop="8dip" - android:background="@android:drawable/divider_horizontal_bright"/> + android:background="@drawable/divider_horizontal_dark"/> <TextView android:id="@+id/instructions" @@ -59,8 +59,8 @@ android:layout_height="wrap_content" android:layout_below="@+id/spacerTop" android:layout_marginTop="8dip" - android:gravity="center" - android:textSize="18sp" + android:layout_marginLeft="9dip" + android:textAppearance="?android:attr/textAppearanceSmall" android:text="@android:string/lockscreen_glogin_instructions" /> @@ -70,6 +70,8 @@ android:layout_height="wrap_content" android:layout_below="@id/instructions" android:layout_marginTop="8dip" + android:layout_marginLeft="7dip" + android:layout_marginRight="7dip" android:hint="@android:string/lockscreen_glogin_username_hint" android:inputType="textEmailAddress" /> @@ -79,7 +81,9 @@ android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_below="@id/login" - android:layout_marginTop="8dip" + android:layout_marginTop="15dip" + android:layout_marginLeft="7dip" + android:layout_marginRight="7dip" android:inputType="textPassword" android:hint="@android:string/lockscreen_glogin_password_hint" android:nextFocusRight="@+id/ok" @@ -89,38 +93,35 @@ <!-- ok below password, aligned to right of screen --> <Button android:id="@+id/ok" - android:layout_width="wrap_content" + android:layout_width="85dip" android:layout_height="wrap_content" android:layout_below="@id/password" - android:layout_marginTop="8dip" + android:layout_marginTop="7dip" + android:layout_marginRight="7dip" android:layout_alignParentRight="true" - android:textSize="18sp" android:text="@android:string/lockscreen_glogin_submit_button" /> </RelativeLayout> </ScrollView> - <View android:layout_width="1dp" android:layout_height="3dp" /> - + <!-- spacer above emergency call --> + <View + android:layout_width="fill_parent" + android:layout_height="1dip" + android:layout_marginBottom="4dip" + + android:background="@drawable/divider_horizontal_dark"/> + <!-- emergency call button at bottom center --> <Button android:id="@+id/emergencyCall" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" - android:layout_weight="0" - android:textSize="18sp" android:drawableLeft="@drawable/ic_emergency" android:drawablePadding="3dip" android:text="@android:string/lockscreen_emergency_call" /> - <!-- spacer above emergency call (doesn't fit in landscape...)--> - <!--View - android:layout_width="fill_parent" - android:layout_height="1dip" - android:layout_above="@id/emergencyCall" - android:layout_marginBottom="8dip" - android:background="@android:drawable/divider_horizontal_bright"/--> </LinearLayout> diff --git a/core/res/res/layout/keyguard_screen_lock.xml b/core/res/res/layout/keyguard_screen_lock.xml index fbbc1a4..952fc5d 100644 --- a/core/res/res/layout/keyguard_screen_lock.xml +++ b/core/res/res/layout/keyguard_screen_lock.xml @@ -36,8 +36,8 @@ android:layout_marginBottom="15dip" android:layout_marginLeft="15dip" android:layout_marginRight="15dip" - android:paddingTop="20dip" - android:paddingBottom="20dip" + android:paddingTop="20dip" + android:paddingBottom="20dip" android:background="@android:drawable/popup_full_dark" > @@ -59,13 +59,15 @@ android:layout_height="wrap_content" android:gravity="center" android:text="@android:string/lockscreen_missing_sim_message" - android:textSize="22sp"/> + android:textAppearance="?android:attr/textAppearanceLarge"/> <TextView android:id="@+id/headerSimBad2" android:layout_width="fill_parent" android:layout_height="wrap_content" + android:layout_marginTop="7dip" + android:layout_marginBottom="7dip" android:gravity="center" android:text="@android:string/lockscreen_missing_sim_instructions" - android:textSize="20sp"/> + android:textAppearance="?android:attr/textAppearanceSmall"/> <!-- spacer after carrier info / sim messages --> <View @@ -203,17 +205,15 @@ <!-- emergency call button shown when sim is missing or PUKd --> <Button android:id="@+id/emergencyCallButton" - android:layout_width="fill_parent" + android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_marginLeft="5dip" - android:layout_marginRight="5dip" android:layout_marginBottom="5dip" - android:drawableTop="@drawable/ic_emergency" + android:layout_marginTop="5dip" + android:layout_gravity="center_horizontal" + android:drawableLeft="@drawable/ic_emergency" android:drawablePadding="3dip" android:text="@android:string/lockscreen_emergency_call" - android:textSize="14sp" /> - </LinearLayout> </LinearLayout> diff --git a/core/res/res/layout/zoom_browser_accessory_buttons.xml b/core/res/res/layout/zoom_browser_accessory_buttons.xml new file mode 100644 index 0000000..4bf2bdf --- /dev/null +++ b/core/res/res/layout/zoom_browser_accessory_buttons.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 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. +*/ +--> +<merge xmlns:android="http://schemas.android.com/apk/res/android"> + <ImageView android:id="@+id/zoom_fit_page" + android:background="@android:drawable/btn_browser_zoom_fit_page" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="bottom|left" + android:layout_marginLeft="7dip" + /> + <ImageView android:id="@+id/zoom_page_overview" + android:background="@android:drawable/btn_browser_zoom_page_overview" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="bottom|right" + android:layout_marginRight="7dip" + /> +</merge> diff --git a/core/res/res/layout/zoom_container.xml b/core/res/res/layout/zoom_container.xml new file mode 100644 index 0000000..fc5cf3d --- /dev/null +++ b/core/res/res/layout/zoom_container.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 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. +*/ +--> +<merge xmlns:android="http://schemas.android.com/apk/res/android"> + <ZoomControls android:id="@+id/zoomControls" + android:layout_gravity="bottom|center_horizontal" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + style="@style/ZoomControls" + android:background="@null" + /> +</merge> diff --git a/core/res/res/layout/zoom_controls.xml b/core/res/res/layout/zoom_controls.xml index 729af1b..95cf1d5 100644 --- a/core/res/res/layout/zoom_controls.xml +++ b/core/res/res/layout/zoom_controls.xml @@ -18,13 +18,13 @@ */ --> <merge xmlns:android="http://schemas.android.com/apk/res/android"> - <ZoomButton android:id="@+id/zoomIn" - android:background="@android:drawable/btn_plus" + <ZoomButton android:id="@+id/zoomOut" + android:background="@android:drawable/btn_zoom_down" android:layout_width="wrap_content" android:layout_height="wrap_content" /> - <ZoomButton android:id="@+id/zoomOut" - android:background="@android:drawable/btn_minus" + <ZoomButton android:id="@+id/zoomIn" + android:background="@android:drawable/btn_zoom_up" android:layout_width="wrap_content" android:layout_height="wrap_content" /> diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index 5fa5f8d..899d109 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -586,7 +586,7 @@ <!-- There is no specific action associated with this editor, let the editor come up with its own if it can. Corresponds to - {@link android.view.inputmethod.EditorInfo#IME_ACTION_UNSPECIFIED}. --> + {@link android.view.inputmethod.EditorInfo#IME_NULL}. --> <flag name="actionUnspecified" value="0x00000000" /> <!-- This editor has no action associated with it. Corresponds to @@ -595,28 +595,38 @@ <!-- The action key performs a "go" operation to take the user to the target of the text they typed. Typically used, for example, when entering a URL. + Corresponds to {@link android.view.inputmethod.EditorInfo#IME_ACTION_GO}. --> <flag name="actionGo" value="0x00000002" /> <!-- The action key performs a "search" operation, taking the user to the results of searching for the text the have typed (in whatever context is appropriate). + Corresponds to {@link android.view.inputmethod.EditorInfo#IME_ACTION_SEARCH}. --> <flag name="actionSearch" value="0x00000003" /> <!-- The action key performs a "send" operation, delivering the text to its target. This is typically used when composing a message. + Corresponds to {@link android.view.inputmethod.EditorInfo#IME_ACTION_SEND}. --> <flag name="actionSend" value="0x00000004" /> <!-- The action key performs a "next" operation, taking the user to the next field that will accept text. + Corresponds to {@link android.view.inputmethod.EditorInfo#IME_ACTION_NEXT}. --> <flag name="actionNext" value="0x00000005" /> + <!-- The action key performs a "done" + operation, closing the soft input method. + Corresponds to + {@link android.view.inputmethod.EditorInfo#IME_ACTION_DONE}. --> + <flag name="actionDone" value="0x00000006" /> <!-- Used in conjunction with a custom action, this indicates that the action should not be available in-line as the same as a "enter" key. Typically this is because the action has such a significant impact or is not recoverable enough that accidentally hitting it should be avoided, such as sending a message. + <p>Corresponds to {@link android.view.inputmethod.EditorInfo#IME_FLAG_NO_ENTER_ACTION}. --> <flag name="flagNoEnterAction" value="0x40000000" /> </attr> @@ -3115,23 +3125,23 @@ </declare-styleable> <!-- =============================== --> - <!-- Gadget package class attributes --> + <!-- AppWidget package class attributes --> <!-- =============================== --> - <!-- Use <code>gadget-provider</code> as the root tag of the XML resource that - describes a gadget provider. See TODO android.gadget package + <!-- Use <code>appwidget-provider</code> as the root tag of the XML resource that + describes an AppWidget provider. See TODO android.appwidget package for more info. --> - <declare-styleable name="GadgetProviderInfo"> - <!-- Minimum width of the gadget. --> + <declare-styleable name="AppWidgetProviderInfo"> + <!-- Minimum width of the AppWidget. --> <attr name="minWidth"/> - <!-- Minimum height of the gadget. --> + <!-- Minimum height of the AppWidget. --> <attr name="minHeight"/> - <!-- Update period in milliseconds, or 0 if the gadget will update itself. --> + <!-- Update period in milliseconds, or 0 if the AppWidget will update itself. --> <attr name="updatePeriodMillis" format="integer" /> <!-- A resource id of a layout. --> <attr name="initialLayout" format="reference" /> - <!-- A class name in the gadget's package to be launched to configure. + <!-- A class name in the AppWidget's package to be launched to configure. If not supplied, then no activity will be launched. --> <attr name="configure" format="string" /> </declare-styleable> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index cb63e17..761cedd 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -1184,7 +1184,7 @@ <!-- Title of the unlock screen that uses your Google login and password --> <string name="lockscreen_glogin_too_many_attempts">Too many pattern attempts!</string> <!-- In the unlock screen, message telling the user that they need to use their Google login and password to unlock the phone --> - <string name="lockscreen_glogin_instructions">To unlock,\nsign in with your Google account</string> + <string name="lockscreen_glogin_instructions">To unlock, sign in with your Google account</string> <!-- Hint caption for the username field when unlocking the phone using login and password --> <string name="lockscreen_glogin_username_hint">Username (email)</string> <!-- Hint caption for the password field when unlocking the phone using login and password --> diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml index 54eba62..ff8f8c2 100644 --- a/core/res/res/values/styles.xml +++ b/core/res/res/values/styles.xml @@ -144,6 +144,13 @@ <item name="windowExitAnimation">@anim/search_bar_exit</item> </style> + <!-- Window animations that are applied to the zoom buttons overlay window. + {@hide Pending API council approval} --> + <style name="Animation.ZoomButtons"> + <item name="windowEnterAnimation">@anim/fade_in</item> + <item name="windowExitAnimation">@anim/fade_out</item> + </style> + <!-- Status Bar Styles --> <style name="TextAppearance.StatusBarTitle"> diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java index 6fac969..81980d9 100644 --- a/graphics/java/android/graphics/Paint.java +++ b/graphics/java/android/graphics/Paint.java @@ -109,13 +109,13 @@ public class Paint { */ BUTT (0), /** - * The stroke projects out as a square, with the center at the end - * of the path. + * The stroke projects out as a semicircle, with the center at the + * end of the path. */ ROUND (1), /** - * The stroke projects out as a semicircle, with the center at the - * end of the path. + * The stroke projects out as a square, with the center at the end + * of the path. */ SQUARE (2); diff --git a/include/media/PVPlayer.h b/include/media/PVPlayer.h index 6d98852..8122df6 100644 --- a/include/media/PVPlayer.h +++ b/include/media/PVPlayer.h @@ -53,8 +53,8 @@ public: virtual status_t setLooping(int loop); virtual player_type playerType() { return PV_PLAYER; } - // make available to PlayerDriver - void sendEvent(int msg, int ext1=0, int ext2=0) { MediaPlayerBase::sendEvent(msg, ext1, ext2); } + // make available to PlayerDriver + void sendEvent(int msg, int ext1=0, int ext2=0) { MediaPlayerBase::sendEvent(msg, ext1, ext2); } private: static void do_nothing(status_t s, void *cookie, bool cancelled) { } diff --git a/include/media/mediaplayer.h b/include/media/mediaplayer.h index 7288445..58906d1 100644 --- a/include/media/mediaplayer.h +++ b/include/media/mediaplayer.h @@ -34,11 +34,72 @@ enum media_event_type { MEDIA_SEEK_COMPLETE = 4, MEDIA_SET_VIDEO_SIZE = 5, MEDIA_ERROR = 100, + MEDIA_INFO = 200, }; -typedef int media_error_type; -const media_error_type MEDIA_ERROR_UNKNOWN = 1; -const media_error_type MEDIA_ERROR_SERVER_DIED = 100; +// Generic error codes for the media player framework. Errors are fatal, the +// playback must abort. +// +// Errors are communicated back to the client using the +// MediaPlayerListener::notify method defined below. +// In this situation, 'notify' is invoked with the following: +// 'msg' is set to MEDIA_ERROR. +// 'ext1' should be a value from the enum media_error_type. +// 'ext2' contains an implementation dependant error code to provide +// more details. Should default to 0 when not used. +// +// The codes are distributed as follow: +// 0xx: Reserved +// 1xx: Android Player errors. Something went wrong inside the MediaPlayer. +// 2xx: Media errors (e.g Codec not supported). There is a problem with the +// media itself. +// 3xx: Runtime errors. Some extraordinary condition arose making the playback +// impossible. +// +enum media_error_type { + // 0xx + MEDIA_ERROR_UNKNOWN = 1, + // 1xx + MEDIA_ERROR_SERVER_DIED = 100, + // 2xx + MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK = 200, + // 3xx +}; + + +// Info and warning codes for the media player framework. These are non fatal, +// the playback is going on but there might be some user visible issues. +// +// Info and warning messages are communicated back to the client using the +// MediaPlayerListener::notify method defined below. In this situation, +// 'notify' is invoked with the following: +// 'msg' is set to MEDIA_INFO. +// 'ext1' should be a value from the enum media_info_type. +// 'ext2' contains an implementation dependant error code to provide +// more details. Should default to 0 when not used. +// +// The codes are distributed as follow: +// 0xx: Reserved +// 7xx: Android Player info/warning (e.g player lagging behind.) +// 8xx: Media info/warning (e.g media badly interleaved.) +// +enum media_info_type { + // 0xx + MEDIA_INFO_UNKNOWN = 1, + // 7xx + // The video is too complex for the decoder: it can't decode frames fast + // enough. Possibly only the audio plays fine at this stage. + MEDIA_INFO_VIDEO_TRACK_LAGGING = 700, + // 8xx + // Bad interleaving means that a media has been improperly interleaved or not + // interleaved at all, e.g has all the video samples first then all the audio + // ones. Video is playing but a lot of disk seek may be happening. + MEDIA_INFO_BAD_INTERLEAVING = 800, + // The media is not seekable (e.g live stream). + MEDIA_INFO_NOT_SEEKABLE = 801, +}; + + enum media_player_states { MEDIA_PLAYER_STATE_ERROR = 0, @@ -141,4 +202,3 @@ private: }; // namespace android #endif // ANDROID_MEDIAPLAYER_H - diff --git a/libs/audioflinger/AudioFlinger.cpp b/libs/audioflinger/AudioFlinger.cpp index 440778d..57a53bd 100644 --- a/libs/audioflinger/AudioFlinger.cpp +++ b/libs/audioflinger/AudioFlinger.cpp @@ -119,7 +119,8 @@ static bool settingsAllowed() { AudioFlinger::AudioFlinger() : BnAudioFlinger(), mAudioHardware(0), mA2dpAudioInterface(0), mA2dpEnabled(false), mNotifyA2dpChange(false), - mForcedSpeakerCount(0), mForcedRoute(0), mRouteRestoreTime(0), mMusicMuteSaved(false) + mForcedSpeakerCount(0), mA2dpDisableCount(0), mA2dpSuppressed(false), mForcedRoute(0), + mRouteRestoreTime(0), mMusicMuteSaved(false) { mHardwareStatus = AUDIO_HW_IDLE; mAudioHardware = AudioHardwareInterface::create(); @@ -166,7 +167,7 @@ AudioFlinger::AudioFlinger() setMasterMute(false); // Start record thread - mAudioRecordThread = new AudioRecordThread(mAudioHardware); + mAudioRecordThread = new AudioRecordThread(mAudioHardware, this); if (mAudioRecordThread != 0) { mAudioRecordThread->run("AudioRecordThread", PRIORITY_URGENT_AUDIO); } @@ -242,6 +243,12 @@ bool AudioFlinger::streamForcedToSpeaker(int streamType) streamType == AudioSystem::NOTIFICATION); } +bool AudioFlinger::streamDisablesA2dp(int streamType) +{ + return (streamType == AudioSystem::VOICE_CALL || + streamType == AudioSystem::BLUETOOTH_SCO); +} + status_t AudioFlinger::dumpClients(int fd, const Vector<String16>& args) { const size_t SIZE = 256; @@ -482,7 +489,11 @@ status_t AudioFlinger::setRouting(int mode, uint32_t routes, uint32_t mask) if (routes & AudioSystem::ROUTE_BLUETOOTH_A2DP) { enableA2dp = true; } - setA2dpEnabled_l(enableA2dp); + if (mA2dpDisableCount > 0) { + mA2dpSuppressed = enableA2dp; + } else { + setA2dpEnabled_l(enableA2dp); + } LOGV("setOutput done\n"); } #endif @@ -798,9 +809,9 @@ void AudioFlinger::handleForcedSpeakerRoute(int command) if (--mForcedSpeakerCount == 0) { mRouteRestoreTime = systemTime() + milliseconds(kStopSleepTime/1000); } - LOGV("mForcedSpeakerCount decremented to %d", mForcedSpeakerCount); + LOGV("mForcedSpeakerCount decremented to %d", mForcedSpeakerCount); } else { - LOGE("mForcedSpeakerCount is already zero"); + LOGE("mForcedSpeakerCount is already zero"); } } break; @@ -825,6 +836,41 @@ void AudioFlinger::handleForcedSpeakerRoute(int command) } } +#ifdef WITH_A2DP +void AudioFlinger::handleStreamDisablesA2dp(int command) +{ + switch(command) { + case ACTIVE_TRACK_ADDED: + { + AutoMutex lock(mHardwareLock); + if (mA2dpDisableCount++ == 0) { + if (mA2dpEnabled) { + setA2dpEnabled_l(false); + mA2dpSuppressed = true; + } + } + LOGV("mA2dpDisableCount incremented to %d", mA2dpDisableCount); + } + break; + case ACTIVE_TRACK_REMOVED: + { + AutoMutex lock(mHardwareLock); + if (mA2dpDisableCount > 0){ + if (--mA2dpDisableCount == 0) { + if (mA2dpSuppressed) { + setA2dpEnabled_l(true); + mA2dpSuppressed = false; + } + } + LOGV("mA2dpDisableCount decremented to %d", mA2dpDisableCount); + } else { + LOGE("mA2dpDisableCount is already zero"); + } + } + break; + } +} +#endif // ---------------------------------------------------------------------------- @@ -1455,6 +1501,11 @@ void AudioFlinger::MixerThread::addActiveTrack_l(const wp<Track>& t) if (streamForcedToSpeaker(track->type())) { mAudioFlinger->handleForcedSpeakerRoute(ACTIVE_TRACK_ADDED); } +#ifdef WITH_A2DP + if (streamDisablesA2dp(track->type())) { + mAudioFlinger->handleStreamDisablesA2dp(ACTIVE_TRACK_ADDED); + } +#endif } } @@ -1472,6 +1523,11 @@ void AudioFlinger::MixerThread::removeActiveTrack_l(const wp<Track>& t) if (streamForcedToSpeaker(track->type())) { mAudioFlinger->handleForcedSpeakerRoute(ACTIVE_TRACK_REMOVED); } +#ifdef WITH_A2DP + if (streamDisablesA2dp(track->type())) { + mAudioFlinger->handleStreamDisablesA2dp(ACTIVE_TRACK_REMOVED); + } +#endif } } @@ -2311,8 +2367,10 @@ status_t AudioFlinger::RecordHandle::onTransact( // ---------------------------------------------------------------------------- -AudioFlinger::AudioRecordThread::AudioRecordThread(AudioHardwareInterface* audioHardware) : +AudioFlinger::AudioRecordThread::AudioRecordThread(AudioHardwareInterface* audioHardware, + const sp<AudioFlinger>& audioFlinger) : mAudioHardware(audioHardware), + mAudioFlinger(audioFlinger), mActive(false) { } @@ -2417,6 +2475,12 @@ status_t AudioFlinger::AudioRecordThread::start(MixerThread::RecordTrack* record mRecordTrack = recordTrack; +#ifdef WITH_A2DP + if (streamDisablesA2dp(recordTrack->type())) { + mAudioFlinger->handleStreamDisablesA2dp(ACTIVE_TRACK_ADDED); + } +#endif + // signal thread to start LOGV("Signal record thread"); mWaitWorkCV.signal(); @@ -2429,6 +2493,11 @@ void AudioFlinger::AudioRecordThread::stop(MixerThread::RecordTrack* recordTrack LOGV("AudioRecordThread::stop"); AutoMutex lock(&mLock); if (mActive && (recordTrack == mRecordTrack.get())) { +#ifdef WITH_A2DP + if (streamDisablesA2dp(recordTrack->type())) { + mAudioFlinger->handleStreamDisablesA2dp(ACTIVE_TRACK_REMOVED); + } +#endif mActive = false; mStopped.wait(mLock); } diff --git a/libs/audioflinger/AudioFlinger.h b/libs/audioflinger/AudioFlinger.h index c505336..596e7f3 100644 --- a/libs/audioflinger/AudioFlinger.h +++ b/libs/audioflinger/AudioFlinger.h @@ -165,6 +165,7 @@ private: void checkA2dpEnabledChange_l(); #endif static bool streamForcedToSpeaker(int streamType); + static bool streamDisablesA2dp(int streamType); // Management of forced route to speaker for certain track types. enum force_speaker_command { @@ -174,6 +175,9 @@ private: FORCE_ROUTE_RESTORE }; void handleForcedSpeakerRoute(int command); +#ifdef WITH_A2DP + void handleStreamDisablesA2dp(int command); +#endif // Internal dump utilites. status_t dumpPermissionDenial(int fd, const Vector<String16>& args); @@ -576,7 +580,7 @@ private: class AudioRecordThread : public Thread { public: - AudioRecordThread(AudioHardwareInterface* audioHardware); + AudioRecordThread(AudioHardwareInterface* audioHardware, const sp<AudioFlinger>& audioFlinger); virtual ~AudioRecordThread(); virtual bool threadLoop(); virtual status_t readyToRun() { return NO_ERROR; } @@ -590,6 +594,7 @@ private: private: AudioRecordThread(); AudioHardwareInterface *mAudioHardware; + sp<AudioFlinger> mAudioFlinger; sp<MixerThread::RecordTrack> mRecordTrack; Mutex mLock; Condition mWaitWorkCV; @@ -620,6 +625,10 @@ private: mutable int mHardwareStatus; SortedVector< wp<IBinder> > mNotificationClients; int mForcedSpeakerCount; + int mA2dpDisableCount; + + // true if A2DP should resume when mA2dpDisableCount returns to zero + bool mA2dpSuppressed; uint32_t mSavedRoute; uint32_t mForcedRoute; nsecs_t mRouteRestoreTime; diff --git a/libs/surfaceflinger/SurfaceFlinger.cpp b/libs/surfaceflinger/SurfaceFlinger.cpp index 900282a..d915a84 100644 --- a/libs/surfaceflinger/SurfaceFlinger.cpp +++ b/libs/surfaceflinger/SurfaceFlinger.cpp @@ -179,6 +179,7 @@ SurfaceFlinger::SurfaceFlinger() mDeferReleaseConsole(false), mFreezeDisplay(false), mFreezeCount(0), + mFreezeDisplayTime(0), mDebugRegion(0), mDebugCpu(0), mDebugFps(0), @@ -467,16 +468,24 @@ void SurfaceFlinger::waitForEvent() // wait for something to do if (UNLIKELY(isFrozen())) { // wait 5 seconds - int err = mSyncObject.wait(ms2ns(5000)); + const nsecs_t freezeDisplayTimeout = ms2ns(5000); + const nsecs_t now = systemTime(); + if (mFreezeDisplayTime == 0) { + mFreezeDisplayTime = now; + } + nsecs_t waitTime = freezeDisplayTimeout - (now - mFreezeDisplayTime); + int err = (waitTime > 0) ? mSyncObject.wait(waitTime) : TIMED_OUT; if (err != NO_ERROR) { if (isFrozen()) { // we timed out and are still frozen LOGW("timeout expired mFreezeDisplay=%d, mFreezeCount=%d", mFreezeDisplay, mFreezeCount); mFreezeCount = 0; + mFreezeDisplay = false; } } } else { + mFreezeDisplayTime = 0; mSyncObject.wait(); } } @@ -671,13 +680,6 @@ void SurfaceFlinger::handleTransaction(uint32_t transactionFlags) if (mCurrentState.freezeDisplay != mDrawingState.freezeDisplay) { // freezing or unfreezing the display -> trigger animation if needed mFreezeDisplay = mCurrentState.freezeDisplay; - const nsecs_t now = systemTime(); - if (mFreezeDisplay) { - mFreezeDisplayTime = now; - } else { - //LOGD("Screen was frozen for %llu us", - // ns2us(now-mFreezeDisplayTime)); - } } // some layers might have been removed, so diff --git a/libs/utils/String16.cpp b/libs/utils/String16.cpp index ae0ae1e..aef67f2 100644 --- a/libs/utils/String16.cpp +++ b/libs/utils/String16.cpp @@ -244,7 +244,6 @@ void terminate_string16() // --------------------------------------------------------------------------- -// Note: not dealing with generating surrogate pairs. static char16_t* allocFromUTF8(const char* in, size_t len) { if (len == 0) return getEmptyString(); @@ -255,7 +254,10 @@ static char16_t* allocFromUTF8(const char* in, size_t len) while (p < end) { chars++; - p += utf8_char_len(*p); + int utf8len = utf8_char_len(*p); + uint32_t codepoint = utf8_to_utf32((const uint8_t*)p, utf8len); + if (codepoint > 0xFFFF) chars++; // this will be a surrogate pair in utf16 + p += utf8len; } SharedBuffer* buf = SharedBuffer::alloc((chars+1)*sizeof(char16_t)); @@ -265,7 +267,19 @@ static char16_t* allocFromUTF8(const char* in, size_t len) char16_t* d = str; while (p < end) { size_t len = utf8_char_len(*p); - *d++ = (char16_t)utf8_to_utf32((const uint8_t*)p, len); + uint32_t codepoint = utf8_to_utf32((const uint8_t*)p, len); + + // Convert the UTF32 codepoint to one or more UTF16 codepoints + if (codepoint <= 0xFFFF) { + // Single UTF16 character + *d++ = (char16_t) codepoint; + } else { + // Multiple UTF16 characters with surrogates + codepoint = codepoint - 0x10000; + *d++ = (char16_t) ((codepoint >> 10) + 0xD800); + *d++ = (char16_t) ((codepoint & 0x3FF) + 0xDC00); + } + p += len; } *d = 0; diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java index 369af3b..202d0ae 100644 --- a/media/java/android/media/MediaPlayer.java +++ b/media/java/android/media/MediaPlayer.java @@ -839,6 +839,7 @@ public class MediaPlayer mOnCompletionListener = null; mOnSeekCompleteListener = null; mOnErrorListener = null; + mOnInfoListener = null; mOnVideoSizeChangedListener = null; _release(); } @@ -918,18 +919,7 @@ public class MediaPlayer private static final int MEDIA_SEEK_COMPLETE = 4; private static final int MEDIA_SET_VIDEO_SIZE = 5; private static final int MEDIA_ERROR = 100; - - // error codes from framework that indicate content issues - // contained in arg1 of error message - - // Seek not supported - live stream - private static final int ERROR_SEEK_NOT_SUPPORTED = 42; - - // A/V interleave exceeds the progressive streaming buffer - private static final int ERROR_CONTENT_IS_POORLY_INTERLEAVED = 43; - - // video decoder is falling behind - content is too complex - private static final int ERROR_VIDEO_TRACK_IS_FALLING_BEHIND = 44; + private static final int MEDIA_INFO = 200; private class EventHandler extends Handler { @@ -974,6 +964,8 @@ public class MediaPlayer return; case MEDIA_ERROR: + // For PV specific error values (msg.arg2) look in + // opencore/pvmi/pvmf/include/pvmf_return_codes.h Log.e(TAG, "Error (" + msg.arg1 + "," + msg.arg2 + ")"); boolean error_was_handled = false; if (mOnErrorListener != null) { @@ -984,6 +976,17 @@ public class MediaPlayer } stayAwake(false); return; + + case MEDIA_INFO: + // For PV specific code values (msg.arg2) look in + // opencore/pvmi/pvmf/include/pvmf_return_codes.h + Log.i(TAG, "Info (" + msg.arg1 + "," + msg.arg2 + ")"); + if (mOnInfoListener != null) { + mOnInfoListener.onInfo(mMediaPlayer, msg.arg1, msg.arg2); + } + // No real default action so far. + return; + case MEDIA_NOP: // interface test message - ignore break; @@ -1165,12 +1168,19 @@ public class MediaPlayer * @see android.media.MediaPlayer.OnErrorListener */ public static final int MEDIA_ERROR_UNKNOWN = 1; + /** Media server died. In this case, the application must release the * MediaPlayer object and instantiate a new one. * @see android.media.MediaPlayer.OnErrorListener */ public static final int MEDIA_ERROR_SERVER_DIED = 100; + /** The video is streamed and its container is not valid for progressive + * playback i.e the video's index (e.g moov atom) is not at the start of the + * file. + * @hide pending API council approval. Replace with @see tag after. + */ + public static final int MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK = 200; /** * Interface definition of a callback to be invoked when there @@ -1188,7 +1198,8 @@ public class MediaPlayer * <li>{@link #MEDIA_ERROR_UNKNOWN} * <li>{@link #MEDIA_ERROR_SERVER_DIED} * </ul> - * @param extra an extra code, specific to the error type + * @param extra an extra code, specific to the error. Typically + * implementation dependant. * @return True if the method handled the error, false if it didn't. * Returning false, or not having an OnErrorListener at all, will * cause the OnCompletionListener to be called. @@ -1200,12 +1211,83 @@ public class MediaPlayer * Register a callback to be invoked when an error has happened * during an asynchronous operation. * - * @param l the callback that will be run + * @param listener the callback that will be run */ - public void setOnErrorListener(OnErrorListener l) + public void setOnErrorListener(OnErrorListener listener) { - mOnErrorListener = l; + mOnErrorListener = listener; } private OnErrorListener mOnErrorListener; + + + /* Do not change these values without updating their counterparts + * in include/media/mediaplayer.h! + */ + /** Unspecified media player info. + * @see android.media.MediaPlayer.OnInfoListener + * @hide pending API council approval. + */ + public static final int MEDIA_INFO_UNKNOWN = 1; + + /** The video is too complex for the decoder: it can't decode frames fast + * enough. Possibly only the audio plays fine at this stage. + * @see android.media.MediaPlayer.OnInfoListener + * @hide pending API council approval. + */ + public static final int MEDIA_INFO_VIDEO_TRACK_LAGGING = 700; + + /** Bad interleaving means that a media has been improperly interleaved or + * not interleaved at all, e.g has all the video samples first then all the + * audio ones. Video is playing but a lot of disk seeks may be happening. + * @see android.media.MediaPlayer.OnInfoListener + * @hide pending API council approval. + */ + public static final int MEDIA_INFO_BAD_INTERLEAVING = 800; + + /** The media cannot be seeked (e.g live stream) + * @see android.media.MediaPlayer.OnInfoListener + * @hide pending API council approval. + */ + public static final int MEDIA_INFO_NOT_SEEKABLE = 801; + + /** + * Interface definition of a callback to be invoked to communicate some + * info and/or warning about the media or its playback. + * @hide pending API council approval. + */ + public interface OnInfoListener + { + /** + * Called to indicate an info or a warning. + * + * @param mp the MediaPlayer the info pertains to. + * @param what the type of info or warning. + * <ul> + * <li>{@link #MEDIA_INFO_UNKNOWN} + * <li>{@link #MEDIA_INFO_VIDEO_TRACK_LAGGING} + * <li>{@link #MEDIA_INFO_BAD_INTERLEAVING} + * <li>{@link #MEDIA_INFO_NOT_SEEKABLE} + * </ul> + * @param extra an extra code, specific to the info. Typically + * implementation dependant. + * @return True if the method handled the info, false if it didn't. + * Returning false, or not having an OnErrorListener at all, will + * cause the info to be discarded. + */ + boolean onInfo(MediaPlayer mp, int what, int extra); + } + + /** + * Register a callback to be invoked when an info/warning is available. + * + * @param listener the callback that will be run + * @hide pending API council approval. + */ + public void setOnInfoListener(OnInfoListener listener) + { + mOnInfoListener = listener; + } + + private OnInfoListener mOnInfoListener; } diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp index bd8579c..6b40412 100644 --- a/media/libmedia/mediaplayer.cpp +++ b/media/libmedia/mediaplayer.cpp @@ -215,6 +215,10 @@ status_t MediaPlayer::prepareAsync_l() return INVALID_OPERATION; } +// TODO: In case of error, prepareAsync provides the caller with 2 error codes, +// one defined in the Android framework and one provided by the implementation +// that generated the error. The sync version of prepare returns only 1 error +// code. status_t MediaPlayer::prepare() { LOGV("prepare"); @@ -512,7 +516,9 @@ void MediaPlayer::notify(int msg, int ext1, int ext2) } break; case MEDIA_ERROR: - // Always log errors + // Always log errors. + // ext1: Media framework error code. + // ext2: Implementation dependant error code. LOGE("error (%d, %d)", ext1, ext2); mCurrentState = MEDIA_PLAYER_STATE_ERROR; if (mPrepareSync) @@ -524,6 +530,11 @@ void MediaPlayer::notify(int msg, int ext1, int ext2) send = false; } break; + case MEDIA_INFO: + // ext1: Media framework error code. + // ext2: Implementation dependant error code. + LOGW("info/warning (%d, %d)", ext1, ext2); + break; case MEDIA_SEEK_COMPLETE: LOGV("Received seek complete"); if (mSeekPosition != mCurrentPosition) { diff --git a/media/libmedia/mediarecorder.cpp b/media/libmedia/mediarecorder.cpp index 5eba0ef..572b1e7 100644 --- a/media/libmedia/mediarecorder.cpp +++ b/media/libmedia/mediarecorder.cpp @@ -456,6 +456,11 @@ status_t MediaRecorder::stop() mCurrentState = MEDIA_RECORDER_ERROR; return ret; } + + // FIXME: + // stop and reset are semantically different. + // We treat them the same for now, and will change this in the future. + doCleanUp(); mCurrentState = MEDIA_RECORDER_IDLE; return ret; } diff --git a/services/java/com/android/server/GadgetService.java b/services/java/com/android/server/AppWidgetService.java index 0943778..de5d0ac 100644 --- a/services/java/com/android/server/GadgetService.java +++ b/services/java/com/android/server/AppWidgetService.java @@ -18,6 +18,8 @@ package com.android.server; import android.app.AlarmManager; import android.app.PendingIntent; +import android.appwidget.AppWidgetManager; +import android.appwidget.AppWidgetProviderInfo; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; @@ -30,8 +32,6 @@ import android.content.pm.ResolveInfo; import android.content.pm.PackageItemInfo; import android.content.res.TypedArray; import android.content.res.XmlResourceParser; -import android.gadget.GadgetManager; -import android.gadget.GadgetProviderInfo; import android.net.Uri; import android.os.Binder; import android.os.Bundle; @@ -53,8 +53,8 @@ import java.util.List; import java.util.HashMap; import java.util.HashSet; -import com.android.internal.gadget.IGadgetService; -import com.android.internal.gadget.IGadgetHost; +import com.android.internal.appwidget.IAppWidgetService; +import com.android.internal.appwidget.IAppWidgetHost; import com.android.internal.util.XmlUtils; import com.android.internal.util.FastXmlSerializer; @@ -62,11 +62,11 @@ import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; -class GadgetService extends IGadgetService.Stub +class AppWidgetService extends IAppWidgetService.Stub { - private static final String TAG = "GadgetService"; + private static final String TAG = "AppWidgetService"; - private static final String SETTINGS_FILENAME = "gadgets.xml"; + private static final String SETTINGS_FILENAME = "appwidgets.xml"; private static final String SETTINGS_TMP_FILENAME = SETTINGS_FILENAME + ".tmp"; /* @@ -77,8 +77,8 @@ class GadgetService extends IGadgetService.Stub static class Provider { int uid; - GadgetProviderInfo info; - ArrayList<GadgetId> instances = new ArrayList(); + AppWidgetProviderInfo info; + ArrayList<AppWidgetId> instances = new ArrayList(); PendingIntent broadcast; boolean zombie; // if we're in safe mode, don't prune this just because nobody references it @@ -89,15 +89,15 @@ class GadgetService extends IGadgetService.Stub int uid; int hostId; String packageName; - ArrayList<GadgetId> instances = new ArrayList(); - IGadgetHost callbacks; + ArrayList<AppWidgetId> instances = new ArrayList(); + IAppWidgetHost callbacks; boolean zombie; // if we're in safe mode, don't prune this just because nobody references it int tag; // for use while saving state (the index) } - static class GadgetId { - int gadgetId; + static class AppWidgetId { + int appWidgetId; Provider provider; RemoteViews views; Host host; @@ -107,12 +107,12 @@ class GadgetService extends IGadgetService.Stub PackageManager mPackageManager; AlarmManager mAlarmManager; ArrayList<Provider> mInstalledProviders = new ArrayList(); - int mNextGadgetId = GadgetManager.INVALID_GADGET_ID + 1; - ArrayList<GadgetId> mGadgetIds = new ArrayList(); + int mNextAppWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID + 1; + ArrayList<AppWidgetId> mAppWidgetIds = new ArrayList(); ArrayList<Host> mHosts = new ArrayList(); boolean mSafeMode; - GadgetService(Context context) { + AppWidgetService(Context context) { mContext = context; mPackageManager = context.getPackageManager(); mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE); @@ -121,7 +121,7 @@ class GadgetService extends IGadgetService.Stub public void systemReady(boolean safeMode) { mSafeMode = safeMode; - loadGadgetList(); + loadAppWidgetList(); loadStateLocked(); // Register for the boot completed broadcast, so we can send the @@ -149,23 +149,23 @@ class GadgetService extends IGadgetService.Stub return; } - synchronized (mGadgetIds) { + synchronized (mAppWidgetIds) { int N = mInstalledProviders.size(); pw.println("Providers: (size=" + N + ")"); for (int i=0; i<N; i++) { Provider p = mInstalledProviders.get(i); - GadgetProviderInfo info = p.info; + AppWidgetProviderInfo info = p.info; pw.println(" [" + i + "] provder=" + info.provider + " min=(" + info.minWidth + "x" + info.minHeight + ")" + " updatePeriodMillis=" + info.updatePeriodMillis + " initialLayout=" + info.initialLayout + " zombie=" + p.zombie); } - N = mGadgetIds.size(); - pw.println("GadgetIds: (size=" + N + ")"); + N = mAppWidgetIds.size(); + pw.println("AppWidgetIds: (size=" + N + ")"); for (int i=0; i<N; i++) { - GadgetId id = mGadgetIds.get(i); - pw.println(" [" + i + "] gadgetId=" + id.gadgetId + AppWidgetId id = mAppWidgetIds.get(i); + pw.println(" [" + i + "] appWidgetId=" + id.appWidgetId + " host=" + id.host.hostId + "/" + id.host.packageName + " provider=" + (id.provider == null ? "null" : id.provider.info.provider) + " host.callbacks=" + (id.host != null ? id.host.callbacks : "(no host)") @@ -183,38 +183,38 @@ class GadgetService extends IGadgetService.Stub } } - public int allocateGadgetId(String packageName, int hostId) { + public int allocateAppWidgetId(String packageName, int hostId) { int callingUid = enforceCallingUid(packageName); - synchronized (mGadgetIds) { - int gadgetId = mNextGadgetId++; + synchronized (mAppWidgetIds) { + int appWidgetId = mNextAppWidgetId++; Host host = lookupOrAddHostLocked(callingUid, packageName, hostId); - GadgetId id = new GadgetId(); - id.gadgetId = gadgetId; + AppWidgetId id = new AppWidgetId(); + id.appWidgetId = appWidgetId; id.host = host; host.instances.add(id); - mGadgetIds.add(id); + mAppWidgetIds.add(id); saveStateLocked(); - return gadgetId; + return appWidgetId; } } - public void deleteGadgetId(int gadgetId) { - synchronized (mGadgetIds) { - GadgetId id = lookupGadgetIdLocked(gadgetId); + public void deleteAppWidgetId(int appWidgetId) { + synchronized (mAppWidgetIds) { + AppWidgetId id = lookupAppWidgetIdLocked(appWidgetId); if (id != null) { - deleteGadgetLocked(id); + deleteAppWidgetLocked(id); saveStateLocked(); } } } public void deleteHost(int hostId) { - synchronized (mGadgetIds) { + synchronized (mAppWidgetIds) { int callingUid = getCallingUid(); Host host = lookupHostLocked(callingUid, hostId); if (host != null) { @@ -225,7 +225,7 @@ class GadgetService extends IGadgetService.Stub } public void deleteAllHosts() { - synchronized (mGadgetIds) { + synchronized (mAppWidgetIds) { int callingUid = getCallingUid(); final int N = mHosts.size(); boolean changed = false; @@ -245,8 +245,8 @@ class GadgetService extends IGadgetService.Stub void deleteHostLocked(Host host) { final int N = host.instances.size(); for (int i=N-1; i>=0; i--) { - GadgetId id = host.instances.get(i); - deleteGadgetLocked(id); + AppWidgetId id = host.instances.get(i); + deleteAppWidgetLocked(id); } host.instances.clear(); mHosts.remove(host); @@ -254,28 +254,28 @@ class GadgetService extends IGadgetService.Stub host.callbacks = null; } - void deleteGadgetLocked(GadgetId id) { + void deleteAppWidgetLocked(AppWidgetId id) { Host host = id.host; host.instances.remove(id); pruneHostLocked(host); - mGadgetIds.remove(id); + mAppWidgetIds.remove(id); Provider p = id.provider; if (p != null) { p.instances.remove(id); if (!p.zombie) { - // send the broacast saying that this gadgetId has been deleted - Intent intent = new Intent(GadgetManager.ACTION_GADGET_DELETED); + // send the broacast saying that this appWidgetId has been deleted + Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_DELETED); intent.setComponent(p.info.provider); - intent.putExtra(GadgetManager.EXTRA_GADGET_ID, id.gadgetId); + intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, id.appWidgetId); mContext.sendBroadcast(intent); if (p.instances.size() == 0) { // cancel the future updates cancelBroadcasts(p); // send the broacast saying that the provider is not in use any more - intent = new Intent(GadgetManager.ACTION_GADGET_DISABLED); + intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_DISABLED); intent.setComponent(p.info.provider); mContext.sendBroadcast(intent); } @@ -296,21 +296,21 @@ class GadgetService extends IGadgetService.Stub } } - public void bindGadgetId(int gadgetId, ComponentName provider) { - mContext.enforceCallingPermission(android.Manifest.permission.BIND_GADGET, - "bindGagetId gadgetId=" + gadgetId + " provider=" + provider); - synchronized (mGadgetIds) { - GadgetId id = lookupGadgetIdLocked(gadgetId); + public void bindAppWidgetId(int appWidgetId, ComponentName provider) { + mContext.enforceCallingPermission(android.Manifest.permission.BIND_APPWIDGET, + "bindGagetId appWidgetId=" + appWidgetId + " provider=" + provider); + synchronized (mAppWidgetIds) { + AppWidgetId id = lookupAppWidgetIdLocked(appWidgetId); if (id == null) { - throw new IllegalArgumentException("bad gadgetId"); + throw new IllegalArgumentException("bad appWidgetId"); } if (id.provider != null) { - throw new IllegalArgumentException("gadgetId " + gadgetId + " already bound to " + throw new IllegalArgumentException("appWidgetId " + appWidgetId + " already bound to " + id.provider.info.provider); } Provider p = lookupProviderLocked(provider); if (p == null) { - throw new IllegalArgumentException("not a gadget provider: " + provider); + throw new IllegalArgumentException("not a appwidget provider: " + provider); } if (p.zombie) { throw new IllegalArgumentException("can't bind to a 3rd party provider in" @@ -325,21 +325,21 @@ class GadgetService extends IGadgetService.Stub sendEnableIntentLocked(p); } - // send an update now -- We need this update now, and just for this gadgetId. + // send an update now -- We need this update now, and just for this appWidgetId. // It's less critical when the next one happens, so when we schdule the next one, // we add updatePeriodMillis to its start time. That time will have some slop, // but that's okay. - sendUpdateIntentLocked(p, new int[] { gadgetId }); + sendUpdateIntentLocked(p, new int[] { appWidgetId }); // schedule the future updates - registerForBroadcastsLocked(p, getGadgetIds(p)); + registerForBroadcastsLocked(p, getAppWidgetIds(p)); saveStateLocked(); } } - public GadgetProviderInfo getGadgetInfo(int gadgetId) { - synchronized (mGadgetIds) { - GadgetId id = lookupGadgetIdLocked(gadgetId); + public AppWidgetProviderInfo getAppWidgetInfo(int appWidgetId) { + synchronized (mAppWidgetIds) { + AppWidgetId id = lookupAppWidgetIdLocked(appWidgetId); if (id != null && id.provider != null && !id.provider.zombie) { return id.provider.info; } @@ -347,9 +347,9 @@ class GadgetService extends IGadgetService.Stub } } - public RemoteViews getGadgetViews(int gadgetId) { - synchronized (mGadgetIds) { - GadgetId id = lookupGadgetIdLocked(gadgetId); + public RemoteViews getAppWidgetViews(int appWidgetId) { + synchronized (mAppWidgetIds) { + AppWidgetId id = lookupAppWidgetIdLocked(appWidgetId); if (id != null) { return id.views; } @@ -357,10 +357,10 @@ class GadgetService extends IGadgetService.Stub } } - public List<GadgetProviderInfo> getInstalledProviders() { - synchronized (mGadgetIds) { + public List<AppWidgetProviderInfo> getInstalledProviders() { + synchronized (mAppWidgetIds) { final int N = mInstalledProviders.size(); - ArrayList<GadgetProviderInfo> result = new ArrayList(N); + ArrayList<AppWidgetProviderInfo> result = new ArrayList(N); for (int i=0; i<N; i++) { Provider p = mInstalledProviders.get(i); if (!p.zombie) { @@ -371,43 +371,43 @@ class GadgetService extends IGadgetService.Stub } } - public void updateGadgetIds(int[] gadgetIds, RemoteViews views) { - if (gadgetIds == null) { + public void updateAppWidgetIds(int[] appWidgetIds, RemoteViews views) { + if (appWidgetIds == null) { return; } - if (gadgetIds.length == 0) { + if (appWidgetIds.length == 0) { return; } - final int N = gadgetIds.length; + final int N = appWidgetIds.length; - synchronized (mGadgetIds) { + synchronized (mAppWidgetIds) { for (int i=0; i<N; i++) { - GadgetId id = lookupGadgetIdLocked(gadgetIds[i]); - updateGadgetInstanceLocked(id, views); + AppWidgetId id = lookupAppWidgetIdLocked(appWidgetIds[i]); + updateAppWidgetInstanceLocked(id, views); } } } - public void updateGadgetProvider(ComponentName provider, RemoteViews views) { - synchronized (mGadgetIds) { + public void updateAppWidgetProvider(ComponentName provider, RemoteViews views) { + synchronized (mAppWidgetIds) { Provider p = lookupProviderLocked(provider); if (p == null) { - Log.w(TAG, "updateGadget: provider doesn't exist: " + provider); + Log.w(TAG, "updateAppWidgetProvider: provider doesn't exist: " + provider); return; } - ArrayList<GadgetId> instances = p.instances; + ArrayList<AppWidgetId> instances = p.instances; final int N = instances.size(); for (int i=0; i<N; i++) { - GadgetId id = instances.get(i); - updateGadgetInstanceLocked(id, views); + AppWidgetId id = instances.get(i); + updateAppWidgetInstanceLocked(id, views); } } } - void updateGadgetInstanceLocked(GadgetId id, RemoteViews views) { - // allow for stale gadgetIds and other badness - // lookup also checks that the calling process can access the gadget id - // drop unbound gadget ids (shouldn't be possible under normal circumstances) + void updateAppWidgetInstanceLocked(AppWidgetId id, RemoteViews views) { + // allow for stale appWidgetIds and other badness + // lookup also checks that the calling process can access the appWidgetId + // drop unbound appWidgetIds (shouldn't be possible under normal circumstances) if (id != null && id.provider != null && !id.provider.zombie && !id.host.zombie) { id.views = views; @@ -415,7 +415,7 @@ class GadgetService extends IGadgetService.Stub if (id.host.callbacks != null) { try { // the lock is held, but this is a oneway call - id.host.callbacks.updateGadget(id.gadgetId, views); + id.host.callbacks.updateAppWidget(id.appWidgetId, views); } catch (RemoteException e) { // It failed; remove the callback. No need to prune because // we know that this host is still referenced by this instance. @@ -425,21 +425,21 @@ class GadgetService extends IGadgetService.Stub } } - public int[] startListening(IGadgetHost callbacks, String packageName, int hostId, + public int[] startListening(IAppWidgetHost callbacks, String packageName, int hostId, List<RemoteViews> updatedViews) { int callingUid = enforceCallingUid(packageName); - synchronized (mGadgetIds) { + synchronized (mAppWidgetIds) { Host host = lookupOrAddHostLocked(callingUid, packageName, hostId); host.callbacks = callbacks; updatedViews.clear(); - ArrayList<GadgetId> instances = host.instances; + ArrayList<AppWidgetId> instances = host.instances; int N = instances.size(); int[] updatedIds = new int[N]; for (int i=0; i<N; i++) { - GadgetId id = instances.get(i); - updatedIds[i] = id.gadgetId; + AppWidgetId id = instances.get(i); + updatedIds[i] = id.appWidgetId; updatedViews.add(id.views); } return updatedIds; @@ -447,37 +447,37 @@ class GadgetService extends IGadgetService.Stub } public void stopListening(int hostId) { - synchronized (mGadgetIds) { + synchronized (mAppWidgetIds) { Host host = lookupHostLocked(getCallingUid(), hostId); host.callbacks = null; pruneHostLocked(host); } } - boolean canAccessGadgetId(GadgetId id, int callingUid) { + boolean canAccessAppWidgetId(AppWidgetId id, int callingUid) { if (id.host.uid == callingUid) { - // Apps hosting the gadget have access to it. + // Apps hosting the AppWidget have access to it. return true; } if (id.provider != null && id.provider.uid == callingUid) { - // Apps providing the gadget have access to it (if the gadgetId has been bound) + // Apps providing the AppWidget have access to it (if the appWidgetId has been bound) return true; } - if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.BIND_GADGET) + if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.BIND_APPWIDGET) == PackageManager.PERMISSION_GRANTED) { - // Apps that can bind have access to all gadgetIds. + // Apps that can bind have access to all appWidgetIds. return true; } // Nobody else can access it. return false; } - GadgetId lookupGadgetIdLocked(int gadgetId) { + AppWidgetId lookupAppWidgetIdLocked(int appWidgetId) { int callingUid = getCallingUid(); - final int N = mGadgetIds.size(); + final int N = mAppWidgetIds.size(); for (int i=0; i<N; i++) { - GadgetId id = mGadgetIds.get(i); - if (id.gadgetId == gadgetId && canAccessGadgetId(id, callingUid)) { + AppWidgetId id = mAppWidgetIds.get(i); + if (id.appWidgetId == appWidgetId && canAccessAppWidgetId(id, callingUid)) { return id; } } @@ -528,10 +528,10 @@ class GadgetService extends IGadgetService.Stub } } - void loadGadgetList() { + void loadAppWidgetList() { PackageManager pm = mPackageManager; - Intent intent = new Intent(GadgetManager.ACTION_GADGET_UPDATE); + Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE); List<ResolveInfo> broadcastReceivers = pm.queryBroadcastReceivers(intent, PackageManager.GET_META_DATA); @@ -556,14 +556,14 @@ class GadgetService extends IGadgetService.Stub void removeProviderLocked(int index, Provider p) { int N = p.instances.size(); for (int i=0; i<N; i++) { - GadgetId id = p.instances.get(i); + AppWidgetId id = p.instances.get(i); // Call back with empty RemoteViews - updateGadgetInstanceLocked(id, null); + updateAppWidgetInstanceLocked(id, null); // Stop telling the host about updates for this from now on cancelBroadcasts(p); - // clear out references to this gadgetID + // clear out references to this appWidgetId id.host.instances.remove(id); - mGadgetIds.remove(id); + mAppWidgetIds.remove(id); id.provider = null; pruneHostLocked(id.host); id.host = null; @@ -575,29 +575,29 @@ class GadgetService extends IGadgetService.Stub } void sendEnableIntentLocked(Provider p) { - Intent intent = new Intent(GadgetManager.ACTION_GADGET_ENABLED); + Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_ENABLED); intent.setComponent(p.info.provider); mContext.sendBroadcast(intent); } - void sendUpdateIntentLocked(Provider p, int[] gadgetIds) { - if (gadgetIds != null && gadgetIds.length > 0) { - Intent intent = new Intent(GadgetManager.ACTION_GADGET_UPDATE); - intent.putExtra(GadgetManager.EXTRA_GADGET_IDS, gadgetIds); + void sendUpdateIntentLocked(Provider p, int[] appWidgetIds) { + if (appWidgetIds != null && appWidgetIds.length > 0) { + Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE); + intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds); intent.setComponent(p.info.provider); mContext.sendBroadcast(intent); } } - void registerForBroadcastsLocked(Provider p, int[] gadgetIds) { + void registerForBroadcastsLocked(Provider p, int[] appWidgetIds) { if (p.info.updatePeriodMillis > 0) { // if this is the first instance, set the alarm. otherwise, // rely on the fact that we've already set it and that // PendingIntent.getBroadcast will update the extras. boolean alreadyRegistered = p.broadcast != null; int instancesSize = p.instances.size(); - Intent intent = new Intent(GadgetManager.ACTION_GADGET_UPDATE); - intent.putExtra(GadgetManager.EXTRA_GADGET_IDS, gadgetIds); + Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE); + intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds); intent.setComponent(p.info.provider); long token = Binder.clearCallingIdentity(); try { @@ -614,20 +614,20 @@ class GadgetService extends IGadgetService.Stub } } - static int[] getGadgetIds(Provider p) { + static int[] getAppWidgetIds(Provider p) { int instancesSize = p.instances.size(); - int gadgetIds[] = new int[instancesSize]; + int appWidgetIds[] = new int[instancesSize]; for (int i=0; i<instancesSize; i++) { - gadgetIds[i] = p.instances.get(i).gadgetId; + appWidgetIds[i] = p.instances.get(i).appWidgetId; } - return gadgetIds; + return appWidgetIds; } - public int[] getGadgetIds(ComponentName provider) { - synchronized (mGadgetIds) { + public int[] getAppWidgetIds(ComponentName provider) { + synchronized (mAppWidgetIds) { Provider p = lookupProviderLocked(provider); if (p != null && getCallingUid() == p.uid) { - return getGadgetIds(p); + return getAppWidgetIds(p); } else { return new int[0]; } @@ -641,10 +641,10 @@ class GadgetService extends IGadgetService.Stub XmlResourceParser parser = null; try { parser = activityInfo.loadXmlMetaData(mPackageManager, - GadgetManager.META_DATA_GADGET_PROVIDER); + AppWidgetManager.META_DATA_APPWIDGET_PROVIDER); if (parser == null) { - Log.w(TAG, "No " + GadgetManager.META_DATA_GADGET_PROVIDER + " meta-data for " - + "gadget provider '" + component + '\''); + Log.w(TAG, "No " + AppWidgetManager.META_DATA_APPWIDGET_PROVIDER + " meta-data for " + + "AppWidget provider '" + component + '\''); return null; } @@ -657,30 +657,30 @@ class GadgetService extends IGadgetService.Stub } String nodeName = parser.getName(); - if (!"gadget-provider".equals(nodeName)) { - Log.w(TAG, "Meta-data does not start with gadget-provider tag for" - + " gadget provider '" + component + '\''); + if (!"appwidget-provider".equals(nodeName)) { + Log.w(TAG, "Meta-data does not start with appwidget-provider tag for" + + " AppWidget provider '" + component + '\''); return null; } p = new Provider(); - GadgetProviderInfo info = p.info = new GadgetProviderInfo(); + AppWidgetProviderInfo info = p.info = new AppWidgetProviderInfo(); info.provider = component; p.uid = activityInfo.applicationInfo.uid; TypedArray sa = mContext.getResources().obtainAttributes(attrs, - com.android.internal.R.styleable.GadgetProviderInfo); + com.android.internal.R.styleable.AppWidgetProviderInfo); info.minWidth = sa.getDimensionPixelSize( - com.android.internal.R.styleable.GadgetProviderInfo_minWidth, 0); + com.android.internal.R.styleable.AppWidgetProviderInfo_minWidth, 0); info.minHeight = sa.getDimensionPixelSize( - com.android.internal.R.styleable.GadgetProviderInfo_minHeight, 0); + com.android.internal.R.styleable.AppWidgetProviderInfo_minHeight, 0); info.updatePeriodMillis = sa.getInt( - com.android.internal.R.styleable.GadgetProviderInfo_updatePeriodMillis, 0); + com.android.internal.R.styleable.AppWidgetProviderInfo_updatePeriodMillis, 0); info.initialLayout = sa.getResourceId( - com.android.internal.R.styleable.GadgetProviderInfo_initialLayout, 0); + com.android.internal.R.styleable.AppWidgetProviderInfo_initialLayout, 0); String className = sa.getString( - com.android.internal.R.styleable.GadgetProviderInfo_configure); + com.android.internal.R.styleable.AppWidgetProviderInfo_configure); if (className != null) { info.configure = new ComponentName(component.getPackageName(), className); } @@ -691,7 +691,7 @@ class GadgetService extends IGadgetService.Stub // Ok to catch Exception here, because anything going wrong because // of what a client process passes to us should not be fatal for the // system process. - Log.w(TAG, "XML parsing failed for gadget provider '" + component + '\'', e); + Log.w(TAG, "XML parsing failed for AppWidget provider '" + component + '\'', e); return null; } finally { if (parser != null) parser.close(); @@ -724,15 +724,15 @@ class GadgetService extends IGadgetService.Stub } void sendInitialBroadcasts() { - synchronized (mGadgetIds) { + synchronized (mAppWidgetIds) { final int N = mInstalledProviders.size(); for (int i=0; i<N; i++) { Provider p = mInstalledProviders.get(i); if (p.instances.size() > 0) { sendEnableIntentLocked(p); - int[] gadgetIds = getGadgetIds(p); - sendUpdateIntentLocked(p, gadgetIds); - registerForBroadcastsLocked(p, gadgetIds); + int[] appWidgetIds = getAppWidgetIds(p); + sendUpdateIntentLocked(p, appWidgetIds); + registerForBroadcastsLocked(p, appWidgetIds); } } } @@ -820,11 +820,11 @@ class GadgetService extends IGadgetService.Stub host.tag = i; } - N = mGadgetIds.size(); + N = mAppWidgetIds.size(); for (int i=0; i<N; i++) { - GadgetId id = mGadgetIds.get(i); + AppWidgetId id = mAppWidgetIds.get(i); out.startTag(null, "g"); - out.attribute(null, "id", Integer.toHexString(id.gadgetId)); + out.attribute(null, "id", Integer.toHexString(id.appWidgetId)); out.attribute(null, "h", Integer.toHexString(id.host.tag)); if (id.provider != null) { out.attribute(null, "p", Integer.toHexString(id.provider.tag)); @@ -875,7 +875,7 @@ class GadgetService extends IGadgetService.Stub if (p == null && mSafeMode) { // if we're in safe mode, make a temporary one p = new Provider(); - p.info = new GadgetProviderInfo(); + p.info = new AppWidgetProviderInfo(); p.info.provider = new ComponentName(pkg, cl); p.zombie = true; mInstalledProviders.add(p); @@ -906,10 +906,10 @@ class GadgetService extends IGadgetService.Stub } } else if ("g".equals(tag)) { - GadgetId id = new GadgetId(); - id.gadgetId = Integer.parseInt(parser.getAttributeValue(null, "id"), 16); - if (id.gadgetId >= mNextGadgetId) { - mNextGadgetId = id.gadgetId + 1; + AppWidgetId id = new AppWidgetId(); + id.appWidgetId = Integer.parseInt(parser.getAttributeValue(null, "id"), 16); + if (id.appWidgetId >= mNextAppWidgetId) { + mNextAppWidgetId = id.appWidgetId + 1; } String providerString = parser.getAttributeValue(null, "p"); @@ -920,7 +920,7 @@ class GadgetService extends IGadgetService.Stub int pIndex = Integer.parseInt(providerString, 16); id.provider = loadedProviders.get(pIndex); if (false) { - Log.d(TAG, "bound gadgetId=" + id.gadgetId + " to provider " + Log.d(TAG, "bound appWidgetId=" + id.appWidgetId + " to provider " + pIndex + " which is " + id.provider); } if (id.provider == null) { @@ -941,7 +941,7 @@ class GadgetService extends IGadgetService.Stub id.provider.instances.add(id); } id.host.instances.add(id); - mGadgetIds.add(id); + mAppWidgetIds.add(id); } } } while (type != XmlPullParser.END_DOCUMENT); @@ -973,7 +973,7 @@ class GadgetService extends IGadgetService.Stub } } else { // failed reading, clean up - mGadgetIds.clear(); + mAppWidgetIds.clear(); mHosts.clear(); final int N = mInstalledProviders.size(); for (int i=0; i<N; i++) { @@ -1009,7 +1009,7 @@ class GadgetService extends IGadgetService.Stub } if (Intent.ACTION_PACKAGE_ADDED.equals(action)) { - synchronized (mGadgetIds) { + synchronized (mAppWidgetIds) { Bundle extras = intent.getExtras(); if (extras != null && extras.getBoolean(Intent.EXTRA_REPLACING, false)) { // The package was just upgraded @@ -1026,7 +1026,7 @@ class GadgetService extends IGadgetService.Stub if (extras != null && extras.getBoolean(Intent.EXTRA_REPLACING, false)) { // The package is being updated. We'll receive a PACKAGE_ADDED shortly. } else { - synchronized (mGadgetIds) { + synchronized (mAppWidgetIds) { removeProvidersForPackageLocked(pkgName); saveStateLocked(); } @@ -1039,7 +1039,7 @@ class GadgetService extends IGadgetService.Stub // TODO: If there's a better way of matching an intent filter against the // packages for a given package, use that. void addProvidersForPackageLocked(String pkgName) { - Intent intent = new Intent(GadgetManager.ACTION_GADGET_UPDATE); + Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE); List<ResolveInfo> broadcastReceivers = mPackageManager.queryBroadcastReceivers(intent, PackageManager.GET_META_DATA); @@ -1058,7 +1058,7 @@ class GadgetService extends IGadgetService.Stub // packages for a given package, use that. void updateProvidersForPackageLocked(String pkgName) { HashSet<String> keep = new HashSet(); - Intent intent = new Intent(GadgetManager.ACTION_GADGET_UPDATE); + Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE); List<ResolveInfo> broadcastReceivers = mPackageManager.queryBroadcastReceivers(intent, PackageManager.GET_META_DATA); @@ -1078,24 +1078,24 @@ class GadgetService extends IGadgetService.Stub Provider parsed = parseProviderInfoXml(component, ri); if (parsed != null) { keep.add(ai.name); - // Use the new GadgetProviderInfo. - GadgetProviderInfo oldInfo = p.info; + // Use the new AppWidgetProviderInfo. + AppWidgetProviderInfo oldInfo = p.info; p.info = parsed.info; // If it's enabled final int M = p.instances.size(); if (M > 0) { - int[] gadgetIds = getGadgetIds(p); + int[] appWidgetIds = getAppWidgetIds(p); // Reschedule for the new updatePeriodMillis (don't worry about handling // it specially if updatePeriodMillis didn't change because we just sent // an update, and the next one will be updatePeriodMillis from now). cancelBroadcasts(p); - registerForBroadcastsLocked(p, gadgetIds); - // If it's currently showing, call back with the new GadgetProviderInfo. + registerForBroadcastsLocked(p, appWidgetIds); + // If it's currently showing, call back with the new AppWidgetProviderInfo. for (int j=0; j<M; j++) { - GadgetId id = p.instances.get(j); + AppWidgetId id = p.instances.get(j); if (id.host != null && id.host.callbacks != null) { try { - id.host.callbacks.providerChanged(id.gadgetId, p.info); + id.host.callbacks.providerChanged(id.appWidgetId, p.info); } catch (RemoteException ex) { // It failed; remove the callback. No need to prune because // we know that this host is still referenced by this @@ -1105,7 +1105,7 @@ class GadgetService extends IGadgetService.Stub } } // Now that we've told the host, push out an update. - sendUpdateIntentLocked(p, gadgetIds); + sendUpdateIntentLocked(p, appWidgetIds); } } } @@ -1134,7 +1134,7 @@ class GadgetService extends IGadgetService.Stub // Delete the hosts for this package too // - // By now, we have removed any gadgets that were in any hosts here, + // By now, we have removed any AppWidgets that were in any hosts here, // so we don't need to worry about sending DISABLE broadcasts to them. N = mHosts.size(); for (int i=N-1; i>=0; i--) { diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 77383bd..a629ec6 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -181,7 +181,7 @@ class ServerThread extends Thread { StatusBarService statusBar = null; InputMethodManagerService imm = null; - GadgetService gadget = null; + AppWidgetService appWidget = null; if (factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) { try { @@ -308,11 +308,11 @@ class ServerThread extends Thread { } try { - Log.i(TAG, "Starting Gadget Service"); - gadget = new GadgetService(context); - ServiceManager.addService(Context.GADGET_SERVICE, gadget); + Log.i(TAG, "Starting AppWidget Service"); + appWidget = new AppWidgetService(context); + ServiceManager.addService(Context.APPWIDGET_SERVICE, appWidget); } catch (Throwable e) { - Log.e(TAG, "Failure starting Gadget Service", e); + Log.e(TAG, "Failure starting AppWidget Service", e); } try { @@ -344,8 +344,8 @@ class ServerThread extends Thread { pm.systemReady(); } catch (RemoteException e) { } - if (gadget != null) { - gadget.systemReady(safeMode); + if (appWidget != null) { + appWidget.systemReady(safeMode); } // After making the following code, third party code may be running... diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java index cb16c98..e4bd3c3 100644 --- a/services/java/com/android/server/WindowManagerService.java +++ b/services/java/com/android/server/WindowManagerService.java @@ -1373,10 +1373,9 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo removeWindowInnerLocked(session, win); // Removing a visible window will effect the computed orientation // So just update orientation if needed. - if (wasVisible) { - if (updateOrientationFromAppTokens(null) != null) { - sendNewConfiguration(); - } + if (wasVisible && computeForcedAppOrientationLocked() + != mForcedAppOrientation) { + mH.sendMessage(mH.obtainMessage(H.COMPUTE_AND_SEND_NEW_CONFIGURATION)); } updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL); Binder.restoreCallingIdentity(origId); @@ -2141,23 +2140,19 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo * @see android.view.IWindowManager#updateOrientationFromAppTokens( * android.os.IBinder) */ - public Configuration updateOrientationFromAppTokensLocked( + Configuration updateOrientationFromAppTokensLocked( IBinder freezeThisOneIfNeeded) { boolean changed = false; - Configuration config = null; long ident = Binder.clearCallingIdentity(); try { - int req = getOrientationFromWindowsLocked(); - if (req == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) { - req = getOrientationFromAppTokensLocked(); - } + int req = computeForcedAppOrientationLocked(); if (req != mForcedAppOrientation) { changed = true; mForcedAppOrientation = req; //send a message to Policy indicating orientation change to take //action like disabling/enabling sensors etc., - mPolicy.setCurrentOrientation(req); + mPolicy.setCurrentOrientationLw(req); } if (changed) { @@ -2182,6 +2177,14 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo return null; } + int computeForcedAppOrientationLocked() { + int req = getOrientationFromWindowsLocked(); + if (req == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) { + req = getOrientationFromAppTokensLocked(); + } + return req; + } + public void setAppOrientation(IApplicationToken token, int requestedOrientation) { if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, "setAppOrientation()")) { @@ -3284,7 +3287,7 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo mRequestedRotation = rotation; } if (DEBUG_ORIENTATION) Log.v(TAG, "Overwriting rotation value from " + rotation); - rotation = mPolicy.rotationForOrientation(mForcedAppOrientation, + rotation = mPolicy.rotationForOrientationLw(mForcedAppOrientation, mRotation, mDisplayEnabled); if (DEBUG_ORIENTATION) Log.v(TAG, "new rotation is set to " + rotation); changed = mDisplayEnabled && mRotation != rotation; @@ -4960,7 +4963,7 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo if (holding) { mHoldingScreen.acquire(); } else { - mPolicy.screenOnStopped(); + mPolicy.screenOnStoppedLw(); mHoldingScreen.release(); } } @@ -5290,7 +5293,7 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo synchronized(mWindowMap) { long ident = Binder.clearCallingIdentity(); try { - return mPolicy.performHapticFeedback( + return mPolicy.performHapticFeedbackLw( windowForClientLocked(this, window), effectId, always); } finally { Binder.restoreCallingIdentity(ident); @@ -6944,6 +6947,7 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo public static final int FORCE_GC = 15; public static final int ENABLE_SCREEN = 16; public static final int APP_FREEZE_TIMEOUT = 17; + public static final int COMPUTE_AND_SEND_NEW_CONFIGURATION = 18; private Session mLastReportedHold; @@ -7274,6 +7278,13 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo break; } + case COMPUTE_AND_SEND_NEW_CONFIGURATION: { + if (updateOrientationFromAppTokens(null) != null) { + sendNewConfiguration(); + } + break; + } + } } } diff --git a/tests/AndroidTests/src/com/android/unit_tests/DatabaseGeneralTest.java b/tests/AndroidTests/src/com/android/unit_tests/DatabaseGeneralTest.java index b004c93..d775dc2 100644 --- a/tests/AndroidTests/src/com/android/unit_tests/DatabaseGeneralTest.java +++ b/tests/AndroidTests/src/com/android/unit_tests/DatabaseGeneralTest.java @@ -167,15 +167,6 @@ public class DatabaseGeneralTest extends TestCase implements PerformanceTestCase c.close(); c = mDatabase.query("phones", null, - "PHONE_NUMBERS_EQUAL(num, '+1 (617).555-1212p1234')", null, null, null, null); - assertNotNull(c); - assertEquals(1, c.getCount()); - c.moveToFirst(); - number = c.getString(c.getColumnIndexOrThrow("num")); - assertEquals("+" + PHONE_NUMBER, number); - c.close(); - - c = mDatabase.query("phones", null, "PHONE_NUMBERS_EQUAL(num, '" + PHONE_NUMBER + "')", null, null, null, null); assertNotNull(c); assertEquals(1, c.getCount()); diff --git a/tests/AndroidTests/src/com/android/unit_tests/DatabaseLocaleTest.java b/tests/AndroidTests/src/com/android/unit_tests/DatabaseLocaleTest.java index 0560c21..f07ca7c 100644 --- a/tests/AndroidTests/src/com/android/unit_tests/DatabaseLocaleTest.java +++ b/tests/AndroidTests/src/com/android/unit_tests/DatabaseLocaleTest.java @@ -46,9 +46,13 @@ public class DatabaseLocaleTest extends TestCase { protected void setUp() throws Exception { super.setUp(); mDatabase = SQLiteDatabase.create(null); - mDatabase.execSQL("CREATE TABLE test (data TEXT COLLATE LOCALIZED);"); + mDatabase.execSQL( + "CREATE TABLE test (id INTEGER PRIMARY KEY, data TEXT COLLATE LOCALIZED);"); + } + + private void insertStrings() { for (String s : STRINGS) { - mDatabase.execSQL("INSERT INTO test VALUES('" + s + "');"); + mDatabase.execSQL("INSERT INTO test (data) VALUES('" + s + "');"); } } @@ -75,12 +79,14 @@ public class DatabaseLocaleTest extends TestCase { @MediumTest public void testLocaleInsertOrder() throws Exception { + insertStrings(); String[] results = query("SELECT data FROM test"); MoreAsserts.assertEquals(STRINGS, results); } @MediumTest public void testLocaleenUS() throws Exception { + insertStrings(); Log.i("LocaleTest", "about to call setLocale en_US"); mDatabase.setLocale(new Locale("en", "US")); String[] results; @@ -99,4 +105,25 @@ public class DatabaseLocaleTest extends TestCase { STRINGS[5], // "dog" }); } -} + + @SmallTest + public void testHoge() throws Exception { + Cursor cursor = null; + try { + String expectedString = new String(new int[] {0xFE000}, 0, 1); + mDatabase.execSQL("INSERT INTO test(id, data) VALUES(1, '" + expectedString + "')"); + cursor = mDatabase.rawQuery("SELECT data FROM test WHERE id = 1", null); + + assertNotNull(cursor); + assertTrue(cursor.moveToFirst()); + String actualString = cursor.getString(0); + assertEquals(expectedString.length(), actualString.length()); + for (int i = 0; i < expectedString.length(); i++) { + assertEquals((int)expectedString.charAt(i), (int)actualString.charAt(i)); + } + assertEquals(expectedString, actualString); + } finally { + if (cursor != null) cursor.close(); + } + } +}
\ No newline at end of file diff --git a/tests/gadgets/GadgetHostTest/Android.mk b/tests/appwidgets/AppWidgetHostTest/Android.mk index 5e04b81..1bb1e54 100644 --- a/tests/gadgets/GadgetHostTest/Android.mk +++ b/tests/appwidgets/AppWidgetHostTest/Android.mk @@ -5,7 +5,7 @@ LOCAL_MODULE_TAGS := user LOCAL_SRC_FILES := $(call all-subdir-java-files) -LOCAL_PACKAGE_NAME := GadgetHostTest +LOCAL_PACKAGE_NAME := AppWidgetHostTest LOCAL_CERTIFICATE := platform include $(BUILD_PACKAGE) diff --git a/tests/gadgets/GadgetHostTest/AndroidManifest.xml b/tests/appwidgets/AppWidgetHostTest/AndroidManifest.xml index 52e314f..bf6a7cb 100644 --- a/tests/gadgets/GadgetHostTest/AndroidManifest.xml +++ b/tests/appwidgets/AppWidgetHostTest/AndroidManifest.xml @@ -1,16 +1,16 @@ <manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.android.tests.gadgethost"> + package="com.android.tests.appwidgethost"> <uses-permission android:name="android.permission.VIBRATE" /> <application> - <activity android:name="GadgetHostActivity" android:label="_GadgetHost"> + <activity android:name="AppWidgetHostActivity" android:label="_AppWidgetHost"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> - <activity android:name="TestGadgetConfigure" android:label="Configure TestGadgetProvider"> + <activity android:name="TestAppWidgetConfigure" android:label="Configure TestAppWidgetProvider"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.DEFAULT" /> @@ -18,19 +18,19 @@ </intent-filter> </activity> - <!-- BEGIN_INCLUDE(GadgetProvider) --> - <receiver android:name="TestGadgetProvider" + <!-- BEGIN_INCLUDE(AppWidgetProvider) --> + <receiver android:name="TestAppWidgetProvider" android:label="@string/oh_hai" android:icon="@drawable/oh_hai_icon" > <intent-filter> - <action android:name="android.gadget.action.GADGET_UPDATE" /> + <action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> </intent-filter> - <meta-data android:name="android.gadget.provider" - android:resource="@xml/gadget_info" + <meta-data android:name="android.appwidget.provider" + android:resource="@xml/appwidget_info" /> </receiver> - <!-- END_INCLUDE(GadgetProvider) --> + <!-- END_INCLUDE(AppWidgetProvider) --> </application> </manifest> diff --git a/tests/gadgets/GadgetHostTest/res/drawable/oh_hai_icon.png b/tests/appwidgets/AppWidgetHostTest/res/drawable/oh_hai_icon.png Binary files differindex 30ff267..30ff267 100644 --- a/tests/gadgets/GadgetHostTest/res/drawable/oh_hai_icon.png +++ b/tests/appwidgets/AppWidgetHostTest/res/drawable/oh_hai_icon.png diff --git a/tests/gadgets/GadgetHostTest/res/layout/gadget_host.xml b/tests/appwidgets/AppWidgetHostTest/res/layout/appwidget_host.xml index 743f6c6..e5c3b28 100644 --- a/tests/gadgets/GadgetHostTest/res/layout/gadget_host.xml +++ b/tests/appwidgets/AppWidgetHostTest/res/layout/appwidget_host.xml @@ -22,7 +22,7 @@ <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="@string/gadget_view_title" + android:text="@string/appwidget_view_title" /> <ScrollView @@ -31,8 +31,8 @@ android:layout_weight="1" > - <com.android.tests.gadgethost.GadgetContainerView - android:id="@+id/gadget_container" + <com.android.tests.appwidgethost.AppWidgetContainerView + android:id="@+id/appwidget_container" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" @@ -41,8 +41,8 @@ </ScrollView> <Button - android:id="@+id/add_gadget" - android:text="@string/add_gadget" + android:id="@+id/add_appwidget" + android:text="@string/add_appwidget" android:layout_height="wrap_content" android:layout_width="wrap_content" /> diff --git a/tests/gadgets/GadgetHostTest/res/layout/test_gadget.xml b/tests/appwidgets/AppWidgetHostTest/res/layout/test_appwidget.xml index 4d483c7..4d483c7 100644 --- a/tests/gadgets/GadgetHostTest/res/layout/test_gadget.xml +++ b/tests/appwidgets/AppWidgetHostTest/res/layout/test_appwidget.xml diff --git a/tests/gadgets/GadgetHostTest/res/layout/test_gadget_configure.xml b/tests/appwidgets/AppWidgetHostTest/res/layout/test_appwidget_configure.xml index 0d9b983..0d9b983 100644 --- a/tests/gadgets/GadgetHostTest/res/layout/test_gadget_configure.xml +++ b/tests/appwidgets/AppWidgetHostTest/res/layout/test_appwidget_configure.xml diff --git a/tests/gadgets/GadgetHostTest/res/values/strings.xml b/tests/appwidgets/AppWidgetHostTest/res/values/strings.xml index ad9916a..8a617e7 100644 --- a/tests/gadgets/GadgetHostTest/res/values/strings.xml +++ b/tests/appwidgets/AppWidgetHostTest/res/values/strings.xml @@ -15,10 +15,10 @@ --> <resources> - <string name="gadget_view_title">Gadget Test</string> - <string name="add_gadget">Add Gadget</string> + <string name="appwidget_view_title">Widget Test</string> + <string name="add_appwidget">Add Widget</string> <string name="oh_hai">Oh hai.</string> - <string name="delete_gadget">Delete</string> + <string name="delete_appwidget">Delete</string> <string name="save">Save</string> </resources> diff --git a/tests/appwidgets/AppWidgetHostTest/res/xml/appwidget_info.xml b/tests/appwidgets/AppWidgetHostTest/res/xml/appwidget_info.xml new file mode 100644 index 0000000..f12ba16 --- /dev/null +++ b/tests/appwidgets/AppWidgetHostTest/res/xml/appwidget_info.xml @@ -0,0 +1,10 @@ +<!-- BEGIN_INCLUDE(AppWidgetProviderInfo) --> +<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" + android:minWidth="40dp" + android:minHeight="30dp" + android:updatePeriodMillis="86400000" + android:initialLayout="@layout/test_appwidget" + android:configure="com.android.tests.appwidgethost.TestAppWidgetConfigure" + > +</appwidget-provider> +<!-- END_INCLUDE(AppWidgetProviderInfo) --> diff --git a/tests/gadgets/GadgetHostTest/src/com/android/tests/gadgethost/GadgetContainerView.java b/tests/appwidgets/AppWidgetHostTest/src/com/android/tests/appwidgethost/AppWidgetContainerView.java index 3814836..b08ba52 100644 --- a/tests/gadgets/GadgetHostTest/src/com/android/tests/gadgethost/GadgetContainerView.java +++ b/tests/appwidgets/AppWidgetHostTest/src/com/android/tests/appwidgethost/AppWidgetContainerView.java @@ -14,19 +14,19 @@ * limitations under the License. */ -package com.android.tests.gadgethost; +package com.android.tests.appwidgethost; import android.content.Context; import android.util.AttributeSet; import android.widget.LinearLayout; -public class GadgetContainerView extends LinearLayout +public class AppWidgetContainerView extends LinearLayout { - public GadgetContainerView(Context context) { + public AppWidgetContainerView(Context context) { super(context); } - public GadgetContainerView(Context context, AttributeSet attrs) { + public AppWidgetContainerView(Context context, AttributeSet attrs) { super(context, attrs); } } diff --git a/tests/appwidgets/AppWidgetHostTest/src/com/android/tests/appwidgethost/AppWidgetHostActivity.java b/tests/appwidgets/AppWidgetHostTest/src/com/android/tests/appwidgethost/AppWidgetHostActivity.java new file mode 100644 index 0000000..2fb2d1d --- /dev/null +++ b/tests/appwidgets/AppWidgetHostTest/src/com/android/tests/appwidgethost/AppWidgetHostActivity.java @@ -0,0 +1,198 @@ +/* + * 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.tests.appwidgethost; + +import android.app.Activity; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.appwidget.AppWidgetHost; +import android.appwidget.AppWidgetHostView; +import android.appwidget.AppWidgetProviderInfo; +import android.appwidget.AppWidgetManager; +import android.os.Bundle; +import android.util.Log; +import android.view.ContextMenu; +import android.view.MenuItem; +import android.view.View; +import android.widget.LinearLayout; + +public class AppWidgetHostActivity extends Activity +{ + static final String TAG = "AppWidgetHostActivity"; + + static final int DISCOVER_APPWIDGET_REQUEST = 1; + static final int CONFIGURE_APPWIDGET_REQUEST = 2; + static final int HOST_ID = 1234; + + static final String PENDING_APPWIDGET_ID = "pending_appwidget"; + + AppWidgetManager mAppWidgetManager; + AppWidgetContainerView mAppWidgetContainer; + + public AppWidgetHostActivity() { + mAppWidgetManager = AppWidgetManager.getInstance(this); + } + + @Override + public void onCreate(Bundle icicle) { + super.onCreate(icicle); + setContentView(R.layout.appwidget_host); + + findViewById(R.id.add_appwidget).setOnClickListener(mOnClickListener); + mAppWidgetContainer = (AppWidgetContainerView)findViewById(R.id.appwidget_container); + + if (false) { + if (false) { + mHost.deleteHost(); + } else { + AppWidgetHost.deleteAllHosts(); + } + } + } + + View.OnClickListener mOnClickListener = new View.OnClickListener() { + public void onClick(View v) { + discoverAppWidget(DISCOVER_APPWIDGET_REQUEST); + } + }; + + void discoverAppWidget(int requestCode) { + Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_PICK); + intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mHost.allocateAppWidgetId()); + startActivityForResult(intent, requestCode); + } + + void configureAppWidget(int requestCode, int appWidgetId, ComponentName configure) { + Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_CONFIGURE); + intent.setComponent(configure); + intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId); + SharedPreferences.Editor prefs = getPreferences(0).edit(); + prefs.putInt(PENDING_APPWIDGET_ID, appWidgetId); + prefs.commit(); + startActivityForResult(intent, requestCode); + } + + void handleAppWidgetPickResult(int resultCode, Intent intent) { + // BEGIN_INCLUDE(getExtra_EXTRA_APPWIDGET_ID) + Bundle extras = intent.getExtras(); + int appWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID); + // END_INCLUDE(getExtra_EXTRA_APPWIDGET_ID) + if (resultCode == RESULT_OK) { + AppWidgetProviderInfo appWidget = mAppWidgetManager.getAppWidgetInfo(appWidgetId); + + if (appWidget.configure != null) { + // configure the AppWidget if we should + configureAppWidget(CONFIGURE_APPWIDGET_REQUEST, appWidgetId, appWidget.configure); + } else { + // just add it as is + addAppWidgetView(appWidgetId, appWidget); + } + } else { + mHost.deleteAppWidgetId(appWidgetId); + } + } + + void handleAppWidgetConfigureResult(int resultCode, Intent data) { + int appWidgetId = getPreferences(0).getInt(PENDING_APPWIDGET_ID, -1); + Log.d(TAG, "resultCode=" + resultCode + " appWidgetId=" + appWidgetId); + if (appWidgetId < 0) { + Log.w(TAG, "was no preference for PENDING_APPWIDGET_ID"); + return; + } + if (resultCode == RESULT_OK) { + AppWidgetProviderInfo appWidget = mAppWidgetManager.getAppWidgetInfo(appWidgetId); + addAppWidgetView(appWidgetId, appWidget); + } else { + mHost.deleteAppWidgetId(appWidgetId); + } + } + + void addAppWidgetView(int appWidgetId, AppWidgetProviderInfo appWidget) { + // Inflate the AppWidget's RemoteViews + AppWidgetHostView view = mHost.createView(this, appWidgetId, appWidget); + + // Add it to the list + LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams( + LinearLayout.LayoutParams.FILL_PARENT, + LinearLayout.LayoutParams.WRAP_CONTENT); + mAppWidgetContainer.addView(view, layoutParams); + + registerForContextMenu(view); + } + + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + switch (requestCode) { + case DISCOVER_APPWIDGET_REQUEST: + handleAppWidgetPickResult(resultCode, data); + break; + case CONFIGURE_APPWIDGET_REQUEST: + handleAppWidgetConfigureResult(resultCode, data); + } + } + + protected void onStart() { + super.onStart(); + mHost.startListening(); + } + + protected void onStop() { + super.onStop(); + mHost.stopListening(); + } + + public void onCreateContextMenu(ContextMenu menu, View v, + ContextMenu.ContextMenuInfo menuInfo) { + menu.add(ContextMenu.NONE, R.string.delete_appwidget, ContextMenu.NONE, + R.string.delete_appwidget); + } + + public boolean onContextItemSelected(MenuItem item) { + MyAppWidgetView view = (MyAppWidgetView)item.getMenuInfo(); + switch (item.getItemId()) { + case R.string.delete_appwidget: + Log.d(TAG, "delete! " + view.appWidgetId); + mAppWidgetContainer.removeView(view); + mHost.deleteAppWidgetId(view.appWidgetId); + break; + } + + return true; + } + + class MyAppWidgetView extends AppWidgetHostView implements ContextMenu.ContextMenuInfo { + int appWidgetId; + + MyAppWidgetView(int appWidgetId) { + super(AppWidgetHostActivity.this); + this.appWidgetId = appWidgetId; + } + + public ContextMenu.ContextMenuInfo getContextMenuInfo() { + return this; + } + } + + AppWidgetHost mHost = new AppWidgetHost(this, HOST_ID) { + protected AppWidgetHostView onCreateView(Context context, int appWidgetId, AppWidgetProviderInfo appWidget) { + return new MyAppWidgetView(appWidgetId); + } + }; +} + + diff --git a/tests/gadgets/GadgetHostTest/src/com/android/tests/gadgethost/TestGadgetConfigure.java b/tests/appwidgets/AppWidgetHostTest/src/com/android/tests/appwidgethost/TestAppWidgetConfigure.java index 897c13c..9a6099a 100644 --- a/tests/gadgets/GadgetHostTest/src/com/android/tests/gadgethost/TestGadgetConfigure.java +++ b/tests/appwidgets/AppWidgetHostTest/src/com/android/tests/appwidgethost/TestAppWidgetConfigure.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.tests.gadgethost; +package com.android.tests.appwidgethost; import android.app.Activity; import android.content.Intent; @@ -24,17 +24,17 @@ import android.util.Log; import android.view.View; import android.widget.EditText; -public class TestGadgetConfigure extends Activity { - static final String TAG = "TestGadgetConfigure"; +public class TestAppWidgetConfigure extends Activity { + static final String TAG = "TestAppWidgetConfigure"; - public TestGadgetConfigure() { + public TestAppWidgetConfigure() { super(); } @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); - setContentView(R.layout.test_gadget_configure); + setContentView(R.layout.test_appwidget_configure); findViewById(R.id.save_button).setOnClickListener(mOnClickListener); } @@ -43,9 +43,9 @@ public class TestGadgetConfigure extends Activity { public void onClick(View v) { String text = ((EditText)findViewById(R.id.edit_text)).getText().toString(); Log.d(TAG, "text is '" + text + '\''); - SharedPreferences.Editor prefs = getSharedPreferences(TestGadgetProvider.PREFS_NAME, 0) + SharedPreferences.Editor prefs = getSharedPreferences(TestAppWidgetProvider.PREFS_NAME, 0) .edit(); - prefs.putString(TestGadgetProvider.PREF_PREFIX_KEY, text); + prefs.putString(TestAppWidgetProvider.PREF_PREFIX_KEY, text); prefs.commit(); setResult(RESULT_OK); finish(); diff --git a/tests/gadgets/GadgetHostTest/src/com/android/tests/gadgethost/TestGadgetProvider.java b/tests/appwidgets/AppWidgetHostTest/src/com/android/tests/appwidgethost/TestAppWidgetProvider.java index 370a50b..b5d91d4 100644 --- a/tests/gadgets/GadgetHostTest/src/com/android/tests/gadgethost/TestGadgetProvider.java +++ b/tests/appwidgets/AppWidgetHostTest/src/com/android/tests/appwidgethost/TestAppWidgetProvider.java @@ -14,54 +14,54 @@ * limitations under the License. */ -package com.android.tests.gadgethost; +package com.android.tests.appwidgethost; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; -import android.gadget.GadgetManager; +import android.appwidget.AppWidgetManager; import android.os.Bundle; import android.os.SystemClock; import android.util.Log; import android.widget.RemoteViews; -public class TestGadgetProvider extends BroadcastReceiver { - static final String TAG = "TestGadgetProvider"; +public class TestAppWidgetProvider extends BroadcastReceiver { + static final String TAG = "TestAppWidgetProvider"; - static final String PREFS_NAME = "com.android.tests.gadgethost.TestGadgetProvider"; + static final String PREFS_NAME = "com.android.tests.appwidgethost.TestAppWidgetProvider"; static final String PREF_PREFIX_KEY = "prefix"; public void onReceive(Context context, Intent intent) { String action = intent.getAction(); Log.d(TAG, "intent=" + intent); - if (GadgetManager.ACTION_GADGET_ENABLED.equals(action)) { + if (AppWidgetManager.ACTION_APPWIDGET_ENABLED.equals(action)) { Log.d(TAG, "ENABLED"); } - else if (GadgetManager.ACTION_GADGET_DISABLED.equals(action)) { + else if (AppWidgetManager.ACTION_APPWIDGET_DISABLED.equals(action)) { Log.d(TAG, "DISABLED"); } - else if (GadgetManager.ACTION_GADGET_UPDATE.equals(action)) { + else if (AppWidgetManager.ACTION_APPWIDGET_UPDATE.equals(action)) { Log.d(TAG, "UPDATE"); - // BEGIN_INCLUDE(getExtra_EXTRA_GADGET_IDS) + // BEGIN_INCLUDE(getExtra_EXTRA_APPWIDGET_IDS) Bundle extras = intent.getExtras(); - int[] gadgetIds = extras.getIntArray(GadgetManager.EXTRA_GADGET_IDS); - // END_INCLUDE(getExtra_EXTRA_GADGET_IDS) + int[] appWidgetIds = extras.getIntArray(AppWidgetManager.EXTRA_APPWIDGET_IDS); + // END_INCLUDE(getExtra_EXTRA_APPWIDGET_IDS) SharedPreferences prefs = context.getSharedPreferences( - TestGadgetProvider.PREFS_NAME, 0); + TestAppWidgetProvider.PREFS_NAME, 0); String prefix = prefs.getString(PREF_PREFIX_KEY, "hai"); - GadgetManager gm = GadgetManager.getInstance(context); - RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.test_gadget); + AppWidgetManager gm = AppWidgetManager.getInstance(context); + RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.test_appwidget); views.setTextViewText(R.id.oh_hai_text, prefix + ": " + SystemClock.elapsedRealtime()); if (false) { - gm.updateGadget(gadgetIds, views); + gm.updateAppWidget(appWidgetIds, views); } else { - gm.updateGadget(new ComponentName("com.android.tests.gadgethost", - "com.android.tests.gadgethost.TestGadgetProvider"), views); + gm.updateAppWidget(new ComponentName("com.android.tests.appwidgethost", + "com.android.tests.appwidgethost.TestAppWidgetProvider"), views); } } } diff --git a/tests/gadgets/GadgetProviderTest/Android.mk b/tests/appwidgets/AppWidgetProviderTest/Android.mk index b9bfcdb..c87a0f2 100644 --- a/tests/gadgets/GadgetProviderTest/Android.mk +++ b/tests/appwidgets/AppWidgetProviderTest/Android.mk @@ -5,7 +5,7 @@ LOCAL_MODULE_TAGS := user LOCAL_SRC_FILES := $(call all-subdir-java-files) -LOCAL_PACKAGE_NAME := GadgetProvider +LOCAL_PACKAGE_NAME := AppWidgetProvider LOCAL_CERTIFICATE := platform include $(BUILD_PACKAGE) diff --git a/tests/appwidgets/AppWidgetProviderTest/AndroidManifest.xml b/tests/appwidgets/AppWidgetProviderTest/AndroidManifest.xml new file mode 100644 index 0000000..ec4d583 --- /dev/null +++ b/tests/appwidgets/AppWidgetProviderTest/AndroidManifest.xml @@ -0,0 +1,13 @@ +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.tests.appwidgetprovider"> + <uses-permission android:name="android.permission.VIBRATE" /> + + <application> + <receiver android:name="TestAppWidgetProvider"> + <intent-filter> + <action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> + </intent-filter> + <meta-data android:name="android.appwidget.provider" android:resource="@xml/appwidget_info" /> + </receiver> + </application> +</manifest> diff --git a/tests/gadgets/GadgetProviderTest/res/layout/test_gadget.xml b/tests/appwidgets/AppWidgetProviderTest/res/layout/test_appwidget.xml index e0a416e..e0a416e 100644 --- a/tests/gadgets/GadgetProviderTest/res/layout/test_gadget.xml +++ b/tests/appwidgets/AppWidgetProviderTest/res/layout/test_appwidget.xml diff --git a/tests/gadgets/GadgetProviderTest/res/values/strings.xml b/tests/appwidgets/AppWidgetProviderTest/res/values/strings.xml index e07725f..e51299b 100644 --- a/tests/gadgets/GadgetProviderTest/res/values/strings.xml +++ b/tests/appwidgets/AppWidgetProviderTest/res/values/strings.xml @@ -15,9 +15,9 @@ --> <resources> - <string name="gadget_view_title">Gadget Test</string> - <string name="add_gadget">Add Gadget</string> + <string name="appwidget_view_title">Widget Test</string> + <string name="add_appwidget">Add Widget</string> <string name="oh_hai">Oh hai.</string> - <string name="delete_gadget">Delete</string> + <string name="delete_appwidget">Delete</string> </resources> diff --git a/tests/appwidgets/AppWidgetProviderTest/res/xml/appwidget_info.xml b/tests/appwidgets/AppWidgetProviderTest/res/xml/appwidget_info.xml new file mode 100644 index 0000000..c133743 --- /dev/null +++ b/tests/appwidgets/AppWidgetProviderTest/res/xml/appwidget_info.xml @@ -0,0 +1,7 @@ +<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" + android:minWidth="150dp" + android:minHeight="150dp" + android:updatePeriodMillis="2000" + android:initialLayout="@layout/test_appwidget" + > +</appwidget-provider> diff --git a/tests/gadgets/GadgetProviderTest/src/com/android/tests/gadgetprovider/TestGadgetProvider.java b/tests/appwidgets/AppWidgetProviderTest/src/com/android/tests/appwidgetprovider/TestAppWidgetProvider.java index b81575f..418be65 100644 --- a/tests/gadgets/GadgetProviderTest/src/com/android/tests/gadgetprovider/TestGadgetProvider.java +++ b/tests/appwidgets/AppWidgetProviderTest/src/com/android/tests/appwidgetprovider/TestAppWidgetProvider.java @@ -14,45 +14,45 @@ * limitations under the License. */ -package com.android.tests.gadgetprovider; +package com.android.tests.appwidgetprovider; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; -import android.gadget.GadgetManager; +import android.appwidget.AppWidgetManager; import android.os.Bundle; import android.os.SystemClock; import android.util.Log; import android.widget.RemoteViews; -public class TestGadgetProvider extends BroadcastReceiver { +public class TestAppWidgetProvider extends BroadcastReceiver { - static final String TAG = "TestGadgetProvider"; + static final String TAG = "TestAppWidgetProvider"; public void onReceive(Context context, Intent intent) { String action = intent.getAction(); Log.d(TAG, "intent=" + intent); - if (GadgetManager.ACTION_GADGET_ENABLED.equals(action)) { + if (AppWidgetManager.ACTION_APPWIDGET_ENABLED.equals(action)) { Log.d(TAG, "ENABLED"); } - else if (GadgetManager.ACTION_GADGET_DISABLED.equals(action)) { + else if (AppWidgetManager.ACTION_APPWIDGET_DISABLED.equals(action)) { Log.d(TAG, "DISABLED"); } - else if (GadgetManager.ACTION_GADGET_UPDATE.equals(action)) { + else if (AppWidgetManager.ACTION_APPWIDGET_UPDATE.equals(action)) { Log.d(TAG, "UPDATE"); Bundle extras = intent.getExtras(); - int[] gadgetIds = extras.getIntArray(GadgetManager.EXTRA_GADGET_IDS); + int[] appWidgetIds = extras.getIntArray(AppWidgetManager.EXTRA_APPWIDGET_IDS); - GadgetManager gm = GadgetManager.getInstance(context); - RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.test_gadget); + AppWidgetManager gm = AppWidgetManager.getInstance(context); + RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.test_appwidget); views.setTextViewText(R.id.oh_hai_text, "hai: " + SystemClock.elapsedRealtime()); if (false) { - gm.updateGadget(gadgetIds, views); + gm.updateAppWidget(appWidgetIds, views); } else { - gm.updateGadget(new ComponentName("com.android.tests.gadgetprovider", - "com.android.tests.gadgetprovider.TestGadgetProvider"), views); + gm.updateAppWidget(new ComponentName("com.android.tests.appwidgetprovider", + "com.android.tests.appwidgetprovider.TestAppWidgetProvider"), views); } } } diff --git a/tests/gadgets/GadgetHostTest/res/xml/gadget_info.xml b/tests/gadgets/GadgetHostTest/res/xml/gadget_info.xml deleted file mode 100644 index e0c4222..0000000 --- a/tests/gadgets/GadgetHostTest/res/xml/gadget_info.xml +++ /dev/null @@ -1,10 +0,0 @@ -<!-- BEGIN_INCLUDE(GadgetProviderInfo) --> -<gadget-provider xmlns:android="http://schemas.android.com/apk/res/android" - android:minWidth="40dp" - android:minHeight="30dp" - android:updatePeriodMillis="86400000" - android:initialLayout="@layout/test_gadget" - android:configure="com.android.tests.gadgethost.TestGadgetConfigure" - > -</gadget-provider> -<!-- END_INCLUDE(GadgetProviderInfo) --> diff --git a/tests/gadgets/GadgetHostTest/src/com/android/tests/gadgethost/GadgetHostActivity.java b/tests/gadgets/GadgetHostTest/src/com/android/tests/gadgethost/GadgetHostActivity.java deleted file mode 100644 index 0bd8926..0000000 --- a/tests/gadgets/GadgetHostTest/src/com/android/tests/gadgethost/GadgetHostActivity.java +++ /dev/null @@ -1,198 +0,0 @@ -/* - * 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.tests.gadgethost; - -import android.app.Activity; -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.SharedPreferences; -import android.gadget.GadgetHost; -import android.gadget.GadgetHostView; -import android.gadget.GadgetProviderInfo; -import android.gadget.GadgetManager; -import android.os.Bundle; -import android.util.Log; -import android.view.ContextMenu; -import android.view.MenuItem; -import android.view.View; -import android.widget.LinearLayout; - -public class GadgetHostActivity extends Activity -{ - static final String TAG = "GadgetHostActivity"; - - static final int DISCOVER_GADGET_REQUEST = 1; - static final int CONFIGURE_GADGET_REQUEST = 2; - static final int HOST_ID = 1234; - - static final String PENDING_GADGET_ID = "pending_gadget"; - - GadgetManager mGadgetManager; - GadgetContainerView mGadgetContainer; - - public GadgetHostActivity() { - mGadgetManager = GadgetManager.getInstance(this); - } - - @Override - public void onCreate(Bundle icicle) { - super.onCreate(icicle); - setContentView(R.layout.gadget_host); - - findViewById(R.id.add_gadget).setOnClickListener(mOnClickListener); - mGadgetContainer = (GadgetContainerView)findViewById(R.id.gadget_container); - - if (false) { - if (false) { - mHost.deleteHost(); - } else { - GadgetHost.deleteAllHosts(); - } - } - } - - View.OnClickListener mOnClickListener = new View.OnClickListener() { - public void onClick(View v) { - discoverGadget(DISCOVER_GADGET_REQUEST); - } - }; - - void discoverGadget(int requestCode) { - Intent intent = new Intent(GadgetManager.ACTION_GADGET_PICK); - intent.putExtra(GadgetManager.EXTRA_GADGET_ID, mHost.allocateGadgetId()); - startActivityForResult(intent, requestCode); - } - - void configureGadget(int requestCode, int gadgetId, ComponentName configure) { - Intent intent = new Intent(GadgetManager.ACTION_GADGET_CONFIGURE); - intent.setComponent(configure); - intent.putExtra(GadgetManager.EXTRA_GADGET_ID, gadgetId); - SharedPreferences.Editor prefs = getPreferences(0).edit(); - prefs.putInt(PENDING_GADGET_ID, gadgetId); - prefs.commit(); - startActivityForResult(intent, requestCode); - } - - void handleGadgetPickResult(int resultCode, Intent intent) { - // BEGIN_INCLUDE(getExtra_EXTRA_GADGET_ID) - Bundle extras = intent.getExtras(); - int gadgetId = extras.getInt(GadgetManager.EXTRA_GADGET_ID); - // END_INCLUDE(getExtra_EXTRA_GADGET_ID) - if (resultCode == RESULT_OK) { - GadgetProviderInfo gadget = mGadgetManager.getGadgetInfo(gadgetId); - - if (gadget.configure != null) { - // configure the gadget if we should - configureGadget(CONFIGURE_GADGET_REQUEST, gadgetId, gadget.configure); - } else { - // just add it as is - addGadgetView(gadgetId, gadget); - } - } else { - mHost.deleteGadgetId(gadgetId); - } - } - - void handleGadgetConfigureResult(int resultCode, Intent data) { - int gadgetId = getPreferences(0).getInt(PENDING_GADGET_ID, -1); - Log.d(TAG, "resultCode=" + resultCode + " gadgetId=" + gadgetId); - if (gadgetId < 0) { - Log.w(TAG, "was no preference for PENDING_GADGET_ID"); - return; - } - if (resultCode == RESULT_OK) { - GadgetProviderInfo gadget = mGadgetManager.getGadgetInfo(gadgetId); - addGadgetView(gadgetId, gadget); - } else { - mHost.deleteGadgetId(gadgetId); - } - } - - void addGadgetView(int gadgetId, GadgetProviderInfo gadget) { - // Inflate the gadget's RemoteViews - GadgetHostView view = mHost.createView(this, gadgetId, gadget); - - // Add it to the list - LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams( - LinearLayout.LayoutParams.FILL_PARENT, - LinearLayout.LayoutParams.WRAP_CONTENT); - mGadgetContainer.addView(view, layoutParams); - - registerForContextMenu(view); - } - - protected void onActivityResult(int requestCode, int resultCode, Intent data) { - switch (requestCode) { - case DISCOVER_GADGET_REQUEST: - handleGadgetPickResult(resultCode, data); - break; - case CONFIGURE_GADGET_REQUEST: - handleGadgetConfigureResult(resultCode, data); - } - } - - protected void onStart() { - super.onStart(); - mHost.startListening(); - } - - protected void onStop() { - super.onStop(); - mHost.stopListening(); - } - - public void onCreateContextMenu(ContextMenu menu, View v, - ContextMenu.ContextMenuInfo menuInfo) { - menu.add(ContextMenu.NONE, R.string.delete_gadget, ContextMenu.NONE, - R.string.delete_gadget); - } - - public boolean onContextItemSelected(MenuItem item) { - MyGadgetView view = (MyGadgetView)item.getMenuInfo(); - switch (item.getItemId()) { - case R.string.delete_gadget: - Log.d(TAG, "delete! " + view.gadgetId); - mGadgetContainer.removeView(view); - mHost.deleteGadgetId(view.gadgetId); - break; - } - - return true; - } - - class MyGadgetView extends GadgetHostView implements ContextMenu.ContextMenuInfo { - int gadgetId; - - MyGadgetView(int gadgetId) { - super(GadgetHostActivity.this); - this.gadgetId = gadgetId; - } - - public ContextMenu.ContextMenuInfo getContextMenuInfo() { - return this; - } - } - - GadgetHost mHost = new GadgetHost(this, HOST_ID) { - protected GadgetHostView onCreateView(Context context, int gadgetId, GadgetProviderInfo gadget) { - return new MyGadgetView(gadgetId); - } - }; -} - - diff --git a/tests/gadgets/GadgetProviderTest/AndroidManifest.xml b/tests/gadgets/GadgetProviderTest/AndroidManifest.xml deleted file mode 100644 index 47a7a2e..0000000 --- a/tests/gadgets/GadgetProviderTest/AndroidManifest.xml +++ /dev/null @@ -1,13 +0,0 @@ -<manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.android.tests.gadgetprovider"> - <uses-permission android:name="android.permission.VIBRATE" /> - - <application> - <receiver android:name="TestGadgetProvider"> - <intent-filter> - <action android:name="android.gadget.action.GADGET_UPDATE" /> - </intent-filter> - <meta-data android:name="android.gadget.provider" android:resource="@xml/gadget_info" /> - </receiver> - </application> -</manifest> diff --git a/tests/gadgets/GadgetProviderTest/res/xml/gadget_info.xml b/tests/gadgets/GadgetProviderTest/res/xml/gadget_info.xml deleted file mode 100644 index 33cc2e3..0000000 --- a/tests/gadgets/GadgetProviderTest/res/xml/gadget_info.xml +++ /dev/null @@ -1,7 +0,0 @@ -<gadget-provider xmlns:android="http://schemas.android.com/apk/res/android" - android:minWidth="150dp" - android:minHeight="150dp" - android:updatePeriodMillis="2000" - android:initialLayout="@layout/test_gadget" - > -</gadget-provider> |