summaryrefslogtreecommitdiffstats
path: root/services/java/com/android/server/AppWidgetService.java
diff options
context:
space:
mode:
Diffstat (limited to 'services/java/com/android/server/AppWidgetService.java')
-rw-r--r--services/java/com/android/server/AppWidgetService.java75
1 files changed, 42 insertions, 33 deletions
diff --git a/services/java/com/android/server/AppWidgetService.java b/services/java/com/android/server/AppWidgetService.java
index 59a540b..ad25657 100644
--- a/services/java/com/android/server/AppWidgetService.java
+++ b/services/java/com/android/server/AppWidgetService.java
@@ -22,6 +22,7 @@ import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
+import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
@@ -62,6 +63,7 @@ import android.os.Process;
import android.os.RemoteException;
import android.os.SystemClock;
import android.util.AttributeSet;
+import android.util.Log;
import android.util.Pair;
import android.util.Slog;
import android.util.TypedValue;
@@ -121,18 +123,15 @@ class AppWidgetService extends IAppWidgetService.Stub
* globally and may lead us to leak AppWidgetService instances (if there were more than one).
*/
static class ServiceConnectionProxy implements ServiceConnection {
- private final AppWidgetService mAppWidgetService;
private final Pair<Integer, Intent.FilterComparison> mKey;
private final IBinder mConnectionCb;
- ServiceConnectionProxy(AppWidgetService appWidgetService,
- Pair<Integer, Intent.FilterComparison> key, IBinder connectionCb) {
- mAppWidgetService = appWidgetService;
+ ServiceConnectionProxy(Pair<Integer, Intent.FilterComparison> key, IBinder connectionCb) {
mKey = key;
mConnectionCb = connectionCb;
}
public void onServiceConnected(ComponentName name, IBinder service) {
- IRemoteViewsAdapterConnection cb =
+ final IRemoteViewsAdapterConnection cb =
IRemoteViewsAdapterConnection.Stub.asInterface(mConnectionCb);
try {
cb.onServiceConnected(service);
@@ -141,19 +140,13 @@ class AppWidgetService extends IAppWidgetService.Stub
}
}
public void onServiceDisconnected(ComponentName name) {
- IRemoteViewsAdapterConnection cb =
+ disconnect();
+ }
+ public void disconnect() {
+ final IRemoteViewsAdapterConnection cb =
IRemoteViewsAdapterConnection.Stub.asInterface(mConnectionCb);
try {
cb.onServiceDisconnected();
- mAppWidgetService.mServiceConnectionUpdateHandler.post(new Runnable() {
- public void run() {
- // We don't want to touch mBoundRemoteViewsServices from any other thread
- // so queue this to run on the main thread.
- if (mAppWidgetService.mBoundRemoteViewsServices.containsKey(mKey)) {
- mAppWidgetService.mBoundRemoteViewsServices.remove(mKey);
- }
- }
- });
} catch (RemoteException e) {
e.printStackTrace();
}
@@ -163,7 +156,6 @@ class AppWidgetService extends IAppWidgetService.Stub
// Manages connections to RemoteViewsServices
private final HashMap<Pair<Integer, FilterComparison>, ServiceConnection>
mBoundRemoteViewsServices = new HashMap<Pair<Integer,FilterComparison>,ServiceConnection>();
- private final Handler mServiceConnectionUpdateHandler = new Handler();
Context mContext;
Locale mLocale;
@@ -456,13 +448,24 @@ class AppWidgetService extends IAppWidgetService.Stub
throw new IllegalArgumentException("Unknown component " + componentName);
}
- // Bind to the RemoteViewsService (which will trigger a callback to the
- // RemoteViewsAdapter)
+ // If there is already a connection made for this service intent, then disconnect from
+ // that first. (This does not allow multiple connections to the same service under
+ // the same key)
+ ServiceConnectionProxy conn = null;
Pair<Integer, FilterComparison> key = Pair.create(appWidgetId,
new FilterComparison(intent));
- final ServiceConnection conn = new ServiceConnectionProxy(this, key, connection);
+ if (mBoundRemoteViewsServices.containsKey(key)) {
+ conn = (ServiceConnectionProxy) mBoundRemoteViewsServices.get(key);
+ conn.disconnect();
+ mContext.unbindService(conn);
+ mBoundRemoteViewsServices.remove(key);
+ }
+
+ // Bind to the RemoteViewsService (which will trigger a callback to the
+ // RemoteViewsAdapter.onServiceConnected())
final long token = Binder.clearCallingIdentity();
try {
+ conn = new ServiceConnectionProxy(key, connection);
mContext.bindService(intent, conn, Context.BIND_AUTO_CREATE);
mBoundRemoteViewsServices.put(key, conn);
} finally {
@@ -473,37 +476,43 @@ class AppWidgetService extends IAppWidgetService.Stub
public void unbindRemoteViewsService(int appWidgetId, Intent intent) {
synchronized (mAppWidgetIds) {
- AppWidgetId id = lookupAppWidgetIdLocked(appWidgetId);
- if (id == null) {
- throw new IllegalArgumentException("bad appWidgetId");
- }
-
// Unbind from the RemoteViewsService (which will trigger a callback to the bound
// RemoteViewsAdapter)
Pair<Integer, FilterComparison> key = Pair.create(appWidgetId,
new FilterComparison(intent));
if (mBoundRemoteViewsServices.containsKey(key)) {
- final ServiceConnection conn = mBoundRemoteViewsServices.get(key);
- mBoundRemoteViewsServices.remove(key);
- conn.onServiceDisconnected(null);
+ // We don't need to use the appWidgetId until after we are sure there is something
+ // to unbind. Note that this may mask certain issues with apps calling unbind()
+ // more than necessary.
+ AppWidgetId id = lookupAppWidgetIdLocked(appWidgetId);
+ if (id == null) {
+ throw new IllegalArgumentException("bad appWidgetId");
+ }
+
+ ServiceConnectionProxy conn =
+ (ServiceConnectionProxy) mBoundRemoteViewsServices.get(key);
+ conn.disconnect();
mContext.unbindService(conn);
+ mBoundRemoteViewsServices.remove(key);
+ } else {
+ Log.e("AppWidgetService", "Error (unbindRemoteViewsService): Connection not bound");
}
}
}
private void unbindAppWidgetRemoteViewsServicesLocked(AppWidgetId id) {
+ int appWidgetId = id.appWidgetId;
+ // Unbind all connections to Services bound to this AppWidgetId
Iterator<Pair<Integer, Intent.FilterComparison>> it =
mBoundRemoteViewsServices.keySet().iterator();
- int appWidgetId = id.appWidgetId;
-
- // Unbind all connections to AppWidgets bound to this id
while (it.hasNext()) {
final Pair<Integer, Intent.FilterComparison> key = it.next();
if (key.first.intValue() == appWidgetId) {
- final ServiceConnection conn = mBoundRemoteViewsServices.get(key);
- it.remove();
- conn.onServiceDisconnected(null);
+ final ServiceConnectionProxy conn = (ServiceConnectionProxy)
+ mBoundRemoteViewsServices.get(key);
+ conn.disconnect();
mContext.unbindService(conn);
+ it.remove();
}
}
}