Merge "Changing startListening to only fetch views which are bound" into nyc-dev

This commit is contained in:
Sunny Goyal
2016-04-05 18:53:17 +00:00
committed by Android (Google) Code Review
3 changed files with 63 additions and 31 deletions

View File

@@ -17,8 +17,7 @@
package android.appwidget;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -35,7 +34,9 @@ import android.os.Message;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
import android.util.DisplayMetrics;
import android.util.SparseArray;
import android.util.TypedValue;
import android.widget.RemoteViews;
import android.widget.RemoteViews.OnClickHandler;
@@ -62,7 +63,7 @@ public class AppWidgetHost {
private final Handler mHandler;
private final int mHostId;
private final Callbacks mCallbacks;
private final HashMap<Integer,AppWidgetHostView> mViews = new HashMap<>();
private final SparseArray<AppWidgetHostView> mViews = new SparseArray<>();
private OnClickHandler mOnClickHandler;
static class Callbacks extends IAppWidgetHost.Stub {
@@ -164,7 +165,6 @@ public class AppWidgetHost {
bindService();
}
private static void bindService() {
synchronized (sServiceLock) {
if (sService == null) {
@@ -179,17 +179,25 @@ public class AppWidgetHost {
* becomes visible, i.e. from onStart() in your Activity.
*/
public void startListening() {
int[] updatedIds;
ArrayList<RemoteViews> updatedViews = new ArrayList<RemoteViews>();
final int[] idsToUpdate;
synchronized (mViews) {
int N = mViews.size();
idsToUpdate = new int[N];
for (int i = 0; i < N; i++) {
idsToUpdate[i] = mViews.keyAt(i);
}
}
List<RemoteViews> updatedViews;
int[] updatedIds = new int[idsToUpdate.length];
try {
updatedIds = sService.startListening(mCallbacks, mContextOpPackageName, mHostId,
updatedViews);
updatedViews = sService.startListening(
mCallbacks, mContextOpPackageName, mHostId, idsToUpdate, updatedIds).getList();
}
catch (RemoteException e) {
throw new RuntimeException("system server dead?", e);
}
final int N = updatedIds.length;
int N = updatedViews.size();
for (int i = 0; i < N; i++) {
updateAppWidgetView(updatedIds[i], updatedViews.get(i));
}
@@ -206,10 +214,6 @@ public class AppWidgetHost {
catch (RemoteException e) {
throw new RuntimeException("system server dead?", e);
}
// This is here because keyguard needs it since it'll be switching users after this call.
// If it turns out other apps need to call this often, we should re-think how this works.
clearViews();
}
/**
@@ -418,7 +422,9 @@ public class AppWidgetHost {
* Clear the list of Views that have been created by this AppWidgetHost.
*/
protected void clearViews() {
mViews.clear();
synchronized (mViews) {
mViews.clear();
}
}
}

View File

@@ -33,8 +33,8 @@ interface IAppWidgetService {
//
// for AppWidgetHost
//
int[] startListening(IAppWidgetHost host, String callingPackage, int hostId,
out List<RemoteViews> updatedViews);
ParceledListSlice startListening(IAppWidgetHost host, String callingPackage, int hostId,
in int[] appWidgetIds, out int[] updatedIds);
void stopListening(String callingPackage, int hostId);
int allocateAppWidgetId(String callingPackage, int hostId);
void deleteAppWidgetId(String callingPackage, int appWidgetId);

View File

@@ -744,8 +744,8 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
}
@Override
public int[] startListening(IAppWidgetHost callbacks, String callingPackage,
int hostId, List<RemoteViews> updatedViews) {
public ParceledListSlice<RemoteViews> startListening(IAppWidgetHost callbacks,
String callingPackage, int hostId, int[] appWidgetIds, int[] updatedIds) {
final int userId = UserHandle.getCallingUserId();
if (DEBUG) {
@@ -762,21 +762,21 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
// sure the caller can only access hosts it owns.
HostId id = new HostId(Binder.getCallingUid(), hostId, callingPackage);
Host host = lookupOrAddHostLocked(id);
host.callbacks = callbacks;
updatedViews.clear();
ArrayList<Widget> instances = host.widgets;
int N = instances.size();
int[] updatedIds = new int[N];
int N = appWidgetIds.length;
ArrayList<RemoteViews> outViews = new ArrayList<>(N);
RemoteViews rv;
int added = 0;
for (int i = 0; i < N; i++) {
Widget widget = instances.get(i);
updatedIds[i] = widget.appWidgetId;
updatedViews.add(cloneIfLocalBinder(widget.getEffectiveViewsLocked()));
rv = host.getPendingViewsForId(appWidgetIds[i]);
if (rv != null) {
updatedIds[added] = appWidgetIds[i];
outViews.add(rv);
added++;
}
}
return updatedIds;
return new ParceledListSlice<>(outViews);
}
}
@@ -1884,6 +1884,10 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
}
private void scheduleNotifyUpdateAppWidgetLocked(Widget widget, RemoteViews updateViews) {
long requestTime = SystemClock.uptimeMillis();
if (widget != null) {
widget.lastUpdateTime = requestTime;
}
if (widget == null || widget.provider == null || widget.provider.zombie
|| widget.host.callbacks == null || widget.host.zombie) {
return;
@@ -1893,6 +1897,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
args.arg1 = widget.host;
args.arg2 = widget.host.callbacks;
args.arg3 = updateViews;
args.arg4 = requestTime;
args.argi1 = widget.appWidgetId;
mCallbackHandler.obtainMessage(
@@ -1901,9 +1906,10 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
}
private void handleNotifyUpdateAppWidget(Host host, IAppWidgetHost callbacks,
int appWidgetId, RemoteViews views) {
int appWidgetId, RemoteViews views, long requestTime) {
try {
callbacks.updateAppWidget(appWidgetId, views);
host.lastWidgetUpdateTime = requestTime;
} catch (RemoteException re) {
synchronized (mLock) {
Slog.e(TAG, "Widget host dead: " + host.id, re);
@@ -3400,10 +3406,11 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
Host host = (Host) args.arg1;
IAppWidgetHost callbacks = (IAppWidgetHost) args.arg2;
RemoteViews views = (RemoteViews) args.arg3;
long requestTime = (Long) args.arg4;
final int appWidgetId = args.argi1;
args.recycle();
handleNotifyUpdateAppWidget(host, callbacks, appWidgetId, views);
handleNotifyUpdateAppWidget(host, callbacks, appWidgetId, views, requestTime);
} break;
case MSG_NOTIFY_PROVIDER_CHANGED: {
@@ -3771,6 +3778,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
boolean zombie; // if we're in safe mode, don't prune this just because nobody references it
int tag = TAG_UNDEFINED; // for use while saving state (the index)
long lastWidgetUpdateTime; // last time we were successfully able to send an update.
public int getUserId() {
return UserHandle.getUserId(id.uid);
@@ -3792,6 +3800,23 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
return false;
}
/**
* Returns the RemoveViews for the provided widget id if an update is pending
* for that widget.
*/
public RemoteViews getPendingViewsForId(int appWidgetId) {
long updateTime = lastWidgetUpdateTime;
int N = widgets.size();
for (int i = 0; i < N; i++) {
Widget widget = widgets.get(i);
if (widget.appWidgetId == appWidgetId
&& widget.lastUpdateTime > updateTime) {
return cloneIfLocalBinder(widget.getEffectiveViewsLocked());
}
}
return null;
}
@Override
public String toString() {
return "Host{" + id + (zombie ? " Z" : "") + '}';
@@ -3862,6 +3887,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
RemoteViews maskedViews;
Bundle options;
Host host;
long lastUpdateTime;
@Override
public String toString() {