summaryrefslogtreecommitdiffstats
path: root/core/java
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2009-03-11 12:11:56 -0700
committerThe Android Open Source Project <initial-contribution@android.com>2009-03-11 12:11:56 -0700
commitc39a6e0c51e182338deb8b63d07933b585134929 (patch)
treee55fc5bd38b1eb8fb4851a0fe1cc264a7fe2f245 /core/java
parentb2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54 (diff)
downloadframeworks_base-c39a6e0c51e182338deb8b63d07933b585134929.zip
frameworks_base-c39a6e0c51e182338deb8b63d07933b585134929.tar.gz
frameworks_base-c39a6e0c51e182338deb8b63d07933b585134929.tar.bz2
auto import from //branches/cupcake/...@137873
Diffstat (limited to 'core/java')
-rw-r--r--core/java/android/app/SearchDialog.java26
-rw-r--r--core/java/android/appwidget/AppWidgetHost.java (renamed from core/java/android/gadget/GadgetHost.java)99
-rw-r--r--core/java/android/appwidget/AppWidgetHostView.java (renamed from core/java/android/gadget/GadgetHostView.java)44
-rw-r--r--core/java/android/appwidget/AppWidgetManager.java320
-rwxr-xr-xcore/java/android/appwidget/AppWidgetProvider.java154
-rw-r--r--core/java/android/appwidget/AppWidgetProviderInfo.aidl (renamed from core/java/android/gadget/GadgetProviderInfo.aidl)4
-rw-r--r--core/java/android/appwidget/AppWidgetProviderInfo.java (renamed from core/java/android/gadget/GadgetProviderInfo.java)66
-rw-r--r--core/java/android/appwidget/package.html136
-rw-r--r--core/java/android/content/Context.java4
-rw-r--r--core/java/android/content/Intent.java10
-rw-r--r--core/java/android/content/res/ColorStateList.java1
-rw-r--r--core/java/android/gadget/GadgetManager.java320
-rwxr-xr-xcore/java/android/gadget/GadgetProvider.java154
-rw-r--r--core/java/android/gadget/package.html136
-rw-r--r--core/java/android/inputmethodservice/ExtractButton.java30
-rw-r--r--core/java/android/inputmethodservice/InputMethodService.java11
-rw-r--r--core/java/android/provider/Contacts.java37
-rw-r--r--core/java/android/provider/Gmail.java10
-rw-r--r--core/java/android/server/BluetoothA2dpService.java9
-rw-r--r--core/java/android/server/BluetoothDeviceService.java1
-rw-r--r--core/java/android/server/BluetoothEventLoop.java12
-rw-r--r--core/java/android/text/method/QwertyKeyListener.java6
-rw-r--r--core/java/android/view/View.java19
-rw-r--r--core/java/android/view/ViewDebug.java376
-rw-r--r--core/java/android/view/WindowManagerPolicy.java10
-rw-r--r--core/java/android/view/inputmethod/InputMethodInfo.java8
-rw-r--r--core/java/android/view/inputmethod/InputMethodManager.java1
-rw-r--r--core/java/android/webkit/LoadListener.java9
-rw-r--r--core/java/android/webkit/TextDialog.java4
-rw-r--r--core/java/android/webkit/WebSettings.java8
-rw-r--r--core/java/android/webkit/WebView.java329
-rw-r--r--core/java/android/webkit/WebViewCore.java6
-rw-r--r--core/java/android/widget/AbsListView.java17
-rw-r--r--core/java/android/widget/ArrayAdapter.java13
-rw-r--r--core/java/android/widget/AutoCompleteTextView.java14
-rw-r--r--core/java/android/widget/ListView.java24
-rw-r--r--core/java/android/widget/PopupWindow.java2
-rw-r--r--core/java/android/widget/RelativeLayout.java21
-rw-r--r--core/java/android/widget/SlidingDrawer.java14
-rw-r--r--core/java/android/widget/TextView.java3
-rw-r--r--core/java/android/widget/VideoView.java16
-rw-r--r--core/java/android/widget/ZoomButtonsController.java71
-rw-r--r--core/java/com/android/internal/appwidget/IAppWidgetHost.aidl (renamed from core/java/com/android/internal/gadget/IGadgetHost.aidl)10
-rw-r--r--core/java/com/android/internal/appwidget/IAppWidgetService.aidl (renamed from core/java/com/android/internal/gadget/IGadgetService.aidl)32
-rw-r--r--core/java/com/android/internal/appwidget/package.html (renamed from core/java/com/android/internal/gadget/package.html)0
-rw-r--r--core/java/com/android/internal/widget/NumberPicker.java37
46 files changed, 1476 insertions, 1158 deletions
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>&lt;gadget-provider&gt;</code> xml tag.
+ * Describes the meta data for an installed AppWidget provider. The fields in this class
+ * correspond to the fields in the <code>&lt;appwidget-provider&gt;</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>&lt;receiver&gt;</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>&lt;receiver&gt;</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>&lt;intent-filter&gt;</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>&lt;meta-data&gt;</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 &gt;
+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>&lt;receiver&gt;</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>&lt;intent-filter&gt;</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>&lt;meta-data&gt;</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 &gt;
-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);
}
}